调用使用 C# 返回结构数组的非托管 dll 函数

Posted

技术标签:

【中文标题】调用使用 C# 返回结构数组的非托管 dll 函数【英文标题】:calling unmanaged dll function that returns an array of struct using C# 【发布时间】:2011-12-04 11:42:30 【问题描述】:

我有一个使用 C++ 编写的非托管 dll。我可以从我的 C# 应用程序中轻松调用一些函数。但是一个功能让我受苦:)

C++

问题出在日志参数中。它应该反映为Data_Struct 类型的数组:

typedef struct

unsigned int    id;
unsigned short  year;
unsigned char   month;
unsigned char   day;
unsigned char   hour;
unsigned char   min;
unsigned char   sec;
unsigned char   status; 
Data_Struct;

int Read_Stored_Data(HUNIT pUnitHandle, int option, int updateFlag, 
                     int maxEntries, unsigned char *log)

C#(我的转换)

public struct Data_Struct

    public uint id;
    public ushort year;
    public byte month;
    public byte day;
    public byte hour;
    public byte min;
    public byte sec;
    public byte status;



[DllImport("SData.dll", EntryPoint = "Read_Stored_Data")]
public static extern int Read_Stored_Data(int pUnitHandle, int option, 
    int updateFlag, int maxEntries, ref Data_Struct[] log);

请假设我传递了正确的值pUnitHandleoptionupdateFlagmaxEntries。问题出在最后一个参数(log):

Data_Struct[] logs = new Data_Struct[1000];
res = Read_Stored_Data(handle, 1, 0, 1000, ref logs); // This should work but it 
                                                      // causes the application 
                                                      // to terminate!

有什么想法吗?

【问题讨论】:

调用它会发生什么?堆栈不平衡? AccessViolationException?静默失败? 静默失败..没有帮助 【参考方案1】:

尝试使用 PInvoke 属性。

具体来说,将布局应用于结构:

[StructLayout(LayoutKind.Sequential)]
public struct Data_Struct

    public uint id;
    public ushort year;
    public byte month;
    public byte day;
    public byte hour;
    public byte min;
    public byte sec;
    public byte status;

并对参数应用编组属性,同时删除ref

[DllImport("SData.dll", EntryPoint = "Read_Stored_Data")]
public static extern int Read_Stored_Data(int pUnitHandle, int option,
    int updateFlag, int maxEntries, [MarshalAs(UnmanagedType.LPArray), Out()] Data_Struct[] log);

看看是否有帮助,然后进行相应的调整。

【讨论】:

这非常有效。即使 [StructLayout(LayoutKind.Sequential)] 不是必需的。 在更改结构后再次陷入困境,如下所示:

以上是关于调用使用 C# 返回结构数组的非托管 dll 函数的主要内容,如果未能解决你的问题,请参考以下文章

c# - 如何调用分配输出缓冲区以在c#中返回数据的非托管c++函数?

C#中如何调用动态链接库DLL

将指针从非托管代码返回到托管代码

dllimport如何在非托管dll中获取哪个应用程序调用了函数

编写用于 C# 的非托管 C++ DLL

C# 调用C++ DLL,而c++函数的有一个参数需要是null,该怎么传递?