How to marshall "pointer to pointer"

X

Xinjie ZHANG

I use a third-party C library in my .NET CF application. The method signature for one of the C functions is:
int PlaceInstance( U32 Handle, U16 ParticleID, U16 Layer, char* InstanceName, SFLOAT X, SFLOAT Y, char* Path, char** DstPath );
In C++ applications, it can be called like this:

PlaceInstance(handle, 123, 222, "name", 10, 50, NULL, NULL)

I have tried many ways to make it work, but unfortunately, I can not :(

public static extern int PlaceInstance( uint Handle, ushort ParticleID, ushort Layer, string InstanceName, float X, float Y, string Path, out StringBuilder DstPath );
call ==>
StringBuilder builder = new StringBuilder(1024);
PlaceInstance(handle, 123, 222, "name", 10, 50, null, out builder)

public static unsafe extern int PlaceInstance( uint Handle, ushort ParticleID, ushort Layer, string InstanceName, float X, float Y, char* Path, char** DstPath );
call ==> PlaceInstance(handle, 123, 222, "name", 10, 50, (char*)0, (char**)0)

public static unsafe extern int PlaceInstance( uint Handle, ushort ParticleID, ushort Layer, string InstanceName, float X, float Y, byte* Path, byte** DstPath );
call ==> PlaceInstance(handle, 123, 222, "name", 10, 50, (byte*)0, (byte**)0)

public static extern int PlaceInstance( uint Handle, ushort ParticleID, ushort Layer, string InstanceName, float X, float Y, IntPtr Path, out IntPtr DstPath );
call ==>
IntPtr ptr = IntPtr.Zero;
PlaceInstance(handle, 123, 222, "name", 10, 50, IntPtr.Zero, out ptr )

They always fail in PlaceInstance call with "Object reference not set to an instance of an object" error. It makes me crazy :( Could anyone helps me out? Thanks !
 
I

Ilya Tumanov [MS]

Please try this:

public static extern Int32 PlaceInstance( UInt32 Handle, UInt16 ParticleID,
UInt16 Layer, Byte[] InstanceName, float X, float Y, Byte[] Path, IntPtr
DstPath );

Call it as follows:

PlaceInstance(handle, 123, 222, Encoding.ASCII.GetBytes("name"), 10, 50,
null, IntPtr.Zero);

Note you can's pass strings. Strings are unicode and your DLL seems to
expect ASCII.

If you're expecting DstPath back, you would have to pass an instance of
IntPtr.
After call is done, cast it to Int32*, get value at this pointer, cast it to
IntPtr and pass it it Marshal.PtrToStringBSTR() to get this string.

Best regards,

Ilya
This posting is provided "AS IS" with no warranties, and confers no rights.

I use a third-party C library in my .NET CF application. The method
signature for one of the C functions is:
int PlaceInstance( U32 Handle, U16 ParticleID, U16 Layer, char*
InstanceName, SFLOAT X, SFLOAT Y, char* Path, char** DstPath );
In C++ applications, it can be called like this:

PlaceInstance(handle, 123, 222, "name", 10, 50, NULL, NULL)

I have tried many ways to make it work, but unfortunately, I can not :(

public static extern int PlaceInstance( uint Handle, ushort ParticleID,
ushort Layer, string InstanceName, float X, float Y, string Path, out
StringBuilder DstPath );
call ==>
StringBuilder builder = new StringBuilder(1024);
PlaceInstance(handle, 123, 222, "name", 10, 50, null, out builder)

public static unsafe extern int PlaceInstance( uint Handle, ushort
ParticleID, ushort Layer, string InstanceName, float X, float Y, char* Path,
char** DstPath );
call ==> PlaceInstance(handle, 123, 222, "name", 10, 50, (char*)0,
(char**)0)

public static unsafe extern int PlaceInstance( uint Handle, ushort
ParticleID, ushort Layer, string InstanceName, float X, float Y, byte* Path,
byte** DstPath );
call ==> PlaceInstance(handle, 123, 222, "name", 10, 50, (byte*)0,
(byte**)0)

public static extern int PlaceInstance( uint Handle, ushort ParticleID,
ushort Layer, string InstanceName, float X, float Y, IntPtr Path, out IntPtr
DstPath );
call ==>
IntPtr ptr = IntPtr.Zero;
PlaceInstance(handle, 123, 222, "name", 10, 50, IntPtr.Zero, out ptr )

They always fail in PlaceInstance call with "Object reference not set to an
instance of an object" error. It makes me crazy :( Could anyone helps me
out? Thanks !
 
A

Alex Feinman [MVP]

There is no way a P/Invoke can produce NullReferenceException. It has to occur on the previous line of code. Recheck your code.
As for the P/Invoke definition, the last one is correct, but if you don't care about the returned value for DstPath, you should simply define it as int and pass 0 as Ilya points out.

Regarding the string recovery from the pointer returned to you, I'd use Marshal.PtrToStringUni

--
Alex Feinman
---
Visit http://www.opennetcf.org
I use a third-party C library in my .NET CF application. The method signature for one of the C functions is:
int PlaceInstance( U32 Handle, U16 ParticleID, U16 Layer, char* InstanceName, SFLOAT X, SFLOAT Y, char* Path, char** DstPath );
In C++ applications, it can be called like this:

PlaceInstance(handle, 123, 222, "name", 10, 50, NULL, NULL)

I have tried many ways to make it work, but unfortunately, I can not :(

public static extern int PlaceInstance( uint Handle, ushort ParticleID, ushort Layer, string InstanceName, float X, float Y, string Path, out StringBuilder DstPath );
call ==>
StringBuilder builder = new StringBuilder(1024);
PlaceInstance(handle, 123, 222, "name", 10, 50, null, out builder)

public static unsafe extern int PlaceInstance( uint Handle, ushort ParticleID, ushort Layer, string InstanceName, float X, float Y, char* Path, char** DstPath );
call ==> PlaceInstance(handle, 123, 222, "name", 10, 50, (char*)0, (char**)0)

public static unsafe extern int PlaceInstance( uint Handle, ushort ParticleID, ushort Layer, string InstanceName, float X, float Y, byte* Path, byte** DstPath );
call ==> PlaceInstance(handle, 123, 222, "name", 10, 50, (byte*)0, (byte**)0)

public static extern int PlaceInstance( uint Handle, ushort ParticleID, ushort Layer, string InstanceName, float X, float Y, IntPtr Path, out IntPtr DstPath );
call ==>
IntPtr ptr = IntPtr.Zero;
PlaceInstance(handle, 123, 222, "name", 10, 50, IntPtr.Zero, out ptr )

They always fail in PlaceInstance call with "Object reference not set to an instance of an object" error. It makes me crazy :( Could anyone helps me out? Thanks !
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top