2009-10-07 12 views
8

उम्मीद है कि यह एक दिमागी आसान सवाल है, लेकिन यह सी ++ के साथ विशेषज्ञता की कमी दिखाता है। मैं एक सी # प्रोग्रामर हूं, और मैंने अतीत में पी/Invoke के साथ अन्य लोगों के सी ++/सी डीएलएस के साथ व्यापक काम किया है। हालांकि, इस बार मैंने खुद को एक रैपर सी ++ डीएल (अप्रबंधित) लिखने का फैसला किया है, और फिर मैं अपने रैपर डीएल को सी # से बुला रहा हूं।सी ++ फ़ंक्शन कैसे सेट अप करें ताकि इसका उपयोग पी/इनवॉक द्वारा किया जा सके?

समस्या जो मैं तुरंत चल रहा हूं वह यह है कि मैं एक सी ++ फ़ंक्शन को परिभाषित करने में असमर्थ हूं जो पी/इनवॉक द्वारा पाया जा सकता है। मैं क्या इस के लिए वाक्य रचना है पता नहीं, लेकिन यहाँ मैं अब तक क्या कोशिश कर रहा हूँ है:

extern bool __cdecl TestFunc() 
{ 
    return true; 
} 

मूल रूप से मैं बस यह था, लेकिन यह या तो काम नहीं किया:

bool TestFunc() 
{ 
    return true; 
} 

और तो सी # तरफ, मेरे पास है:

public const string InterfaceLibrary = @"Plugins\TestDLL.dll"; 

    [DllImport(InterfaceLibrary, CallingConvention = CallingConvention.Cdecl, 
     EntryPoint = "TestFunc"), SuppressUnmanagedCodeSecurity] 
    internal static extern bool TestFunc(); 

सब कुछ संकलित, लेकिन जब मैं इस सी # पी निष्पादित/कॉल आह्वान, मैं एक System.EntryPointNotFoundException मिलती है: DLL में 'TestFunc' 'नामक एक प्रवेश बिंदु खोजने में असमर्थ प्लगइन्स \ TestDLL.dll '।

निश्चित रूप से यह C++ अंत में कुछ अविश्वसनीय रूप से सरल होना चाहिए कि मुझे सिंटैक्स नहीं पता है।

उत्तर

12

आप __declspec(export) रूप extern "C" उपयोग करने के लिए और साथ ही, इसलिए जैसे चाहता हूँ:

extern "C" _declspec(dllexport) bool TestFunc() 
{ 
    return true; 
} 

पूरी जानकारी के लिए MSDN on Marshalling Types देखते हैं।

+0

बिल्कुल सही, यह किया! मैंने अतीत में बाहरी "सी" होने का भी प्रयास किया था, लेकिन यह काम नहीं किया। यह तब तक विफल रहता है जब तक _declspec (dllexport) को जोड़ा नहीं जाता है। – x4000

1

आपको इस फ़ंक्शन को extern "C" के साथ बेनकाब करना होगा अन्यथा नाम उलझन में आता है।

1

सी ++ कंपाइलर पैरामीटर और रिटर्न प्रकारों के बारे में जानकारी शामिल करने के लिए आपके कार्यों के नामों को संशोधित करता है। इसे नाम मैंगलिंग कहा जाता है। दूसरी तरफ, सी कंपाइलर आपके फ़ंक्शन नामों को उलझन में नहीं डालता है।

आप सी बता सकते हैं ++ संकलक एक सी संकलक extern "C" का उपयोग कर के रूप में काम करने के लिए:

extern "C" __declspec(dllexport) bool TestFunc { return true; } 

का उपयोग कर पी/आह्वान, अपने नाम घायल नहीं किया जाना चाहिए सी # से कार्यों को कॉल करने के। इसलिए, आप वास्तव में सी कार्यों को सी # में निर्यात कर सकते हैं। यदि आप सी ++ में कार्यक्षमता को कार्यान्वित करना चाहते हैं, तो आप एक सी फ़ंक्शन लिख सकते हैं जो कार्यक्षमता को लागू करने वाले C++ फ़ंक्शन को कॉल करता है।

6

रीड के सही उत्तर को विस्तारित करना।

PInvoke के माध्यम से C++ फ़ंक्शन को उजागर करते समय आप एक और समस्या को चला सकते हैं, अमान्य प्रकार का उपयोग कर रहा है। PInvoke वास्तव में केवल आदिम प्रकारों और सादे पुराने डेटा संरचना/वर्ग प्रकारों के marshalling का समर्थन कर सकते हैं।

उदाहरण के लिए, मान लीजिए TestFunc निम्नलिखित हस्ताक्षर

void TestFunc(std::string input); 

भी जोड़ने निर्वासन 'सी' और __declspec(dllexport) सी ++ समारोह का पर्दाफाश करने के लिये पर्याप्त नहीं होगा था। इसके बजाय आपको एक सहायक कार्य बनाने की आवश्यकता होगी जो केवल PInvoke संगत प्रकारों का खुलासा करे और फिर मुख्य फ़ंक्शन में बुलाया जाए।उदाहरण

void TestFunc(const std::string& input) { ... } 

extern "C" _declspec(dllexport) void TestFuncWrapper(char* pInput) { 
    std::string input(pInput); 
    TestFunc(input); 
} 
+0

हाँ, यह ठीक है कि मैं इस तरह का कारण है कि मैं एक स्ट्रैपर सी ++ डीएल लिख रहा हूं, बजाय मुझे आवश्यक सभी कार्यों को कॉल करने की कोशिश करने के बजाय। मेरा लक्ष्य पी/Invoke के लिए एक सरल इंटरफ़ेस बनाना है, जबकि सभी आवश्यक जटिलता को कॉलबैक और जटिल प्रकार आदि के साथ देना, सी ++ पक्ष पर रहता है। अच्छे अंक! – x4000

+0

@ x4000, मैंने पहले एक ही दृष्टिकोण लिया है। एक नए डीएलएल के बजाय, मैंने सिर्फ उसी डीएलएल में रैपर फ़ंक्शन जोड़े। अधिक डीएलएल क्लीनर होगा। – JaredPar

+0

प्रारंभिक डीएलएल जो मैं लपेट रहा हूं वह तीसरी पार्टी है, इसलिए यह मेरे लिए एक विकल्प नहीं था। लेकिन आप सही हैं, मुझे लगता है कि जब संभव हो तो लपेटने वाली सामग्री से रैपर को अलग करने के कई पहलुओं में यह क्लीनर है। – x4000

1

कुछ करो के लिए यह पसंद करती है:

#define EXPORT extern "C" __declspec(dllexport) 

और फिर उदाहरण के एक C++ समारोह के लिए निर्यात कीवर्ड के साथ किसी भी समारोह की घोषणा,

BOOL getString(TCHAR* string, DWORD size); 

बन जाएगा

EXPORT BOOL getString(TCHAR* string, DWORD size); 

फिर मजेदार भाग: अपने वी.एस. कंसोल और प्रकार पर जाएँ:

dumpbin /EXPORTS <PATH_TO_GENERATED_DLL> 

और you'l घायल नाम और अपने सभी आसानी से निर्यात कार्यों की क्रमसूचक देखते हैं, तो यह उनके

0

बिल्ड के साथ सभी परियोजना pInvoking ओ सिर्फ एक बात है Win32 मंच और उपयुक्त बिट (उदाहरण के लिए x86 या x64) बिल्ड विकल्प।

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

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