P/Invoke and **struct

  • Thread starter Thread starter Gary Desrosiers
  • Start date Start date
G

Gary Desrosiers

Anyone have an example of calling DLL functions that take a pointer to a
pointer to a struct. In C it would be:

some_struct_t *param;
func(&param);

in C#, I've got:

[StructLayout(LayoutKind.Sequential)]
public struct ppStruct
{
public IntPtr ptr;
}
public class libwrapper
{
[DllImport("my.dll")]
public static extern void func([MarshalAs(UnmanagedType.LPStruct)]ppStruct
param);
}

Then I try:

ppStruct param = new ppStruct();
IntPtr ppParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(param));
Marshal.StructureToPtr(param,ppParam,false);
func(param);

Nothing seems to work, I've been looking for a good (working) example.
 
Gary Desrosiers said:
Anyone have an example of calling DLL functions that take a pointer to a
pointer to a struct. In C it would be:

some_struct_t *param;
func(&param);

in C#, I've got:

[StructLayout(LayoutKind.Sequential)]
public struct ppStruct
{
public IntPtr ptr;
}
public class libwrapper
{
[DllImport("my.dll")]
public static extern void func([MarshalAs(UnmanagedType.LPStruct)]ppStruct
param);
}

Then I try:

ppStruct param = new ppStruct();
IntPtr ppParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(param));
Marshal.StructureToPtr(param,ppParam,false);
func(param);

Nothing seems to work, I've been looking for a good (working) example.

Don't marshal the "param" to the func as an LPStruct, pass it as
a ref IntPtr.

[DllImport("my.dll")]
private static extern void func(ref IntPtr structPtr);

....

IntPtr ptr = IntPtr.Zero;
try
{
ppStruct param = new ppStruct();
Marshal.AllocHGlobal(param, ptr, true);

func( ref ptr );

param = Marshal.PtrToStructure(ptr, typeof(ppStruct));
}
finally
{
if( ptr != IntPtr.Zero )
{
Marshal.FreeHGlobal(ptr);
}
}


My only concern is, the only reason to pass a pointer to
a pointer is if you plan on changing the original pointer.

This could lead to a memory leak because what happens
to the original pointer?

In the example I showed you, there could be a critical
flaw if func() changes the pointer because the pointer
returned may not be freeable by Marshal.FreeHGlobal()
and the pointer you originally Alloc'd is unretrievable.

It all depends on exactly what func() is doing.

-c
 
Thanks!, that worked. The func() actually sets the IntPtr passed to memory
within itself and the kernel and shouldn't be free'd/FreeHGlobal'ed. func()
manages the memory. We just get to look at it. The only thing I should need
to FreeCoTaskMem now is the IntPtr being passed. I'm going to assume that if
I Marshal.PtrToStructure() something being returned, that garbage collection
will eventually remove the stucture referenced. But maybe that's a bad
assumption.
 
Back
Top