2010-08-24 13 views
5

कृपया मेरे साथ भालू क्योंकि मैं marshalling के लिए नया हूँ। मैं एक सी संरचना और समारोह निम्नलिखित के रूप में घोषित किया है:सी संरचना के मार्शलिंग को सी #

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

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

BT_ADDR संरचना में समान संरचना विन सीई SDK में wsbth2.h में परिभाषित किया गया है। PerformQuery डिवाइसलिस्ट की एक सरणी में एक सूचक देता है।

मेरी सी # प्रोग्राम में, मैं के रूप में

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

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

पीछा सी # कार्यक्रम चलाने के बाद निम्नलिखित PInvoke घोषणा करते हैं, एक NotSupportedException दिया जाता है। क्या आप कृपया मुझे सलाह दे सकते हैं कि मेरे मार्शलिंग में क्या गलत है?

उत्तर

2

एक समस्या यह है कि मार्शलर यह नहीं बता सकता कि लौटे सरणी में कितनी वस्तुएं हैं, जिसका अर्थ है कि यह इसे मार्शल नहीं कर सकता है।

क्या PerformQuery() API में सरणी की लंबाई निर्धारित करने का कोई अन्य तरीका है?

यह केवल कभी 1 आइटम देता है, तो आप के रूप में यहाँ वर्णित यह एक IntPtr वापसी और उसके बाद का उपयोग Marshal.PtrToStructure() बनाना चाहते हो सकता है:

p/invoke C function that returns pointer to a struct

अद्यतन:

आप कर सकते थे इस तरह एक सी इंटरफ़ेस आज़माएं - यानी एक फ़ंक्शन जो आइटम की संख्या देता है, और वह आइटम जो प्री-आवंटित सरणी को आइटम के साथ भरता है।

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

तो सी # परिभाषा इस प्रकार दिखाई देगा:

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

और आपको लगता है कि कहेंगे सी # में इस तरह:

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

जब सी # और सी इंटरफ़ेस ++ मैं आमतौर पर यह आसान लगता है एक सी ++/सीएलआई कक्षा पुस्तकालय बनाने के लिए, जो एक प्रबंधित इंटरफेस प्रदान करता है जो एक मिश्रित डीएलएल में सी कोड को लपेटता है। हालांकि यदि आप सीई पर चल रहे हैं तो वह विकल्प आपके लिए उपलब्ध नहीं हो सकता है।

+0

हाय सैक्सन, PerformQuery() एपीआई वास्तव में एक से अधिक आइटम लौटाएगा। सरणी की लंबाई निर्धारित करने के लिए, मैं सी ++ में आकार (* devList)/sizeof (DeviceList) का उपयोग करूंगा, लेकिन मैं अपने एपीआई को लौटाए गए सरणी में आइटम्स की संख्या पर मार्शलर को सूचित करने के लिए कैसे घोषित करूं? –

+0

@CK: सी ++ 'आकार (* devList) में' आकार (डिवाइसलिस्ट) ', यानी एक आइटम का आकार वापस कर देगा। यदि आपके पास 'डिवाइसलिस्ट *' पॉइंटर है, तो कंपाइलर यह नहीं बता सकता कि कितने आइटम हैं। यह केवल तभी होता है जब आपके पास 'डिवाइसलिस्ट []' सरणी (एक निश्चित संख्या के आइटम के साथ) है जो आकार सरणी के पूर्ण आकार को वापस कर सकता है। –

+0

@CK: वैसे, PerformQuery() एक फ़ंक्शन है जिसे आप लिख रहे हैं, या यह मौजूदा DLL में एक फ़ंक्शन है जिसे आपको इंटरफ़ेस करना है? –

संबंधित मुद्दे