简体   繁体   中英

C++/CLI - callback to C#

I've cut this problem down to the bare bones. I'm using a 3rd party market data DLL and the connection to this is managed by class CManager. This is then wrapped with class CManagerWrapper as below.

// clr.cpp

    #include <windows.h>  
    #using <System.dll>

    using namespace System;

    class CManager
    {
    public:
        CManager() {}
        ~CManager() {}
    };

    public ref class CManagerWrapper {
    public:
        CManagerWrapper() : m_Impl(new CManager) {}
        ~CManagerWrapper() {
            delete m_Impl;
        }

    public:
        typedef void(__stdcall *Callbackfunc)(int);
        void TestCallBack(Callbackfunc cbf)
        {
            cbf(2);
        }

    private:
        CManager * m_Impl;
    };

The C++ program is compiled as a DLL (CLR Console App) and referenced in the following C# project.

using System;
using System.Runtime.InteropServices;

namespace main
{
    class Program
    {

        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        delegate void CallbackFunc(int value);

        static void Main(string[] args)
        {

            CallbackFunc callback =
                (value) =>
                {
                    Console.WriteLine("Callback value = {0}", value);
                };

            CManagerWrapper mw = new CManagerWrapper();

            mw.TestCallBack(Marshal.GetFunctionPointerForDelegate(callback));

        }
    }
}

I will need to manage some callbacks so my first stab was to get a pointer to the callback function over to the managed class. The problem is on the C# side it doesn't recognise the TestCallBack() method of the class. It simply can't see it. When I create other methods with simple arguments they are fine but it doesn't like this function because of the function pointer argument.

error CS0570: 'CManagerWrapper.TestCallBack(?)' is not supported by the language

Can somebody tell me what silliness I'm doing? I probably need a layer between the C++ and the C#?

Since you're using C++/cli you can use all of the .NET ( and managed ) code functionalities. eg Use of a Action or Delegate instead of native function pointers.

code example :

testclass.h file

#pragma once

#using <System.dll>

using namespace System;

class NativeClass
{
public:
    NativeClass();
    ~NativeClass();
};
namespace Managed
{
    // delegate declaration as in simple C# code
    public delegate void ManagedCallbackHandler(int);

    public ref class ManagedClass
    {
    public:
        ManagedClass();
        ~ManagedClass();

        // call this directly from c# with method adequate to the action
        void TestCallBack(Action<int>^);
        // call this directly from C# with method adequate to the handler
        void TestCallBack2(ManagedCallbackHandler^);

    private:
        NativeClass * m_native;
    };
}

testclass.cpp file

#include "TestClass.h"

NativeClass::NativeClass() { }
NativeClass::~NativeClass() { }

Managed::ManagedClass::ManagedClass() : m_native(new NativeClass) { }
Managed::ManagedClass::~ManagedClass() { delete m_native; }

void Managed::ManagedClass::TestCallBack(System::Action<int>^ cbf)
{
    cbf(2);
}

void Managed::ManagedClass::TestCallBack2(Managed::ManagedCallbackHandler^ cbf)
{
    cbf(2);
}

Build this as alibrary (.DLL) and reference it from your C# application. Then just simply use this :

class Program
{
    static void Main(string[] args)
    {
        Managed.ManagedClass c = new Managed.ManagedClass();
        // call using Action<int>
        c.TestCallBack(Console.WriteLine);
        // call using ManagedCallbackHandler
        c.TestCallBack2(Console.WriteLine);
        Console.ReadLine();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM