簡體   English   中英

將引用轉換為函數指針返回值中的指針

[英]Cast reference to pointer in function pointer return value

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是一個嚴重的壞主意。

而是編寫一個適配器:

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必須是不可捕獲的,因此成員函數指針必須作為非類型模板參數傳遞,這意味着無法推導它。 您可以使用宏來解決此問題。

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())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM