Как вы используете JIT-компиляцию для получения обратного вызова указателя C из захваченной лямбды? - PullRequest
0 голосов
/ 14 января 2020

В C ++ 11 и более поздних версиях преобразование лямбда-выражения без захваченных переменных очень просто, но для лямбда-выражений с захваченными переменными, чтобы сделать это правильно, требуется динамическая c генерация кода согласно этому парню answer .

Это то, что, по моему мнению, должно генерироваться динамически. (Обратите внимание, что код здесь указывает на мою желаемую семантику, а не на какой-либо реальный код)

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

И я бы сгенерировал это, чтобы я мог связать динамически сгенерированный код с соответствующим обратным вызовом указателя функции, определенным в некотором API

api_return_value (*callback) (api_data);

Есть ли достаточно чистый и переносимый способ go об этом, используя что-то вроде LLVM или NativeJIT? Я застрял, используя C API без указателя пользовательских данных, так что, похоже, это моя единственная альтернатива.

1 Ответ

2 голосов
/ 15 января 2020

Вместо генерации JIT-кода во время выполнения вы можете "предварительно создать" пул (extern "C") функций во время компиляции и управлять пулом их распределения. Примерно так:

#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];

создаст 100 таких функций статически и свяжет их в список фриланса. Затем вы можете написать тип RAII-оболочки, который выделяет их из этого списка и возвращает их после завершения.

...