在函数指针返回值中转换对指针的引用
Posted
技术标签:
【中文标题】在函数指针返回值中转换对指针的引用【英文标题】:Cast reference to pointer in function pointer return value 【发布时间】:2014-07-24 17:22:25 【问题描述】:Emscripten 为从 javascript 调用 C++ 函数生成自动绑定。但是,如果函数返回一个引用,则结果会按值传递给 JavaScript。指针返回值通过引用传递。所以如果我有一个函数:
MyType &MyClass::doStuff(int x,int y);
我可以这样做:
function("doStuff",&MyClass::doStuff);
使其出现在 JavaScript 中。但我需要的是:
function("doStuff",reinterpret_cast<MyType *(MyClass::*)(int,int)>(&doStuff));
让它返回一个指针。但是,为每个函数键入很糟糕,所以我需要一个魔术宏来转换:
function("doStuff",MAGIC(MyClass::doStuff));
到上面的版本(对于采用任意数量的任何类型参数的函数)带有强制转换或等效的东西。问题是:这在 C++11 中可行吗?
【问题讨论】:
我无法理解reinterpret_cast
。它是如何工作的,甚至是如何工作的?
它将 MyType &MyClass::doStuff 声明中的第一个 & 更改为 *。
我很确定使用reinterpret_cast
通过指向不同类型函数的指针调用函数是未定义的行为。
这是特定于 emscripten 编译器的,所以如果它是不可移植的也没关系。并且假装一个引用是一个指针听起来并不那么糟糕......
【参考方案1】:
在函数指针(或成员函数指针)上执行reinterpret_cast
是一个非常糟糕的主意。
改为编写一个适配器:
template<typename M, M m> struct make_wrapper_helper;
template<typename T, typename R, typename... A, R& (T::*m)(A...)>
struct make_wrapper_helper<R& (T::*)(A...), m>
R* (*operator()())(T&, A...)
return [](T& t, A ...a) -> R* return &(t.*m)(static_cast<A>(a)...); ;
;
template<typename M, M m>
decltype(make_wrapper_helper<M, m>()()) make_wrapper()
return make_wrapper_helper<M, m>()();
function("doStuff", make_wrapper<decltype(&MyClass::doStuff), &MyClass::doStuff>())
不幸的是,因为 lambda 必须是无捕获的,所以成员函数指针必须作为非类型模板参数传递,这意味着它不能被推导。您可以使用宏来解决此问题。
【讨论】:
谢谢!我怀疑会有比演员更清洁的方式,但不知道怎么做。这非常有效。【参考方案2】:ecatmur 完美地回答了这个问题,但我花了一些时间来理解代码的实际作用,所以这是一个使用宏的注释版本:
// Helper type for PTR_RETURN() macro.
template<typename RetTypeRef, RetTypeRef method> struct ptrReturnHelper;
// Specialize the helper for a particular class, method and set of arguments.
template<
typename Class,
typename RetType,
typename... ArgType,
RetType &(Class::*method)(ArgType...)
> struct ptrReturnHelper<RetType &(Class::*)(ArgType...), method>
/* Function returning function pointer,
called inside EMSCRIPTEN_BINDINGS block. */
auto getWrapper()->auto(*)(Class &, ArgType...)->RetType *
/* PTR_RETURN() macro ultimately returns this lambda function which
converts the original function pointer return value: */
return [](Class &obj, ArgType ...arg) -> RetType *
return &(obj.*method)(static_cast<ArgType>(arg)...);
;
;
/* Convert a pointer to RetType &Class::method(ArgType...)
into a pointer to RetType *Class::method(ArgType...) */
#define PTR_RETURN(method) \
(ptrReturnHelper<decltype(method),method>().getWrapper())
【讨论】:
以上是关于在函数指针返回值中转换对指针的引用的主要内容,如果未能解决你的问题,请参考以下文章