I am using a 3. party SDK, which is made up from .dll, .lib and .h files. I am using the .dll's to PInvoke against. And the .h files to see the function names and parameters. (So I am not using the .lib files).
The SDK is rather complex, so making the PInvoke wrappers have proven to be a challenge. All the functions/structs/enums is defined in the .h files.
The function I am trying to wrap is called InitBaseComponent, and I can call it, but it returns a "Error In Argument" enum back. So my guess is it is marshalling that creates this problem. So the question is: I am doing this right?
Function: InitBaseComponent(...)
//C Function: InitBaseComponent(...)
ERROR InitBaseComponent(
Method_Interface* methodInterface, //[in]
void* methodInst, //[in]
ErrorCallBackFunction errorCallbackFunc, //[in]
void* ErrorCallbackInst, //[in]
Component* BaseComponent //[in, out]
);
//C# Function: InitBaseComponent(...)
[DllImport("externalSDK.dll", EntryPoint = "InitBaseComponent", CallingConvention = CallingConvention.Cdecl)]
public static extern ERROR InitBaseComponent(
Method_Interface methodInterface,
IntPtr methodInst,
ErrorCallBackFunction errorCallbackFunc,
IntPtr ErrorCallbackInst,
out Component BaseComponent
);
Enum: ERROR
//C Enum: ERROR
typedef enum ERROR_E {
OK = 0, //Everything is ok
E_ARG = 1, //Error in the Arguments
E_DATA = 2 //Data error
//And more...
} ERROR;
//C# Enum: ERROR
public enum ERROR
{
OK = 0, //Everything is ok
E_ARG = 1, //Error in the Arguments
E_DATA = 2 //Data error
//And more...
}
Struct: Method_Interface
//C struct: Method_Interface
typedef struct Method_Interface_S
{
void* (*Method1)(void* Inst, size_t size);
void* (*Method2)(void* Inst, size_t nelements, size_t bytes);
void* (*Method3)(void* Inst, void *pointer, size_t size);
void (*Method4)(void* Inst, void* pointer);
}Method_Interface;
//C# class: Method_Interface
[StructLayout(LayoutKind.Sequential)]
public class Method_Interface
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void Method1_delegate(IntPtr Inst, uint size);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void Method2_delegate(IntPtr Inst, uint nelements, uint bytes);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void Method3_delegate(IntPtr Inst, IntPtr pointer, uint size);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void Method4_delegate(IntPtr Inst, IntPtr pointer);
public Method1_delegate Method1;
public Method2_delegate Method2;
public Method3_delegate Method3;
public Method4_delegate Method4;
}
Delegate: ErrorCallBackFunction
//C ErrorCallBackFunction
typedef void (*ErrorCallBackFunction)(void* errorCallBackInst, ERROR errorCode, const char* szMessage, const char* szDetail);
//C# delegate: ErrorCallBackFunction
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ErrorCallBackFunction(IntPtr errorCallBackInst, ERROR errorCode, string szMessage, string szDetail);
Struct: Component
//C struct: Component
typedef struct Component_S
{
void* ObjPointer;
unsigned long number;
} Component;
//C# class: Component
[StructLayout(LayoutKind.Sequential)]
public class Component
{
public IntPtr ObjPointer;
public ulong number;
}
Anyone knows what I am doing wrong?
You have declared Component in the C# as a class. That means that it is already a reference. But then you passed it as an out parameter which adds an extra layer of indirection, one too many. So, you need to remove the out, just as you did for methodInterface.
[DllImport(...)]
public static extern ERROR InitBaseComponent(
Method_Interface methodInterface,
IntPtr methodInst,
ErrorCallBackFunction errorCallbackFunc,
IntPtr ErrorCallbackInst,
Component BaseComponent
);
Obviously you need to instantiate the Component object in your C# before you call InitBaseComponent.
Some other observations:
size_t is pointer sized, so your translation as uint will fail on 64 bit platforms.long is 64 bits, but C++ long is 32 bits, on Windows. So your translation of the C++ Component struct is wrong. The number field must be declared with type uint.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With