问题描述
我尝试在 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 (将#修改为@)