Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marshalling of C structure to C#

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?

like image 581
C K Siew Avatar asked Nov 05 '22 09:11

C K Siew


1 Answers

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.

like image 105
Saxon Druce Avatar answered Nov 14 '22 23:11

Saxon Druce