C++/CLI - 回调到 C#
C++/CLI - callback to C#
我已经将这个问题精简到最基本的部分。我正在使用第 3 方市场数据 DLL,与此的连接由 class CManager 管理。然后用 class CManagerWrapper 包装,如下所示。
// 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;
};
C++ 程序编译为 DLL(CLR 控制台应用程序)并在以下 C# 项目中引用。
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));
}
}
}
我将需要管理一些回调,因此我的第一个尝试是将指向回调函数的指针移至托管 class。问题出在 C# 端,它无法识别 class 的 TestCallBack() 方法。它根本看不到它。当我使用简单参数创建其他方法时,它们很好,但由于函数指针参数,它不喜欢这个函数。
error CS0570: 'CManagerWrapper.TestCallBack(?)' is not supported by the language
有人能告诉我我在做什么傻事吗?我可能需要一个介于 C++ 和 C# 之间的层?
由于您使用的是 C++/cli,因此您可以使用所有 .NET(和托管)代码功能。例如,使用 Action
或 Delegate
而不是本机函数指针。
代码示例:
testclass.h 文件
#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 文件
#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);
}
将其构建为库 (.DLL) 并从您的 C# 应用程序中引用它。然后只需简单地使用这个:
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();
}
}
我已经将这个问题精简到最基本的部分。我正在使用第 3 方市场数据 DLL,与此的连接由 class CManager 管理。然后用 class CManagerWrapper 包装,如下所示。
// 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;
};
C++ 程序编译为 DLL(CLR 控制台应用程序)并在以下 C# 项目中引用。
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));
}
}
}
我将需要管理一些回调,因此我的第一个尝试是将指向回调函数的指针移至托管 class。问题出在 C# 端,它无法识别 class 的 TestCallBack() 方法。它根本看不到它。当我使用简单参数创建其他方法时,它们很好,但由于函数指针参数,它不喜欢这个函数。
error CS0570: 'CManagerWrapper.TestCallBack(?)' is not supported by the language
有人能告诉我我在做什么傻事吗?我可能需要一个介于 C++ 和 C# 之间的层?
由于您使用的是 C++/cli,因此您可以使用所有 .NET(和托管)代码功能。例如,使用 Action
或 Delegate
而不是本机函数指针。
代码示例:
testclass.h 文件
#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 文件
#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);
}
将其构建为库 (.DLL) 并从您的 C# 应用程序中引用它。然后只需简单地使用这个:
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();
}
}