2011-04-26 12 views
6

मेरे पास एक सी ++ - सीएलआर रैपर है जो सी # से कॉल की गई मानक सी ++ लाइब्रेरी के आसपास है। लाइब्रेरी से स्टेटस संदेश प्राप्त करने के लिए मैं मार्शल :: GetFunctionPointerForDelegate के माध्यम से C++ कोड में कॉलबैक को असाइन किए गए प्रतिनिधि का उपयोग करता हूं।सी ++ - सीएलआई से सी # के माध्यम से सी ++ - सीएलआई कॉलबैक और प्रतिनिधियों

इसने मुझे काम करने के लिए काफी समय लगाया है और मैं बहुत करीब हूं (मुझे लगता है)। सी # प्रतिनिधि को बुलाया जाता है लेकिन स्ट्रिंग सीमा पार सही ढंग से पारित नहीं होती है।

जब मैं सी ++ कोड से टेक्सकॉलबैक ("टेस्ट स्ट्रिंग") को कॉल करता हूं तो मुझे सी # फ़ंक्शन में वापस बकवास मिलता है। प्रबंधित आवरण के कॉलबैक स्थापित करने के लिए

--- मूल सी ++ वर्ग और कॉलबैक फ़ंक्शन ---

class Solver 
{ 
    private: 

    std::string TakesCallback(const std::string message) 
    { 
     return cb(message); 
    } 

    public: 

    // Declare an unmanaged function type that takes a string 
    typedef std::string (__stdcall* ANSWERCB)(const std::string); 
    ANSWERCB cb; 
}; 

--- समारोह ----

// Set the delegate callback 
void ManagedSolver::SetMessageCallback(SendMessageDelegate^ sendMessageDelegate) 
{ 
    _sendMessage = sendMessageDelegate; 

    // Use GetFunctionPointerForDelegate to get the pointer for delegate callback 
    IntPtr ip = Marshal::GetFunctionPointerForDelegate(sendMessageDelegate); 
    _solver->cb = static_cast<Solver::ANSWERCB>(ip.ToPointer()); 
} 

--- सी # समारोह सी ++ \ CLR आवरण SetMessageCallBack के लिए पारित किया ----

private void Message(string message) 
{ 
    XtraMessageBox.Show(message, "Done", MessageBoxButtons.OK); 
} 
+2

क्या आप वाकई प्रबंधित मतलब सी ++ हैं? सी ++ के लिए प्रबंधित एक्सटेंशन (मुझे लगता है) विजुअल स्टूडियो 2003 में समर्थित होना बंद कर दिया गया है। सी ++/सीएलआई इसका प्रतिस्थापन है, और यह एक पूरी तरह से अलग भाषा है ... –

+0

हाय बिली, क्षमा करें आप बिल्कुल सही हैं। मेरा रैपर एक मानक सी ++ लाइब्रेरी के आसपास सी ++/सीएलआर है। मैंने शीर्षक और शरीर को अद्यतन किया है। –

+0

ठीक है मैंने इसे हल किया है std :: स्ट्रिंग इंटरऑप के साथ काम नहीं करेगा जैसा कि यहां बताया गया है http://stackoverflow.com/questions/874551/stdstring-in-c मैं वापस आऊंगा और जवाब दूंगा जैसे ही स्टैक ओवरफ्लो मुझे अनुमति देता है। –

उत्तर

1

सी ++ std::string और .NET System::String अंतर-परिवर्तनीय नहीं हैं। सी # पहले का उपयोग नहीं कर सकता, और देशी सी ++ कोड दूसरे का उपयोग नहीं कर सकता है। आपको जो चाहिए वह एक सी ++/सीएलआई फ़ंक्शन है जो प्रतिनिधि को कॉल करने से पहले std::string स्वीकार करता है और इसे System::String^ में परिवर्तित करता है।

1

सामान्य तौर पर, एसटीडी C++ कक्षाएं दलदल नहीं किया जा सकता सी # से/से aled। आप अपने सी ++ यूनिकोड के रूप में कोड का निर्माण कर रहे हैं, मैं निम्नलिखित में अपने कोड को बदलने के लिए सिफारिश करेंगे:

सी ++

// Declare an unmanaged function type that takes a string 
typedef int (__stdcall* ANSWERCB)(LPCTSTR); 

सी #

private void Message([MarshalAs(UnmanagedType.LPWStr)]string message) 
{ 
    XtraMessageBox.Show(message, "Done", MessageBoxButtons.OK); 
} 

निम्नलिखित example from MSDN

पर एक नजर डालें
3

मैं कुछ महीनों के लिए the code from this page का उपयोग कर रहा हूं और मुझे यह बहुत अच्छा लगता है। यह केवल एक ही हेडर फ़ाइल है जिसे आप अपनी परियोजनाओं में कॉपी कर सकते हैं और यह नौकरी जल्दी और साफ करता है।

आप उदाहरण के लिए का उपयोग

std::wstring s = clix::marshalString<E_UNICODE>(myCliString); 

या

System::String^ s = clix::marshalString<E_ANSI>(mystdstring); 

यह दोनों तरीकों से काम करता है और आपके द्वारा निर्दिष्ट क्या एन्कोडिंग आप (एएनएसआई, UTF8 या Windows का यूनिकोड - वास्तव में UTF16) चाहते हैं।

1

सी ++ (अप्रबंधित)

class DllContext 
{ 
public: 
typedef void (__stdcall *LOG_CALLBECK)(const wchar_t* LogString); 
DllContext(LOG_CALLBECK WriteLog) // Constructor 
{ 
    this->WriteLog = WriteLog; 
    this->WriteLog(L"Creating сontext..."); // UNICODE string! 
} 

private: 
LOG_CALLBECK WriteLog; 
} 

// Export function 
SENDAUDIOCLIENT_API DllContext *CreateContext(DllContext::LOG_CALLBECK WriteLog) 
{ 
    return new DllContext(WriteLog); 
} 

सी #

class MyClass 
{ 
private delegate void WriteLog_Delegate([MarshalAs(UnmanagedType.LPWStr)]string Mess); 
private WriteLog_Delegate WriteLog; 

[DllImport("My.dll", EntryPoint = "[email protected]@[email protected]@[email protected]@Z", CallingConvention = CallingConvention.Cdecl)] 
private static extern IntPtr CreateContext(WriteLog_Delegate WriteLogProc); 

private IntPtr Context = IntPtr.Zero; 

public MyClass() 
{ 
    this.WriteLog = new WriteLog_Delegate(this.WriteLogToConsole); 
     this.Context = CreateContext(this.WriteLog); 
} 

private void WriteLogToConsole(string Mess) 
{ 
    Console.WriteLine("Message from unmanaged code: {0}", Mess); 
} 
} 
संबंधित मुद्दे