Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This just happens to be similar to something I'm in the middle of working on right now.</p> <p>Here is an blog post on providing native callbacks using C++ classes: <a href="http://blogs.microsoft.co.il/blogs/alon/archive/2007/05/29/Native-Callback.aspx" rel="nofollow">http://blogs.microsoft.co.il/blogs/alon/archive/2007/05/29/Native-Callback.aspx</a></p> <p>I'm not familiar with calling C++ member functions from C, but I have done an interface (abstract base) class to another C++ class for callbacks (similar to the article). Here is a basic example of what I am providing a bridge for:</p> <pre><code>// Interface (abstract base) class providing the callback class IProvider { public: virtual ~IProvider() {} virtual void Callback() = 0; }; // User class of the callback class CUser { IProvider * m_pProvider; public: CUser(IProvider * pProvider) { m_pProvider = pProvider; } void DoSomething() { m_pProvider-&gt;Callback(); } }; // Implementation of the interface class class CHelloWorldProvider : public IProvider { void Callback() { printf("Hello World!"); } }; // Usage of the callback provider in a pure native setting void PureNativeUsage() { CHelloWorldProvider oProvider; CUser oUser(&amp;oProvider); oUser.DoSomething(); } </code></pre> <p>Now in order to make this available for managed implementations of the provider, we have to create a series of classes that provide the bridge.</p> <pre><code>// Where gcroot is defined #include &lt;vcclr.h&gt; // Managed provider interface class public interface class IManagedProvider { void Callback(); }; // Native bridge class that can be passed to the user class CProviderBridge : public IProvider { // Give the managed class full access friend ref class ManagedProviderBase; // Store a reference to the managed object for callback redirects gcroot&lt;IManagedProvider ^&gt; m_rManaged; public: void Callback(){ m_rManaged-&gt;Callback(); } }; // Managed provider base class, this provides a managed base class for extending public ref class ManagedProviderBase abstract : public IManagedProvider { // Pointer to the native bridge object CProviderBridge * m_pNative; protected: ManagedProviderBase() { // Create the native bridge object and set the managed reference m_pNative = new CProviderBridge(); m_pNative-&gt;m_rManaged = this; } public: ~ManagedProviderBase() { delete m_pNative; } // Returns a pointer to the native provider object IProvider * GetProvider() { return m_pNative; } // Makes the deriving class implement the function virtual void Callback() = 0; }; // Pure managed provider implementation (this could also be declared in another library and/or in C#/VB.net) public ref class ManagedHelloWorldProvider : public ManagedProviderBase { public: virtual void Callback() override { Console::Write("Hello World"); } }; // Usage of the managed provider from the native user void MixedUsage() { ManagedHelloWorldProvider ^ rManagedProvider = gcnew ManagedHelloWorldProvider; CUser oUser(rManagedProvider-&gt;GetProvider()); oUser.DoSomething(); } </code></pre> <hr> <p><b>Edit:</b> Added code to show w/o the managed interface class example I use.</p> <p>Here is a modified version of my example that can be used given your <code>CLibFunc</code> above. This is assuming how the C function performs the callback is accurate. </p> <p>Also this might be able to be slimmed down a bit depending on how involved your callback classes are and how much freedom for extension you need. </p> <pre><code>// Where gcroot is defined #include &lt;vcclr.h&gt; // C callback signature // Second parameter is meant to point to the calling C++ object typedef int (__stdcall CLIBCALLBACK) (int param1, void *caller); // C library function void CLibFunc(CLIBCALLBACK *callback, void *caller) { // Do some work (*callback)(1234, caller); // Do more work } // Managed caller interface class public interface class IManagedCaller { void EventFunction(int param1); }; // C++ native bridge struct struct CCallerBridge { // Give the managed class full access friend ref class ManagedCaller; // Store a reference to the managed object for callback redirects gcroot&lt;IManagedCaller ^&gt; m_rManaged; public: // Cast the caller to the native bridge and call managed event function // Note: This must be __stdcall to prevent function call stack corruption static int __stdcall CallBackImpl(int param1, void * caller) { CCallerBridge * pCaller = (CCallerBridge *) caller; pCaller-&gt;m_rManaged-&gt;EventFunction(param1); return 0; } }; // C++/CLI caller class public ref class ManagedCaller : public IManagedCaller { // Pointer to the native bridge object CCallerBridge * m_pNative; public: ManagedCaller() { // Create the native bridge object and set the managed reference m_pNative = new CCallerBridge(); m_pNative-&gt;m_rManaged = this; } ~ManagedCaller() { delete m_pNative; } // Calls the C library function void CallerFunction() { CLibFunc(CCallerBridge::CallBackImpl, m_pNative); } // Managed callback function virtual void EventFunction(int param1) { Console::WriteLine(param1); } }; // Usage int main(array&lt;System::String ^&gt; ^args) { ManagedCaller ^ oCaller = gcnew ManagedCaller(); oCaller-&gt;CallerFunction(); return 0; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload