c# - 将 C 结构编码到 C#

标签 c# c pinvoke marshalling

请耐心等待,因为我是编码新手。我有一个声明如下的 C 结构和函数:

typedef struct 
{
    char* name;
    BT_ADDR address;
} DeviceList;

extern "C" _declspec(dllexport)DeviceList* PerformQuery();

BT_ADDR 结构与 Win CE SDK 中 wsbth2.h 中定义的结构相同。 PerformQuery 返回一个指向 DeviceList 数组的指针。

在我的 C# 程序中,我执行以下 pinvoke 声明

[StructLayout(LayoutKind.Sequential)]
struct DeviceList
{
    public string name;
    public ulong address;
}

[DllImport("BT_Conn.dll")]
public extern static DeviceList[] PerformQuery();

运行 C# 程序后,返回 NotSupportedException。你能告诉我我的编码有什么问题吗?

最佳答案

一个问题是编码器无法判断返回的数组中有多少项,这意味着它无法编码它。

PerformQuery() API 是否有一些其他方法来确定数组的长度?

如果它只返回 1 个项目,您可能想让它返回一个 IntPtr,然后按照此处所述使用 Marshal.PtrToStructure():

p/invoke C function that returns pointer to a struct

更新:

您可以尝试这样的 C 接口(interface) - 即一个函数返回项目的数量,另一个函数用项目填充预分配的数组。

extern "C" _declspec(dllexport) int GetQueryNumItems(); 
extern "C" _declspec(dllexport) void GetQueryItems(DeviceList* items); 

那么 C# 定义将如下所示:

[DllImport("BT_Conn.dll")]  
public extern static int GetQueryNumItems();
[DllImport("BT_Conn.dll")]  
public extern static void GetQueryItems([In, Out] DeviceList[] items);

在 C# 中你可以这样调用它:

int numItems = GetQueryNumItems();
DeviceList[] items = new DeviceList[numItems];
GetQueryItems(items);

当连接 C# 和 C++ 时,我通常会发现创建 C++/CLI 类库更容易,它提供了一个在混合 DLL 中包装 C 代码的托管接口(interface)。但是,如果您在 CE 上运行,则该选项可能对您不可用。

关于c# - 将 C 结构编码到 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3553310/

相关文章:

.net - GetLastWin32Error 返回 int 而不是 uint

c# - 集成测试数据库,我做对了吗?

c# - 如何在 C# 控制台中读取用户输入

c# - If-Else 语句在 while 循环中不起作用

C typedef 枚举编译

c - pthread_create-无法创建线程errno 12

c# - 验证在运行时从 URI 加载的 WPF 位图图像

c - 一些指针运算

c# - PInvoke - 如何表示来自 COM 接口(interface)的字段

c# - 找不到入口点