我在C ++中有以下本机函数接口:
int func1(void* param, int sizeOfParam).
在文档中,提供了以下呼叫示例:
typedef struct
{
int x;
int y;
int width;
int height;
} Rect;
Rect rect;
int func1((void*)&rect, sizeof(rect));
我需要用C#代码调用这个函数。
我在本地库的开发人员的C#中有以下标题:
[DllImport(NATIVE_DLL_NAME,
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "func1")]
private static extern int func1(IntPtr param, int sizeOfParam);
我还有以下C#结构Rect
:
public struct Rect
{
int x;
int y;
int width;
int height;
};
我需要在C#代码中调用func1
并传递Rect
:
我执行以下操作:
Rect rect = new Rect();
int rectSize = System.Runtime.InteropServices.Marshal.SizeOf(rect);
func1(???, rectSize);
在???
应该传递rect
的位置放置什么(但由于类型不兼容而无法实现)?
似乎应该传递IntPtr
,然后转换为struct rect
。怎么做到这一点?
(此处为rect
输出参数)
更新
希望不要更改C ++代码和C#包装器的签名 - 它是第三部分代码
此外,Rect
传递为func1
答案 0 :(得分:3)
您更改了游戏规则以禁止修改C#代码。所以P / invoke必须是这种形式:
private static extern int func1(IntPtr param, int sizeOfParam);
在这种情况下,您需要手动进行编组:
int size = Marshal.SizeOf(typeof(Rect));
IntPtr param1 = Marshal.AllocHGlobal(size);
try
{
func1(param1, size);
Rect rect = (Rect)Marshal.PtrToStructure(param1, typeof(Rect));
}
finally
{
Marshal.FreeHGlobal(param1);
}
答案 1 :(得分:1)
使用out
类型的Rect
参数而不是IntPtr
,我可能会让自己的生活更轻松一些。像这样:
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
int x;
int y;
int width;
int height;
};
[DllImport(NATIVE_DLL_NAME, CallingConvention = CallingConvention.Cdecl, EntryPoint = "func1")]
private static extern int func1(out Rect param, int sizeOfParam);
然后调用该函数你可以写下:
Rect param;
int res = func1(out param, Marshal.SizeOf(typeof(Rect)));
答案 2 :(得分:1)
尝试传递ref Rect。
[DllImport(NATIVE_DLL_NAME, CallingConvention = CallingConvention.Cdecl, EntryPoint = "func1")]
private static extern int func1(ref Rect param, int sizeOfParam);