Passing delegates in structure to C dll

R

renjini

I am a starter in C# ...

I will present my problem :

I am wrapping a C dll in C#. The C dll exports a function which takes a
structure MYSTRUCT holding 2 function pointers(callback functions).

struct MYSTRUCT
{
ontest1 t1;
ontest2 t2
};
where ontest1 and ontest2 are two function pointers.

In C# dll, I have declared this structure as

[StructLayout(LayoutKind.Sequential)]
public struct MYSTRUCT
{
[MarshalAs(UnmanagedType.FunctionPtr)]
ontest1 t1;
[MarshalAs(UnmanagedType.FunctionPtr)]
ontest2 t2
}

where ontest1 and ontest2 are two delegates.


//Importing the C dll function "MyFunctions"

[DllImport("mydll.dll")]
IntPtr MyFunctions(IntPtr myStruct);

//The .NET function wrapping the above function :

IntPtr MyFunctions1(ref MYSTRUCT mystruct)
{
//Converts MYSTRUCT to pointer
GCHandle callbackHandle = GCHandle.Alloc
(mystruct ,GCHandleType.Pinned);

IntPtr mystructptr = callbackHandle.AddrOfPinnedObject();

//Calls the imported C dll function
IntPtr handle = MyFunctions(mystructptr);

return handle;
}


The address in the delegates in MYSTRUCT are stored inside the C dll..
and the same functions are invoked whenever an event occurs. That is
the unmanaged code calls the managed code asynchronously.

The call to the C dll is working fine.. but whenever an event occurs
the registered function is not getting involked..
Do I have to add/remove anything more to the code?

Any help will be appreciated...

regards
Renjini
 
B

Barry Kelly

renjini said:
I am a starter in C# ...

I am in no way an expert in P/Invoke, but there is something obviously
wrong with the code below:
[StructLayout(LayoutKind.Sequential)]
public struct MYSTRUCT
{
[MarshalAs(UnmanagedType.FunctionPtr)]
ontest1 t1;
[MarshalAs(UnmanagedType.FunctionPtr)]
ontest2 t2
}

where ontest1 and ontest2 are two delegates.

//Importing the C dll function "MyFunctions"

[DllImport("mydll.dll")]
IntPtr MyFunctions(IntPtr myStruct);

I think you need to use 'ref MYSTRUCT myStruct' or 'out MYSTRUCT
myStruct', because otherwise using IntPtr directly will hide the actual
type of the arguments from .NET, and it won't be able to marshal the
calls (it needs to generate stub methods to adjust for managed / native
boundary). Delegates are not the same as unmanaged function pointers
(they are at least 8 bytes in size, for one thing), and that's another
reason why P/Invoke needs to see into this structure.
//Converts MYSTRUCT to pointer
GCHandle callbackHandle = GCHandle.Alloc
(mystruct ,GCHandleType.Pinned);

The above call boxes the struct (in order to convert it from a ValueType
- i.e. a C# struct - to the reference type 'object' aka System.Object),
and returns a pinned handle to this copy of the struct on the heap.
Thus, any modifications that MyFunctions does to the struct will be
modifying a copy of the structure.

But: there is more. A boxed struct on the heap is more than just the
struct: it also contains a reference to the method table etc. of the
class (analogous to vtable in C++). So, your pointer may not be a
pointer to MYSTRUCT.t1, but in fact may point to a .CLR method-table
pointer.

I think you should use 'ref mystruct', and let .NET P/Invoke create the
pinned handle automatically.

Alternatively, use C++/CLI or Managed C++.

-- Barry
 
R

renjini

Hi Barry,

I forgot to mention the point that this .NET dll (which wraps the
C dll) and the application using it as well, has to be deployed in a
mobile device that is using Compact Framework (2.0)

I had tried the way you suggested earlier, but I am getting an
exception "NotSupportedException".
It was because of this that I had pinned the structure, and I changed
the signature of the imported function from ref MYSTRUCT to IntPtr.

I have come to a dead end because of this...



-renjini
 
B

Barry Kelly

renjini said:
I forgot to mention the point that this .NET dll (which wraps the
C dll) and the application using it as well, has to be deployed in a
mobile device that is using Compact Framework (2.0)

I had tried the way you suggested earlier, but I am getting an
exception "NotSupportedException".
It was because of this that I had pinned the structure, and I changed
the signature of the imported function from ref MYSTRUCT to IntPtr.

I have come to a dead end because of this...

The only other thing I can suggest is, have you tried writing a test
case in C++/CLI?

-- Barry
 

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