2010-08-24 89 views
5

請耐心等待,因爲我是編組新手。我有一個C的結構和功能聲明如下:將C結構編組爲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異常。你能不能告訴我我的編組有什麼問題?

回答

2

一個問題是編組器不能告訴返回數組中有多少項,這意味着它不能編組它。

PerformQuery()API有確定數組長度的其他方法嗎?

如果永遠只能返回1項,你可能要使它返回一個IntPtr,然後使用Marshal.PtrToStructure()如下所述:

p/invoke C function that returns pointer to a struct

更新:

你可以嘗試一個像這樣的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上運行,那麼該選項可能無法使用。

+0

Hi Saxon, PerformQuery()API實際上會返回多個項目。要確定數組的長度,我會在C++中使用sizeof(* devList)/ sizeof(DeviceList),但是我應該如何聲明我的API以通知編組器中返回數組中的項數? – 2010-08-24 03:47:06

+0

@CK:在C++中'sizeof(* devList)'將返回'sizeof(DeviceList)',即單個項目的大小。如果你有一個'DeviceList *'指針,那麼編譯器就不知道有多少項。只有當您有一個'DeviceList []'數組(具有固定數量的項目)時,sizeof才能返回數組的全部大小。 – 2010-08-24 03:50:05

+0

@CK:順便說一下,PerformQuery()是一個你正在編寫的函數,還是它是你必須接口的現有DLL中的一個函數? – 2010-08-24 03:51:11