2010-10-04 17 views
7

मुझे एक डीएल में निहित सी एपीआई से एक फ़ंक्शन कॉल करने की आवश्यकता है। समारोह प्रोटोटाइप के रूप में निम्नानुसारमंच के साथ मार्शल शून्य * कैसे करें

int func(char* name, void* value); 

लग रहा है .... जहां सूचक मूल्य की सामग्री को किसी भी प्रकार से पारित कर दिया नाम पर निर्भर है देख सकते हैं। मुझे यह सुनिश्चित नहीं है कि इस शून्य * को सही ढंग से मार्शल करने के लिए डीएल इनपोर्ट कैसे सेट अप करें। Ihave IntPtr पर प्रयोग कर रहे काम करने के लिए whe मूल्य एक पूर्णांक है, लेकिन मैं तैरता आदि के लिए सही ढंग से मूल्यों प्राप्त नहीं कर सकता

मैं इस तरह समारोह आयात करने के लिए कोशिश कर रहा हूँ ...

[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, ref IntPtr value); 

कृपया ध्यान दें लगता है जो वह मान एक आउटपुट है। किसी भी प्रकार के मूल्य के लिए एक सूचक, यानी एक ज्ञात प्रकार (कॉलर को ज्ञात) के मूल्य की स्मृति के वैश्विक क्षेत्र में पता। एक सी प्रोजे में कॉलर से उम्मीद की जाएगी कि वांछित प्रकार और वांछित वांछित प्रकार को वहां वास्तविक मूल्य प्राप्त करने के लिए किया जाए। अब तक दिए गए उत्तरों को इस धारणा के आधार पर माना जाता है कि समारोह परिणामस्वरूप पॉइंटर स्थान पर परिणाम लिख देगा। मेरी गलती क्योंकि मैं बहुत विशिष्ट नहीं हूं। माफ़ कीजिये। सी # मेरा बैग नहीं है, और मैं यह भी नहीं जानता कि यदि IntPtr यहां जाने का रास्ता है ...

उत्तर

2

आप ref जरूरत नहीं है - IntPtr तरह से मूल कोड को void* पारित करने के लिए है।

[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, IntPtr value); 

संपादित करें: सी कोड इनपुट का उपयोग आवश्यक स्मृति में लिखने के लिए कर सकते हैं। आपके द्वारा सामना की जाने वाली समस्या प्रबंधित कोड के लिए यह जानना है कि प्रत्येक संभावित वापसी मूल्य प्रकार के लिए कितनी मेमोरी आवंटित की जाती है। फिर एक उचित आकार का ब्लॉक Marshal.AllocHGlobal या Marshal.AllocCoTaskMem का उपयोग करके आवंटित किया जा सकता है, जिसे आपके द्वारा उपयोग की जाने वाली आवंटन विधि के अनुसार FreeHGlobal या FreeCoTaskMem के माध्यम से उपयोग किया जा सकता है, एक बार प्रबंधित कोड आउटपुट मान के साथ किया जाता है।

उदाहरण के लिए @Alex Farber से उत्तर देखें।

+0

मुझे और अधिक विशिष्ट खेद होना चाहिए था। IntPtr मान एक आउटपुट है। इस फ़ंक्शन के मामले में यह किसी मान के लिए सूचक होगा जो कि किसी भी प्रकार का हो सकता है। कॉलर से यह जानने की उम्मीद है कि वे किस प्रकार से पुनर्प्राप्त करने का प्रयास कर रहे हैं। – matt

+0

@matt - उत्तर अभी भी वही है - संपादन देखें। –

+0

@matt - @ हंस के उत्तर और टिप्पणियों की जांच करें - यह आपकी सबसे अच्छी शर्त है। –

10

इससे निपटने का सबसे अच्छा तरीका फ़ंक्शन के अधिभार प्रदान करना है ताकि सी # पक्ष पर सबकुछ साफ हो।

[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, out int value); 
[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, out float value); 
// etc, one each for each type 
+0

सहमत हुए, बशर्ते सी कोड को संशोधित किया जा सके, यह सबसे अच्छा समाधान है। –

+0

@ स्टेव - सी कोड का कोई संशोधन आवश्यक नहीं है। यह सिर्फ पॉइंटर को देखता है कि पिनवोक मार्शलर गुजरता है। –

+0

तो यह सबसे अच्छा समाधान है और +1 और भी अच्छी तरह से योग्य है –

2
 
[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, IntPtr value); 

... 

// n - number of bytes which is enough to keep any type used by function 
IntPtr ptr = Marshal.AllocHGlobal(n); 
func(name, ptr); 

// Use Marshal.ReadByte, Marshal.ReadInt32 ... or Marshal.Copy 
// to copy from ptr filled by func to managed variable. For example: 
byte b = Marshal.ReadByte(ptr); 

Marshal.FreeHGlobal(IntPtr); 
0

कभी कभी, यह इस दृष्टिकोण का उपयोग करने के लिए आसान हो सकता है: इस तरह।

घोषणा:

: एक चर पारित करने के लिए

func("some string", "test"); 

उदाहरण उपयोग: एक स्ट्रिंग पारित करने के लिए

func("some string", (int)12); 
func("some string", (double)12); 

उदाहरण उपयोग: एक मूल्य के पारित करने के लिए

[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func([MarshalAs(UnmanagedType.LPTStr)] string name, [MarshalAs(UnmanagedType.AsAny)] object value); 

उदाहरण उपयोग

int value = 12; 
func("some string", value); 
संबंधित मुद्दे