I am trying to create a wrapper for a C dll, and I am trying to call a function that accepts a callback function, gets the object as a pointer passed back.
.H file
extern int SetErrorHandler(void (*handler) (int, const char*, void*), void *data_ptr);
A handler is a callback function that is called when an error occurs, and data_ptr is any object (state) that is passed to you, in the case of my application, which will be just that (the current object).
I can call functions in a dll that uses marshalled constant types like strings of simple types, ints, etc. But I canโt understand how easy it is to march a pointer to a C # object, which is a state.
To pass an object reference to a C function from what I found by doing a search here, otherwise it seems that I need a structure type to be able to sort the function, so I created a structure to store my object:
[StructLayout(LayoutKind.Sequential)] struct MyObjectState { public object state; }
EDIT: I tried to put the [MarshalAs(UnmanagedType.Struct, SizeConst = 4)]
attribute in the public object state
property, but this causes the same error, so I deleted it, it looks like it won't work.
The structure contains one property of the object to store any object for the callback function.
I declared a delegate in C # as follows:
delegate void ErrorHandler(int errorCode, IntPtr name, IntPtr data);
Then I declared the import function in C # as follows:
[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)] static extern int SetErrorHandler handler, IntPtr data);
Then I created a callback function in my C # code:
void MyErrorHandler(int errorCode, IntPtr name, IntPtr data) { var strName = Marshal.PtrToStringAnsi(name); var state = new MyObjectState(); Marshal.PtrToStructure(data, state); Console.WriteLine(strName); }
I can call the library function as follows:
var state = new MyObjectState() { state = this }; IntPtr pStruct = Marshal.AllocHGlobal(Marshal.SizeOf(state)); Marshal.StructureToPtr(state, pStruct, true); int ret = SetErrorHandler(MyErrorHandler, pStruct);
The call is called and the callback function is called, but I cannot access the data in the callback function, and when I try Marshal.PtrToStructure
, I get the error message:
A structure should not be a class of values.
I searched a lot here and found various things in Marshall and void *, but nothing helped me get this to work
Thanks.