2011-05-27 9 views
5

के साथ पैरामीटर मैंने इस पर अन्य समान प्रश्न पढ़े हैं लेकिन वे इस विशेष समस्या को हल नहीं करते हैं। मेरे पास एक पुरानी सी-लाइब्रेरी है जिसमें टॉपरकेस फ़ंक्शन (उदाहरण के रूप में) है। यह एक char * लेता है और एक char * देता है। हालांकि, लौटा दिया गया सूचक एक ही स्ट्रिंग के लिए एक सूचक है (मुझसे मत पूछो मैंने इसे नहीं लिखा)।char के साथ एक सी डीएलएल फ़ंक्शन को कॉल करना * पी/Invoke

समारोह इस तरह दिखता है:

[DllImport("mydll.dll", EntryPoint = "touppercase", 
       CharSet = CharSet.Ansi, ExactSpelling = true, 
       CallingConvention = CallingConvention.Cdecl)] 
    private static extern System.IntPtr touppercase(string postData); 

मेरे एप्लिकेशन में यह करने के लिए कॉल की तरह

 string sTest2 = Marshal.PtrToStringAnsi(to_uppercase(sTest)); 

हालांकि दिखता है:

__declspec(dllexport) 
char * __cdecl touppercase(char *ps_source) 
{ 
    char *ps_buffer = NULL; 

    assert (ps_source != NULL); 

    ps_buffer = ps_source; 
    while (*ps_buffer != '\0') 
    { 
     *ps_buffer = toupper(*ps_buffer); 
     ps_buffer++; 
    } 
*ps_buffer = '\0'; 
    return (ps_source); 
} 

सी # कोड इस तरह दिखता है की घोषणा करने के sTest2 बस एक यादृच्छिक स्ट्रिंग होने के समाप्त होता है।

मैंने उसी पैरामीटर के साथ एक ही डीएल में एक परीक्षण फ़ंक्शन जोड़ा लेकिन यह स्थानीय रूप से स्मृति आवंटित करता है और स्ट्रिंग की प्रतिलिपि बनाता है। यह ठीक काम करता है। मूल संस्करण अब क्यों काम करता है?

नोट: डीएलएल पुस्तकालयों को अद्यतन करना स्वयं एक विकल्प नहीं है।

+0

इस फ़ंक्शन पर कॉल करने के बाद एसटेस्ट का क्या होता है? क्या यह बदलता है? –

+0

आप कॉलिंग सम्मेलन की घोषणा क्यों कर रहे हैं। डिफ़ॉल्ट रूप से सी # मानक सम्मेलन (सी/सी ++) के बजाय कॉलिंग सम्मेलन का उपयोग करता है। आप पहले से ही अपनी सी पुस्तकालय में सम्मेलन बदल चुके हैं। यदि आपको सी कोड को किसी अन्य के रूप में घोषित नहीं किया गया था तो आपको केवल सम्मेलन को बदलना होगा। –

+1

@ramhound: निर्यात किए गए कार्यों के कॉलिंग सम्मेलन को स्पष्ट रूप से निर्दिष्ट करना सबसे सुरक्षित है। आप नहीं चाहते कि निर्यात '/ GR' या'/Gz' से प्रभावित हो। –

उत्तर

10

ताकि आप एक stringbuilder का उपयोग करना चाहिए समारोह संदर्भ को संशोधित किया गया है:

[DllImport("dll.dll", EntryPoint="touppercase", 
CharSet = CharSet.Ansi, ExactSpelling = true, 
CallingConvention = CallingConvention.Cdecl)] 
private static extern System.IntPtr touppercase(StringBuilder postData); 

यह कुछ इस तरह कॉल करें:

StringBuilder sTest = new StringBuilder("abs"); 
    touppercase(sTest); 
    string result = sTest.ToString(); 

वापसी सूचक की व्याख्या के लिए -> बेन वोइट

+0

उसने चमत्कार किया। बहुत बहुत धन्यवाद। – Jonnster

3

जैसा कि आपने सही ढंग से देखा है, वापसी प्रकार एक ही स्ट्रिंग के लिए एक सूचक है। और फ़ंक्शन को प्रदान की गई स्ट्रिंग एक अस्थायी बफर है जिसे यूनिकोड-> एएनएसआई रूपांतरण के लिए .NET द्वारा उपयोग किया जाता है, जो P/Invoke रिटर्न से पहले हटा दिया जाता है। तो यह एक जंगली सूचक है जिसे आपको अनदेखा करना होगा (केवल सी # शून्य रिटर्न प्रकार का उपयोग करने के लिए सबसे अच्छा)।

मैं का उपयोग String के बजाय पैरामीटर के लिए StringBuilder का उपयोग करने की भी सिफारिश करता हूं, यह .NET को पता है कि फ़ंक्शन पारित पैरामीटर को बदल देगा। StringBuilder की सामग्री फ़ंक्शन द्वारा संशोधित की जाएगी, इस प्रकार आप रिटर्न वैल्यू के बिना अपने परिणाम कैसे प्राप्त कर सकते हैं।

+0

बहुत बहुत धन्यवाद। – Jonnster

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