将成员函数从C++CLI传递到本机C回调
pass member function from C++ CLI to native C callback
我在将C++CLI类的成员函数从库传递到本机C回调时遇到问题。
确切地说,它是Teamspeak 3 SDK。
您可以使用以下代码毫无问题地传递非成员函数:
struct ClientUIFunctions funcs;
/* Initialize all callbacks with NULL */
memset(&funcs, 0, sizeof(struct ClientUIFunctions));
funcs.onConnectStatusChangeEvent = onConnectStatusChangeEvent;
但是我需要传递一个指向成员函数的指针,例如:
funcs.onConnectStatusChangeEvent = &MyClass::onConnectStatusChangeEvent;
欢迎使用任何其他关于如何在非静态成员函数中使用事件的想法。
提前感谢!
这只能通过静态类函数来完成,因为C对vtable或函数所属对象一无所知。请参阅下面的C++和托管C++示例
然而,这可能是一个变通办法,构建一个包装器类来处理您需要的所有回调。
#include <string.h>
struct ClientUIFunctions
{
void (*onConnectStatusChangeEvent)(void);
};
class CCallback
{
public:
CCallback()
{
struct ClientUIFunctions funcs;
// register callbacks
my_instance = this;
/* Initialize all callbacks with NULL */
memset(&funcs, 0, sizeof(struct ClientUIFunctions));
funcs.onConnectStatusChangeEvent = sOnConnectStatusChangeEvent;
}
~CCallback()
{
// unregister callbacks
my_instance = NULL;
}
static void sOnConnectStatusChangeEvent(void)
{
if (my_instance)
my_instance->OnConnectStatusChangeEvent();
}
private:
static CCallback *my_instance;
void OnConnectStatusChangeEvent(void)
{
// real callback handler in the object
}
};
CCallback *CCallback::my_instance = NULL;
int main(int argc, char **argv)
{
CCallback *obj = new CCallback();
while (1)
{
// do other stuff
}
return 0;
}
另一种可能性是,回调支持和void *args
类似的void (*onConnectStatusChangeEvent)(void *args);
,您可以从插件中设置。你可以在这个args空间中设置对象,这样在de sOnConnectStatusChangeEvent中你会有这样的东西:
static void sOnConnectStatusChangeEvent(void *args)
{
if (args)
args->OnConnectStatusChangeEvent();
}
对于托管C++,它应该是这样的,但是我无法编译它,因为它不喜欢模板括号
wrapper.h:
using namespace std;
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Text;
namespace Test
{
struct ClientUIFunctions
{
void (*onConnectStatusChangeEvent)(void);
};
public delegate void ConnectStatusChangeEvent(void);
public ref class ManagedObject
{
public:
// constructors
ManagedObject();
// destructor
~ManagedObject();
//finalizer
!ManagedObject();
event ConnectStatusChangeEvent^ OnConnectStatusChangeEvent {
void add(ConnectStatusChangeEvent^ callback) {
m_connectStatusChanged = static_cast<ConnectStatusChangeEvent^> (Delegate::Combine(m_connectStatusChanged, callback));
}
void remove(ConnectStatusChangeEvent^ callback) {
m_connectStatusChanged = static_cast<ConnectStatusChangeEvent^> (Delegate::Remove(m_connectStatusChanged, callback));
}
void raise(void) {
if (m_connectStatusChanged != nullptr) {
m_connectStatusChanged->Invoke();
}
}
}
private:
ConnectStatusChangeEvent^ m_connectStatusChanged;
};
class CCallback
{
public:
static void Initialize(ManagedObject^ obj);
static void DeInitialize(void);
private:
static void sOnConnectStatusChangeEvent(void);
static gcroot<ManagedObject^> m_objManagedObject;
};
}
包装纸.cpp:
#include <string.h>
#include "wrapper.h"
using namespace System;
using namespace Test;
void CCallback::Initialize(ManagedObject^ obj)
{
struct ClientUIFunctions funcs;
// register callbacks
m_objManagedObject = obj;
/* Initialize all callbacks with NULL */
memset(&funcs, 0, sizeof(struct ClientUIFunctions));
funcs.onConnectStatusChangeEvent = sOnConnectStatusChangeEvent;
}
void CCallback::DeInitialize(void)
{
// unregister callbacks
m_objManagedObject = nullptr;
}
void CCallback::sOnConnectStatusChangeEvent(void)
{
if (m_objManagedObject != nullptr)
m_objManagedObject->OnConnectStatusChangeEvent();
}
// constructors
ManagedObject::ManagedObject()
{
// you can't place the constructor in the header but just for the idea..
// create wrapper
CCallback::Initialize(this);
}
// destructor
ManagedObject::~ManagedObject()
{
this->!ManagedObject();
}
//finalizer
ManagedObject::!ManagedObject()
{
CCallback::DeInitialize();
}
gcroot<ManagedObject^> CCallback::m_objManagedObject = nullptr;
int main(array<System::String ^> ^args)
{
ManagedObject^ bla = gcnew ManagedObject();
while (1)
{
// do stuff
}
return 0;
}
相关文章:
- 从C++本机插件更新Vector3数组
- 架构决策:返回std::future还是提供回调
- GCC本机矩阵运算库
- 正在为Xtensa simcall函数编写回调函数
- 如何在C++中使用非静态成员函数作为回调函数
- 如何将从本机 c++ 的回调注册到 c#
- 如何在本机C++中跨线程调用(在主线程上回调)
- 如何在Android中从本机层文件回调应用层文件
- 操作方法:将 boost::endian 缓冲区类型转换回本机格式
- 如何使用传递给 C# 代码回调的 C/C++本机结构
- 在本机节点中的回调中调用回调
- 如何在本机回调中使用Cython CDEF类成员方法
- 调用带参数的方法时出现本机回调错误
- 将成员函数从C++CLI传递到本机C回调
- 通过JNI从本机线程回调时Java线程泄漏
- 从本机C++类的实例回调到C++/CX ref类的最佳方法是什么
- 如何使用JNI从本机C/ c++代码调用Java applet回调函数
- 非静态回调如何在本机代码中工作
- Windows:当我从本机代码回调到托管代码时,将显示“仅消息”窗口
- 避免在本机到托管回调上分配字符串