如何将原生C++内存转换为C#结构?

ser*_*gtk 7 c# pinvoke interop

我在C++中有以下本机函数接口:

int func1(void* param, int sizeOfParam).
Run Code Online (Sandbox Code Playgroud)

在文档中,提供了以下调用示例:

typedef struct
{
    int x;
    int y;
    int width;
    int height;
} Rect;

Rect rect;

int func1((void*)&rect, sizeof(rect));
Run Code Online (Sandbox Code Playgroud)

我需要从C#代码调用此函数.

我在本地库的开发人员的C#中有以下标题:

[DllImport(NATIVE_DLL_NAME, 
 CallingConvention = CallingConvention.Cdecl, 
 EntryPoint = "func1")]
private static extern int func1(IntPtr param, int sizeOfParam);
Run Code Online (Sandbox Code Playgroud)

我也有以下C#结构Rect:

public struct Rect
{
    int x;
    int y;
    int width;
    int height;
};
Run Code Online (Sandbox Code Playgroud)

我需要调用func1C#代码并传递Rect:

我做以下事情:

Rect rect = new Rect();
int rectSize = System.Runtime.InteropServices.Marshal.SizeOf(rect);

func1(???, rectSize);
Run Code Online (Sandbox Code Playgroud)

???rect应该通过的位置放置什么(但由于不兼容的类型,这是不可能的)?

似乎IntPtr应该传递然后转换为struct rect.怎么做到这一点?

(rect这里是输出参数)

更新:

希望不要更改C++代码和C#包装器的签名 - 它是第三部分代码.
而且它并不总是Rect作为第一个参数传递的变量func1

Dav*_*nan 3

您更改了游戏规则以禁止修改 C# 代码。因此 P/invoke 必须采用以下形式:

private static extern int func1(IntPtr param, int sizeOfParam);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您需要手动进行编组:

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);
}
Run Code Online (Sandbox Code Playgroud)