簡體   English   中英

從現代C ++ 11函數轉換為原始函數指針

[英]Convert from modern C++11 function to raw function pointer

假設我具有以下功能接口:

void giveme(void (*p)());

該函數僅接受指向沒有返回類型和參數的函數指針

我想知道是否存在一種方法( 不更改接口 )將類方法作為該函數的參數傳遞。

我將嘗試用一個例子更好地解釋。 我有一堂課,例如:

class Foo {
 public:
  template<typename T>
  void bar();
};

我想將bar<T> (該類的可尋址實例的實例)作為函數giveme參數giveme

我想方法與對象綁定 ,並獲得功能目標。

就像是:

int main(int argc, char *argv[]) {
  Foo foo;
  std::function<void()> f = std::bind(&Foo::bar<int>, &foo);

  giveme(f.target<void()>());

  return 0;
}

它可以編譯,但顯然不起作用,因為從這里開始

TargetType應匹配目標類型,以便typeid(TargetType)==target_type() 否則,函數將始終返回指針。

那么,如果存在,有什么方法可以實現呢?

這是一個(非常糟糕的)想法:

Foo * foo_ptr;  // maybe thread_local

void foo_call()
{
    foo_ptr->bar<int>();
}

int main()
{
    Foo foo;
    foo_ptr = &foo;
    give_me(&foo_call);
}

它不漂亮,但您的情況也不是。

我只知道一種方法,這是一個糟糕的主意,不要這樣做。

typedef void (*void_fn)();
struct stateful_void_fn_data = {
    void_fn raw;
    std::function<void()> actual;
    std::atomic_bool in_use;
}
// a global array to hold your function bindings and such
extern stateful_void_fn_data stateful_functions[5];
// N stateless functions that defer to the correct global state
template<int n> void void_fn_impl() {stateful_functions[n].actual();}
extern stateful_void_fn_data stateful_functions[5] = 
    {{void_fn_impl<0>}, {void_fn_impl<1>}, {void_fn_impl<2>}, {void_fn_impl<3>}, {void_fn_impl<4>}};
// function to register a stateful and get a stateless back
void_fn allocate_void_fn(std::function<void()>&& f) {
   for(int i=0; i<5; i++) {
       if(stateful_functions[i].in_use.compare_exchange_weak(false, true)) {
            stateful_functions[i].actual = std::move(f);
            return stateful_functions[i].raw;
        }
   }
   throw std::runtime_error("ran out of stateful functions :(");
}
// function to unregister
void free_void_fn(void_fn f) {
    if (f == nullptr) return;
    for(int i=0; i<5; i++) {
        if (stateful_functions[i].raw == f) {
             stateful_functions[i].in_use = false;
             return;
        }
     }
   throw std::runtime_error("unknown void function");
}

基本上,我生成5個void()函數( void_fn_impl<N> ),每個函數調用存儲在五個全局數組插槽之一中的函數( stateful_functions[i].actual )。 然后, allocate_void_fn將把任何std::function<void()>在全局數組中,並向您提供在數組中調用該條目的void() 該函數本身是無狀態的,因為我們已將所有狀態存儲在全局數組中。 free_void_fnin_use僅用於使這些函數可重用。

當然,因為RAII很好:

class hidden_state_void_fn {
    void_fn raw;
public:
    hidden_state_void_fn(std::function<void()>&& f) 
         :raw(allocate_void_fn(std::move(f)) {}
    hidden_state_void_fn(const hidden_state_void_fn&& r) {
         raw = r.raw;
         r.raw = nullptr;
    }
    hidden_state_void_fn& operator=(const hidden_state_void_fn&& r)  {
         free_void_fn(raw);
         raw = r.raw;
         r.raw = nullptr;
    }
    ~hidden_state_void_fn() {free_void_fn(raw);}
    operator void_fn() {return raw;}
    operator()() {raw();}
};
std::map<int,std::function<void()>> tasks;

template<int n>
struct task_wrapper{
  static void f(){ if (tasks.count(n)) tasks[n](); }
  task_wrapper(std::function<void()> fin){ tasks[n]=fin; }
  ~task_wrapper(){ tasks.erase(n); }
  static std::shared_ptr< void(*)() > make(std::function<void()> fin){
    auto self=std::make_shared<task_wrapper>(fin);
    return { &f, fin };
  }
};

task_wrapper<N>::make(func)返回一個共享的指針,該指針指向將調用有狀態func的無狀態函數指針。

我們可以使用通常的技術來創建簽名為shared_ptr<void(*)()>(*)()的K個函數指針的數組。 然后我們可以有一個shared_ptr<void(*)()> register_func( std::function<void()> )

要查找空白,我們可以進行線性搜索,也可以構建空白表。 這看起來像是傳統的分配/免費的“堆”,或者是空白的范圍樹,等等。


另一種方法是即時創建並保存DLL,然后加載它並調用該符號。 這可以通過黑客(具有這樣的DLL和已知的偏移量來進行修改,復制和寫入,然后加載並運行)或通過將C ++編譯器(或其他編譯器)與您的代碼一起交付(!)來完成。

暫無
暫無

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

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