C 结构到 C# 的编组

发布于 2024-09-15 16:32:43 字数 600 浏览 7 评论 0原文

请耐心等待,因为我是编组新手。我有一个 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。您能告诉我我的编组有什么问题吗?

Please bear with me as i am new to marshalling. I have a C structure and function declared as the following:

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

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

The BT_ADDR structure is the same structure defined in wsbth2.h in Win CE SDK. PerformQuery returns a pointer to an array of DeviceList.

In my C# program, i perform the following pinvoke declaration as followed

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

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

After running the C# program, a NotSupportedException is returned. Can you kindly advise me what is wrong with my marshalling?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

娇纵 2024-09-22 16:32:43

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

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

如果它只返回 1 个项目,您可能希望使其返回 IntPtr,然后使用 Marshal.PtrToStructure(),如下所述:

p/invoke C 函数返回指向结构的指针

更新:

您可以尝试这样的 C 接口 - 即一个返回数字的函数项目,以及用项目填充预先分配的数组的一个。

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 类库更容易,它提供了包装 C 代码的托管接口,混合 DLL。但是,如果您在 CE 上运行,则该选项可能不可用。

One problem is that the marshaller can't tell how many items are in the returned array, which means it can't marshal it.

Does the PerformQuery() API have some other way of determining the length of the array?

If it only ever returns 1 item, you may want to make it return an IntPtr and then use Marshal.PtrToStructure() as described here:

p/invoke C function that returns pointer to a struct

Update:

You could try a C interface like this - ie one function which returns the number of items, and one which fills a pre-allocated array with the items.

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

Then the C# definition would look like this:

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

And you would call that in C# like this:

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

When interfacing C# and C++ I usually find it easier to create a C++/CLI class library, which provides a managed interface that wraps the C code, in a mixed DLL. However that option might not be available to you if you're running on CE.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文