如何将本地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++内存转换为c#结构

你修改了游戏规则,不允许修改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而不是IntPtrout参数可能会让您的生活更轻松一些。这样的:

[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);