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.