473,567 Members | 3,176 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

C++/CLI : How do I hold a reference to Native pointer in a Ref Class

/*

Hi,

I am trying to hold a reference to un-managed pointer IStorage.
The client/callers will make many accesses to IStorage, but
only in-directly. For performance reasons IStorage needs to be
opened once, and a reference held by MyClass for duration of session.

1. Should I use a native class to do the native stuff?
2. Should I use pin_ptr?
3. Is it possible to correct the error message in MyClass?

Please suggest to me the best way to accomplish this.

Russell Mangel
Las Vegas, NV

PS.
Thanks for your assistance.

This project is a C++/CLI CLR Class Library, a DLL for use by C#, and VB.Net
clients.

When you create a CLR Class Library project do the following:
Under Linker, Input, Additional Dependencies, remove $(NoInherit).

*/
#pragma once
using namespace System;

#define WIN32_LEAN_AND_ MEAN
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <ole2.h>

namespace MyNameSpace
{
public ref class MyClass
{
private:
// This line causes an error:
IStorage *pStorage;
// C2440: 'reinterpret_ca st' : cannot convert from 'cli::interior_ ptr<Type>'
to 'IStorage **'

public:
int Open()
{
HRESULT hr = S_OK;
// IStorage *pStorage = NULL;
hr = StgOpenStorage(
L"C:\\AnyMSOffi ceDocument.doc" ,
NULL,STGM_READ | STGM_SHARE_DENY _WRITE,
NULL,
NULL,
reinterpret_cas t <IStorage**>(&p Storage) );

return hr;
}
};
}
Dec 24 '06 #1
7 8101
Russell Mangel wrote:
/*

Hi,

I am trying to hold a reference to un-managed pointer IStorage.
The client/callers will make many accesses to IStorage, but
only in-directly. For performance reasons IStorage needs to be
opened once, and a reference held by MyClass for duration of session.

1. Should I use a native class to do the native stuff?
Most of it, yes.
2. Should I use pin_ptr?
No. That's for converting a managed pointer to a native one. To hold onto
a native pointer in a managed class, simply cast it to a suitably-sized
integer (int on x86 or __int64 on x64/IA64).

3. Is it possible to correct the error message in MyClass?
Yes.

int pStorage;

int Open()
{
HRESULT hr = S_OK;
hr = StgOpenStorage(
L"C:\\AnyMSOffi ceDocument.doc" ,
NULL,STGM_READ | STGM_SHARE_DENY _WRITE,
NULL,
NULL,
reinterpret_cas t <IStorage**>(&p Storage)
);

return hr;
}

Naturally, when you need to access the storage, you'll need to
reinterpret_cas t the int back to IStorage*. Be sure you remember to Release
that pointer! That probably means that your managed class should be both
IDisposable and have a finalizer. That's automatic in C++/CLI if you simply
declare a destructor.

-cd
Dec 24 '06 #2
Carl, thanks for your reply.

I tried to compile #3, but I get the same error message:
Error 1 error C2440: 'reinterpret_ca st' : cannot convert from
'cli::interior_ ptr<Type>' to 'IStorage **'

MyClass needs to hold a reference to IStorage for the duration of the
session.
MyClass will have several other methods, which need the IStorage pointer
to do more work.

Example: C# Client:

// C# Client Code
MyClass myClass = new MyClass("C:\\14 .msg");

// Client calls Open()
Int32 hr = myClass.Open();

// Client now calls GetRootElements ()
// This method uses the private IStorage pointer
// which was previously created by Open()
foreach (Element element in myClass.GetRoot Elements())
{
Console.WriteLi ne(element.Name );
}

// Cleanup IStorage
myClass.Dispose ();
What am I missing here?

Russell Mangel
Las Vegas, NV


Dec 25 '06 #3
Russell Mangel wrote:
Carl, thanks for your reply.

I tried to compile #3, but I get the same error message:
Error 1 error C2440: 'reinterpret_ca st' : cannot convert from
'cli::interior_ ptr<Type>' to 'IStorage **'
Oh sorry - you have to use a local variable as an intermediary - the
compiler won't let you cast the address of a member variable, not even for
the duration of a single function call. You can probably do it with a
pin_ptr as well, but that still takes an intermediary, so I don't see how
that's any better.
public ref class MyClass
{
private:
int m_pStorage;

~MyClass()
{
if (m_pStorage)
reinterpret_cas t<IStorage*>(m_ pStorage)->Release();
}

public:
int Open()
{
int pStorage; // local intermediary
HRESULT hr = S_OK;
hr = StgOpenStorage(
L"C:\\AnyMSOffi ceDocument.doc" ,
NULL,STGM_READ | STGM_SHARE_DENY _WRITE,
NULL,
NULL,
reinterpret_cas t <IStorage**>(&p Storage)
);

if (SUCCEEDED(hr))
m_pStorage = pStorage;

return hr;
}
};

-cd
Dec 25 '06 #4
Holy Christmas, its working!

1. As far as my brain can think, there shouldn't be any problem with the
garbage collector moving around the pointer:
m_pStorage; right? Even if the GC moves the managed int (pointer) around it
will still point to the Native memory. All I have to do
is make sure that I cleanup the Native memory so I don't cause a memory
leak, right?

2. Why do I have to use a System::Int32 for the pointer. I tried to use a
System::Intptr for this , I couldn't make it work, but maybe I did something
wrong?

Thanks for your help.

Russell Mangel
Las Vegas, NV

PS

Merry Christmas!

Additonally:
I can't think of another way to do this, than the solution you have given
me. Reason: Structured Storage documents are just like a file
system right? And so they can have any number of Storages (Directories), and
so I am forced to hold a reference to the IStorage native memory. I have
another version of this contraption working using a Native Class, this was
pretty easy, but it falls apart once you try to open nested IStorage
Storages, I would be forced to track all the IStorage native pointers in the
Native class, and this seems harder to do.



Dec 25 '06 #5
Russell Mangel wrote:
Holy Christmas, its working!

1. As far as my brain can think, there shouldn't be any problem with
the garbage collector moving around the pointer:
m_pStorage; right? Even if the GC moves the managed int (pointer)
around it will still point to the Native memory. All I have to do
is make sure that I cleanup the Native memory so I don't cause a
memory leak, right?
Right.
>
2. Why do I have to use a System::Int32 for the pointer. I tried to
use a System::Intptr for this , I couldn't make it work, but maybe I
did something wrong?
I would think that IntPtr should work as well - it's just an integer type
sized to match the size of a native pointer on the host platform.
>
Thanks for your help.

Russell Mangel
Las Vegas, NV

PS

Merry Christmas!

Additonally:
I can't think of another way to do this, than the solution you have
given me. Reason: Structured Storage documents are just like a file
system right? And so they can have any number of Storages
(Directories), and so I am forced to hold a reference to the IStorage
native memory. I have another version of this contraption working
using a Native Class, this was pretty easy, but it falls apart once
you try to open nested IStorage Storages, I would be forced to track
all the IStorage native pointers in the Native class, and this seems
harder to do.
Yes, you need to keep a reference to the outermost IStorage open - closing
it will close the file and cause any IStorage interfaces you may be holding
on nested storages to become invalid.

-cd
Dec 26 '06 #6

"Russell Mangel" <ru*****@tymer. netwrote in message
news:Op******** ******@TK2MSFTN GP02.phx.gbl...
Holy Christmas, its working!

1. As far as my brain can think, there shouldn't be any problem with the
garbage collector moving around the pointer:
m_pStorage; right? Even if the GC moves the managed int (pointer) around
it
Except while StgOpenStorage is running, because it writes to m_pStorage.
You must give StgOpenStorage the address of a pointer in non-GC-managed
memory. This means either pinned, or on the stack.
will still point to the Native memory. All I have to do
is make sure that I cleanup the Native memory so I don't cause a memory
leak, right?

2. Why do I have to use a System::Int32 for the pointer. I tried to use a
System::Intptr for this , I couldn't make it work, but maybe I did
something wrong?
Carl has given you 3 horribly broken solutions to your simple problem.
Casting is not the answer. Use a local variable of the correct type:

IStorage *pStorage = NULL;
hr = StgOpenStorage(
L"C:\\AnyMSOffi ceDocument.doc" ,
NULL,STGM_READ | STGM_SHARE_DENY _WRITE,
NULL,
NULL,
&pStorage);
this->pStorage = pStorage;
>
Thanks for your help.

Russell Mangel
Las Vegas, NV

PS

Merry Christmas!

Additonally:
I can't think of another way to do this, than the solution you have given
me. Reason: Structured Storage documents are just like a file
system right? And so they can have any number of Storages (Directories),
and so I am forced to hold a reference to the IStorage native memory. I
have another version of this contraption working using a Native Class,
this was pretty easy, but it falls apart once you try to open nested
IStorage Storages, I would be forced to track all the IStorage native
pointers in the Native class, and this seems harder to do.



Dec 26 '06 #7
Hi, it was very nice of you to help me with my question, thanks.

I changed my code to use an IStorage pointer, and it seems to be working.

However, my source code has changed a little from the beginning of this post
could you take a look at it now and see if I have any problems. As you can
see by my source code I simply open a docfile, and then I pass the managed
IStorage pointer to the constuctor of the Managed Class StorageInfo, this
Manged class has a destructor that releases the managed pointer.

I am still concerned because your previous statement.
Ben Voigt <Wrote>
"You must give StgOpenStorage the address of a pointer in non-GC-managed
memory. This means either pinned, or on the stack."

SSCore::IStorag eInfo ^SSCore::Functi ons::StgOpenSto rage(String ^fileName)
{
pin_ptr<const wchar_tpinnedFI lename = PtrToStringChar s(fileName);

HRESULT hr = S_OK;
IStorage *pNativeStorage = NULL;

hr = ::StgOpenStorag e(
pinnedFIlename,
NULL,
STGM_READ | STGM_SHARE_DENY _WRITE,
NULL,
0,
reinterpret_cas t <IStorage**>(&p NativeStorage) );

if(hr != S_OK)
{
Error::ThrowExc eption(hr, "StgOpenStorage ");
}
else
{
StorageInfo ^storageInfo = gcnew StorageInfo(pNa tiveStorage);
return storageInfo;
}
}

//
// Here is destructor for StorageInfo
//
SSCore::Storage Info::~StorageI nfo()
{
// m_pStorage is a Native IStorage type which was passed into the
constructor
// by the previous code.
if(m_pStorage)
{
m_pStorage->Release();
}
}

// End Source Code
Dec 28 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
9975
by: Kent | last post by:
Hi! I am working with an obscure graphics library in school as a university C++ programming project. The graphics library has a class kalled Bitmap wich you use to draw graphics (you can "stamp it down" on the screen, double buffering and such is all within the lib). This is how it works now (i think its a bad design): In a class i...
4
1997
by: Don Kim | last post by:
I have the following code: using namespace System; ref class R { public: R() {
2
2312
by: Martin Zenkel | last post by:
Dear VS Team, using the Beta 2 of VS 2005 I've encontered the following problem. Let's assume threre are three Dll's, one unmanaged and two managed. In the unmanaged we put a simple unmanged struct "A" which is exported in the usual way. The first managed assembly defines a managed class "B" using the unmanaged class "A" defined in the...
1
2541
by: Scott McFadden | last post by:
What is the proper way to pass pointers by reference from managed c++ calls to native c++ calls? In managed C++, I have a pointer to an array of structures, that I pass to a native c++ method by reference: //Managed c++ QueryResult* qr = NULL; ExecuteQuery(1, "abc", qr); //invoke native c++ method passing qr by reference
14
7522
by: Ben Voigt | last post by:
Under certain circumstances I get: First-chance exception at 0x7c812a5b (kernel32.dll) in LTMGUI.exe: 0xC0020001: The string binding is invalid. First-chance exception at 0x7c812a5b (kernel32.dll) in LTMGUI.exe: Microsoft C++ exception: at memory location 0x00000000.. Unhandled exception at 0x7c812a5b (kernel32.dll) in LTMGUI.exe:...
2
1939
by: Andreas Schmitt | last post by:
Crazy idea but... I think everyone could agree with the statement that the CLI standard Base Class Library is incredibly useful, not to mention the extentions by microsoft and managed directX and several other stuff that builds on top of the BCL. Now.. do you think it would be possible to port the BCL to C++? Meaning starting with an...
0
1419
by: DaTurk | last post by:
Hi, I need to have a native class hold on to a managed function pointer. Not a unmanaged class in a manged block. I mean an unmanaged class in an unmanaged block via #pragma unmanaged. I'm wondering if GCHandle will be enough. I can't use gcroot because it's a #pragma unmananged so if I declare a gcrooted variable ...
0
1339
by: Ed | last post by:
Hi, dear all, I want to wrapper the legacy C++ Template Class to be used by the C# code, so I try to wrapper the legacy C++ code into CLI/C++ code first. One problem is how to wrapper C++ template class, such as List, Queue, etc? Here is a snippet of Native Code: //Native code:
275
12113
by: Astley Le Jasper | last post by:
Sorry for the numpty question ... How do you find the reference name of an object? So if i have this bob = modulename.objectname() how do i find that the name is 'bob'
0
7588
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7903
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
1
7650
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7959
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6272
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5488
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3630
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1205
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
930
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.