简体   繁体   English

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

[英]How to convert native C++ memory into C# structure?

I have the following native function interface in C++: 我在C ++中有以下本机函数接口:

int func1(void* param, int sizeOfParam).

In documentation the following example of call is provided: 在文档中,提供了以下调用示例:

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

Rect rect;

int func1((void*)&rect, sizeof(rect));

I need to call this function from C# code. 我需要从C#代码调用此函数。

I have the following header in C# from developers of native library: 我在本地库的开发人员的C#中有以下标题:

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

I also have the following C# structure Rect : 我还有以下C#结构Rect

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

I need to call func1 in C# code and pass Rect : 我需要在C#代码中调用func1并传递Rect

I do the following: 我做以下事情:

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

func1(???, rectSize);

What to place in position of ??? 什么位置??? where rect should be passed (but it is not possible because of incompatible types)? 应该传递rect (但由于类型不兼容而无法实现)?

It seems that IntPtr should be passed and then converted to struct rect . 似乎应该传递IntPtr然后转换为struct rect How to achieve this? 怎么做到这一点?

( rect is output parameter here) rect是这里的输出参数)

UPDATE: 更新:

It is desired not to change signatures of C++ code and C# wrappers - it is third part code. 希望不要更改C ++代码和C#包装器的签名 - 它是第三部分代码。
Moreover it is not always variable of Rect is passed as first param of func1 而且它并不总是变量的Rect作为func1第一个参数传递

You changed the rules of the game to disallow modifications to the C# code. 您更改了游戏规则以禁止修改C#代码。 And so the P/invoke must be of this form: 所以P / invoke必须是这种形式:

private static extern int func1(IntPtr param, int sizeOfParam);

In that case you need to do the marshalling by hand: 在这种情况下,您需要手动编组:

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

I'd probably make life a bit easier for yourself by using an out param of type Rect rather than IntPtr . 我可能通过使用Rect类型而不是IntPtrout参数来让自己的生活更容易一些。 Like this: 像这样:

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

Then to call the function you can write this: 然后调用该函数你可以这样写:

Rect param;
int res = func1(out param, Marshal.SizeOf(typeof(Rect)));

Try passing ref Rect instead. 尝试传递ref Rect。

[DllImport(NATIVE_DLL_NAME, CallingConvention = CallingConvention.Cdecl, EntryPoint = "func1")]
private static extern int func1(ref Rect param, int sizeOfParam);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM