Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / January 2005

Tip: Looking for answers? Try searching our database.

Marshalling pointer to pointer to interface

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Nauman - 12 Jan 2005 17:38 GMT
I would like to call a method in an unmanaged C dll from C# using
VS2003. However, I haven't been able to
successfully do this so far. I am hoping that someone can help me get
this working.

The method signature for the C function is:
HRESULT __stdcall FuncFromCDll(ISomeInterface** ppISomeInterface)

Here is what I've tried:
1)
[DllImport("somedll.DLL", EntryPoint="FuncFromCDll", ExactSpelling=
true, CallingConvention=CallingConvention.StdCall)]
public static extern void FuncFromCDll(ref IntPtr ppISomeInterface);

I then called the above as shown below:

IntPtr myIntPtr = IntPtr.Zero;
FuncFromCDll(ref myIntPtr);
object myObject = Marshal.GetObjectForIUnknown(myIntPtr);

This successfully calls FuncFromCDll. (I confirmed by debugging into
the code above that myIntPtr has a non-zero value after the
FuncFromCDll call.) However, it fails in Marshal.GetObjectForIUnknown
call giving a
System.ExecutionEngineException. Note that ISomeInterface does derive
from IUnknown.

Don't know why but if I initialize myIntPtr as IntPtr myIntPtr = new
IntPtr(300) or some other
non-zero value, then the call to FuncFromCDll fails causing the
application to immediate shut down -- I guess it might
be because IntPtr is pointer to a memory location and we don't know
what is at memory location that we are pointing to when we assign it a
non-zero value.

2) I tried using IntPtr instead of ref IntPtr.
[DllImport("somedll.DLL", EntryPoint="FuncFromCDll", ExactSpelling=
true, CallingConvention=CallingConvention.StdCall)]
public static extern void FuncFromCDll(IntPtr ppISomeInterface);

I then called the above as shown below:

IntPtr myIntPtr = IntPtr.Zero;
FuncFromCDll(myIntPtr);
object myObject = Marshal.GetObjectForIUnknown(myIntPtr);

This fails in FuncFromCDll call with "Object reference not set to an
instance of an object" error.

3) I tried a variation of (1) above using ref Object instead of ref
IntPtr in my P/Invoke call.
I got an error in FuncFromCDll call saying that "Specified OLE variant
is invalid."

4) I also tried the code below which was suggested in the following
thread:
http://groups-beta.google.com/group/microsoft.public.dotnet.framework.interop/br
owse_thread/thread/a1becfa8dc6d46aa/434911737fb7ad58?q=%22pointer+to+a+pointer%2
2&_done=%2Fgroup%2Fmicrosoft.public.dotnet.framework.interop%2Fsearch%3Fgroup%3D
microsoft.public.dotnet.framework.interop%26q%3D%22pointer+to+a+pointer%22%26qt_
g%3D1%26&_doneTitle=Back+to+Search&&d#434911737fb7ad58


[DllImport("somedll.DLL")]
public static extern void FuncFromCDll(
[MarshalAs(UnmanagedType.Interface)]
out ISomeInterface ppISomeInterface);

//Defined ISomeInterface interface in C#
[
ComImport,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("12345678-1234-4323-7878-984783787873")
]
public interface ISomeInterface
{
//Defined placeholders for all the methods on this
//interface
void Method1();
void Method2();
...
}

ISomeInterface someInterface;
FuncFromCDll(out someInterface);

The call to FuncFromCDll fails giving
System.ExecutionEngineException.

I've spent quite a lot of time looking at the newsgroups and websites
(including MSDN) trying to find a solution to this problem, with no
luck.
Any ideas on what else I can try or where I can find examples of how to
do this?

Thanks!
Nauman
Dragomir Stoichev - 12 Jan 2005 17:43 GMT
[DllImport("somedll.DLL", EntryPoint="FuncFromCDll",
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern void FuncFromCDll(
[MarshalAs( UnmanagedType.Interface )]
out object ppISomeInterface
);

object myObject;
FuncFromCDll( out myObject );
Nauman - 12 Jan 2005 17:54 GMT
Thanks for your suggestion Dragomir. It is similar to trial number (3)
in my original question....only difference was that I tried "ref"
object instead of "out" object. I gave your suggestion a try but it
didn't work for me.
I get the same error with out object as I got with ref object.  Error
is "Specified OLE variant
is invalid".

Nauman
Alessandro Angeli [MVP::DigitalMedia] - 12 Jan 2005 17:51 GMT
> The method signature for the C function is:
> HRESULT __stdcall FuncFromCDll(ISomeInterface**
> ppISomeInterface)

What about the following?

[DllImport("somedll.dll"
 ,EntryPoint="FuncFromCDll"
 ,ExactSpelling=true
 ,PreserveSig=false
 ,CharSet=CharSet.Ansi
 ,CallingConvention=CallingConvention.StdCall
)]
[return: MarshalAs(UnmanagedType.Interface)]
public static extern object FuncFromCDll();

Signature

// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net

Nauman - 12 Jan 2005 18:33 GMT
> What about the following?
>
[quoted text clipped - 7 lines]
>  [return: MarshalAs(UnmanagedType.Interface)]
>  public static extern object FuncFromCDll();

I was simplifying the c function in my question since I thought the
rest of the signature would unnecessarily complicate the question that
I have. Maybe I need to provide more information. The signature
actually is more like below:
HRESULT __stdcall FuncFromCDll(ISomeInterfaceCallback* pCallBack, void*
pUserData, ISomeInterface** ppISomeInterface, int reserved);

In C, I could make this call as follows and it works:
ISomeInterface* someInterface = 0;
CreateInstance(0, (void *) 0, &someInterface , 0);

I was trying to use the following:
[DllImport("somedll.DLL", EntryPoint="FuncFromCDll",
ExactSpelling= true,
CallingConvention=CallingConvention.StdCall)]
public static extern object FuncFromCDll(
IntPtr pISomeInterfaceCallback,
IntPtr pUserData,
ref IntPtr ppISomeInterface,
int lReserved);

I was calling this as below:
IntPtr pISomeInterfaceCallback = IntPtr.Zero;
IntPtr pUserData = IntPtr.Zero;
IntPtr myIntPtr = IntPtr.Zero;
FuncFromCDll(pISomeInterfaceCallback, pUserData, ref myIntPtr, 0);
object myObject = Marshal.GetObjectForIUnknown(myIntPtr);

Would I still be able to define the P/Invoke call similar to what you
described above for this case?
i.e.
[DllImport("somedll.DLL", EntryPoint="FuncFromCDll",
ExactSpelling= false, PreserveSig=false,
CharSet=CharSet.Ansi,
CallingConvention=CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Interface)]
public static extern object FuncFromCDll(
IntPtr pISomeInterfaceCallback,
IntPtr pUserData,
//??removed ppISomeInterface since it is returned??
int lReserved);

If the above P/Invoke is a valid one, then I have tried it and I got an
"Object reference not set to an instance of an object" exception.
Thanks for your help!
Nauman
Alessandro Angeli [MVP::DigitalMedia] - 12 Jan 2005 19:08 GMT
> Would I still be able to define the P/Invoke call similar
> to what you described above for this case?

I haven't yet found out what attribute defines a retval
which is not the last one.

I tried this in a test program and it works:

[DllImport("somedll.dll"
 ,EntryPoint="FuncFromCDll"
 ,ExactSpelling=true
 ,PreserveSig=true
 ,CharSet=CharSet.Ansi
 ,CallingConvention=CallingConvention.StdCall
)]
public static extern int FuncFromCDll(
 [MarshalAs(UnmanagedType.Interface)]
   object pCallBack,
 IntPtr pUserData,
 [MarshalAs(UnmanagedType.Interface)]
   out object ppISomeInterface,
 int reserved
);

object pISomeInterface;
int hr = FuncFromCDll
   (null,IntPtr.Zero,out pISomeInterface,0);

Signature

// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net

Alessandro Angeli [MVP::DigitalMedia] - 12 Jan 2005 19:28 GMT
> I haven't yet found out what attribute defines a retval
> which is not the last one.

Well, I found the answer: the retval *must* be the last
param.

Signature

// Alessandro Angeli
// MVP :: Digital Media
// a dot angeli at psynet dot net


Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.