简体   繁体   English

如何使用 JIT 编译从捕获的 lambda 生成 C 指针回调?

[英]How do you use JIT compilation to produce a C pointer callback from a captured lambda?

In C++11 and later converting a lambda expression with no captured variables is very simple, but for lambdas with captured variables to do it properly requires dynamic code generation as per this guys answer .在 C++11 及更高版本中,转换没有捕获变量的 lambda 表达式非常简单,但是对于具有捕获变量的 lambda 表达式,要正确执行此操作,需要根据这些人的回答动态生成代码。

Basically what I figure will have to be dynamically generate is this.基本上我认为必须动态生成的是这个。 (Note the code here indicates my desired semantics not any real code) (注意这里的代码表示我想要的语义而不是任何真正的代码)

UserData *userdata;
api_return_value callback(api_data arg) {
    return customized_callback(arg, userdata);
}

And I would generate this so I can bind the dynamically generated code to a corresponding function pointer callback defined in some api我会生成这个,这样我就可以将动态生成的代码绑定到某个 api 中定义的相应函数指针回调

api_return_value (*callback) (api_data);

Is there a reasonably clean and portable way to go about this using something like LLVM or NativeJIT?使用 LLVM 或 NativeJIT 之类的东西,是否有一种相当干净且可移植的方法来解决这个问题? I'm stuck using a C api with no provided user data pointer so this seems to be my only alternative.我一直在使用没有提供用户数据指针的 C api,所以这似乎是我唯一的选择。

Rather than doing JIT code generation at runtime, you can "pre-create" a pool of (extern "C") functions at compile time and manage an allocation pool of them.您可以在编译时“预创建”一个(extern“C”)函数池并管理它们的分配池,而不是在运行时生成 JIT 代码。 Something like:就像是:

#define REP10(P, M)  M(P##0) M(P##1) M(P##2) M(P##3) M(P##4) M(P##5) M(P##6) M(P##7) M(P##8) M(P##9)
#define REP100(M) REP10(,M) REP10(1,M) REP10(2,M) REP10(3,M) REP10(4,M) REP10(5,M) REP10(6,M) REP10(7,M) REP10(8,M) REP10(9,M)

extern struct func_wrap_t {
    func_wrap_t              *next;
    extern "C" void          (*c_fn)();
    std::function<void()>    fn;
} func_wrap_table[];
#define FUNC_WRAP_INIT(M) { M ? func_wrap_table+M-1 : 0, func_wrap_cfunc##M },
#define FUNC_WRAP_DEF(M) extern "C" void func_wrap_cfunc##M() { func_wrap_table[M].fn(); }
REP100(FUNC_WRAP_DEF)
func_wrap_t func_wrap_table[] = { REP100(FUNC_WRAP_INIT) };
func_wrap_t *func_wrap_freelist = &func_wrap_table[99];

will create 100 such functions statically and link them up into a freelist.将静态创建 100 个这样的函数并将它们链接到一个空闲列表中。 You can then write a wrapper RAII type that allocates them from this list and returns them when finished.然后,您可以编写一个包装器 RAII 类型,从该列表中分配它们并在完成时返回它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM