gpt4 book ai didi

c++ - 将成员函数从 C++ CLI 传递到 native C 回调

转载 作者:太空宇宙 更新时间:2023-11-04 04:00:37 25 4
gpt4 key购买 nike

我在将 C++ CLI 类的成员函数传递给库中的 native 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++,它应该是这样的,但是我无法编译它,因为它不喜欢模板括号..

包装器.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++ - 将成员函数从 C++ CLI 传递到 native C 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12070697/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com