- 在我的 c 代码中,我有一个结构,它在非托管 dll 中包含许多未知大小的数组(c 代码)

- 我需要 的数据,这个结构的一个实例编码到 c# ,我稍后将发送回非托管 c 代码

- 一旦它到达 csharp,我就不需要操纵它,只需要保留它/存储它一段时间(这样它就可以保留在字节数组中)。

- 我不想使用关键字“不安全”,因为这是一个大项目,这只是一小部分,我不想那样编译。

我尝试将它编码为 lpArray,一切看起来都很好,但是当我回到 csharp 后查看内容时,它总是空的。这种类型的编码(marshal)处理风格适用于各种类型的动态数组,但不适用于结构。

搜索网络正在绘制空白和比我自己的场景更复杂的场景,但如果有人看到这样的链接,请在此处发布,我将非常感激!

谢谢。

--update 这里或多或少是我的代码结构:

C#:

[DllImport("mydll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
private static extern int W_Thread_Connect_NET(
    [MarshalAs(UnmanagedType.LPStr, SizeConst = 100)] string IPAddress,
    int DevicePort,
    [MarshalAs(UnmanagedType.LPArray)] byte[] connectionHandle
);

//and call it like this, with an empty struc to be populated by c (can this be done? it is comming back without the data):
byte[] myStrucParam= new byte[100];
int result = W_Thread_Connect_NET(myStrucParam, myParam1, myParam2, ...);

C:
 typedef struct myStructDef{
     char* myArray1,
     char* myArray2,
     int myInt1,
     ...
 } mystrucObj, *pMystrucObj;

//method that i am wanting to marshal the struct as a paramter here..
 MYDLL_DLLIMPORT int APIENTRY W_Thread_Connect_NET(pMystrucObj strucReturn_handle, char * IPAddress, int DevicePort, ...)
    {
      //(omitted)
    }

最佳答案

你说C#代码不需要操作结构体。这使它成为一个非常简单的问题。您可以将 struct 指针视为不透明指针,即 IntPtr

首先,您向 native 代码添加一个新函数:

pMystrucObj CreateStruct(void)
{
    pMystrucObj res = malloc(sizeof(*res));
    return res;
}

然后在你的 C# 代码中你这样称呼它:
[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
private static extern IntPtr CreateStruct();

现在像这样声明 W_Thread_Connect_NET:
[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)]
private static extern int W_Thread_Connect_NET(
    IntPtr theStructPtr,
    string IPAddress,
    int DevicePort,
    ....
);

并这样称呼它:
IntPtr theStructPtr = CreateStruct();
int res = W_Thread_Connect_NET(theStructPtr, IPAddress, DevicePort, ...);

当然,您需要添加另一个名为 DestroyStruct 的函数,以在完成后释放结构体的内存。

10-07 19:16
查看更多