如何将本地c++内存转换为c#结构
本文关键字:转换 结构 内存 c++ | 更新日期: 2023-09-27 18:10:22
我在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;
};
我需要调用func1
在c#代码和传递Rect
:
我做了以下事情:
Rect rect = new Rect();
int rectSize = System.Runtime.InteropServices.Marshal.SizeOf(rect);
func1(???, rectSize);
应该传递rect
(但由于类型不兼容而不可能)的???
位置放置什么?
似乎应该传递IntPtr
,然后转换为struct rect
。如何做到这一点?
(rect
是这里的输出参数)
更新:
不希望改变c++代码和c#包装器的签名——它是第三方代码。
此外,Rect
的变量并不总是作为func1
的第一个参数传递
你修改了游戏规则,不允许修改c#代码。所以P/调用必须是这样的形式:
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);
}
使用类型为Rect
而不是IntPtr
的out
参数可能会让您的生活更轻松一些。这样的:
[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)));
尝试传递refrect。
[DllImport(NATIVE_DLL_NAME, CallingConvention = CallingConvention.Cdecl, EntryPoint = "func1")]
private static extern int func1(ref Rect param, int sizeOfParam);