如何解决用于将 C 函数回调转发到 C++ 成员函数的 C++ thunk 类实现
我尝试在 C++ 中实现一个“thunk”类,该类允许获取 C 函数指针以传递给最终调用 C++ 成员函数的 C 代码。一个特定的要求是它适用于不传递 void * 上下文参数(或类似参数)的 C 代码,这在 C 代码回调中很常见。因此,必须为每个 CC++ 链接创建一个不同的全局或静态 C 粘合函数。在我的实现中,这是通过模板参数 N 实现的,对于 thunk 类的每次使用,它必须是不同的,并导致为每个模板具体化创建不同的“蹦床”函数。
我的问题是:有没有一种方法可以在不需要模板参数 N 的情况下实现这一点,或者编译器可以根据某种模板“魔术”自动为每个具体化分配一个新值 N?
#ifndef THUNK_H
#define THUNK_H
#include <map>
#include <stdexcept>
template <class Sig,class Obj,size_t N>
class Thunk;
class ThunkBase
{
public:
static void clear()
{
for (auto it : mThunkStorage) {
delete it.second;
}
mThunkStorage.clear();
}
virtual ~ThunkBase() {}
protected:
static std::map<void *,ThunkBase *> mThunkStorage;
};
template <class R,class... Args,size_t N>
class Thunk<R(*)(Args...),Obj,N> : public ThunkBase
{
public:
Thunk(Obj &obj,R(Obj::*method)(Args...)) : mObj(obj),mMethod(method)
{
std::pair<decltype(mThunkStorage)::iterator,bool> resPair = mThunkStorage.emplace(
(void *)(&Thunk<R(*)(Args...),N>::trampoline),this);
if (!resPair.second) {
throw std::runtime_error("Failed to insert thunk object");
}
}
R(*entry())(Args...)
{
return &Thunk<R(*)(Args...),N>::trampoline;
}
private:
Obj &mObj;
R(Obj::*mMethod)(Args...);
static R trampoline(Args... args)
{
auto selfFuncPtr = &Thunk<R(*)(Args...),N>::trampoline;
auto it = mThunkStorage.find((void *)selfFuncPtr);
if (it == mThunkStorage.end()) {
throw std::runtime_error("Could not find thunk object");
}
ThunkBase *base = it->second;
Thunk<R(*)(Args...),N> *self = static_cast<Thunk<R(*)(Args...),N> *>(base);
Obj &obj = self->mObj;
R(Obj::*method)(Args...) = self->mMethod;
return (obj.*method)(args...);
}
};
#endif
std::map<void *,ThunkBase *> ThunkBase::mThunkStorage;
// -> usage would be like,for example
struct MyClass
{
void myFunc(int);
};
MyClass myObj;
Thunk<void(*)(int),MyClass,0> myThunk(myObj,&MyClass::myFunc);
void (*myFunc)(int) = myThunk.entry();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。