Я пытаюсь запустить libtcc из C ++, чтобы использовать C в качестве языка сценариев во время выполнения. Скомпилированный код времени выполнения должен иметь возможность запускать функции из внешнего кода.
Это работает нормально при передаче ints, но при передаче структуры из tcc-кода в gcc-код происходят странные вещи.
Минимальный бегущий пример:
#include <libtcc.h>
#include <stdio.h>
struct Vec {
int x;
};
void tmp(struct Vec test) {
printf("got %x\n",test.x);
}
int main() {
TCCState* tcc; tcc = tcc_new();
tcc_set_output_type(tcc, TCC_OUTPUT_MEMORY);
tcc_add_symbol(tcc, "tmp", (void*)&tmp);
tcc_compile_string(tcc, "\
struct Vec {int x;};\
void tmp(struct Vec test);\
void fun() {\
struct Vec x = {0};\
tmp(x);\
}");
tcc_relocate(tcc, TCC_RELOCATE_AUTO);
void (*fun)(void) = (void(*)())tcc_get_symbol(tcc, "fun");
fun();
}
Работает с:
gcc -ltcc -ldl test.c && ./a.out
> got 23b472b0
tcc -ltcc -ldl test.c && ./a.out
> got 0
Почему скомпилированная версия gcc не печатает ожидаемый 0?
Когда я ставлю только long long
s вместо целых чисел в структуре, это работает. Любой другой тип данных и случайные вещи выводятся.
Сначала я думал, что это из-за выравнивания или чего-то еще, но это также происходит, когда в структуре используется только одна переменная.
Я использую Linux 3.16 x86_64 и tcc 0.9.26
Похоже, что проблема заключается в том, что C и C ++ понимают весь «тест struct Vec» как параметр. В TCC он считается / считается указателем. В C ++ это выглядит так, как будто нужно утверждать, что это указатель более четко.
#include libtcc.h
#include stdio.h
struct Vec {
int x;
};
void tmp(struct Vec * test) {
printf("got %x\n",test->x);
}
int main() {
TCCState* tcc; tcc = tcc_new();
tcc_set_output_type(tcc, TCC_OUTPUT_MEMORY);
tcc_add_symbol(tcc, "tmp", (void*)&tmp);
tcc_compile_string(tcc, "\
struct Vec {int x;};\
void tmp(struct Vec test);\
void fun() {\
struct Vec x = {5};\
tmp(x);\
}");
tcc_relocate(tcc, TCC_RELOCATE_AUTO);
void (*fun)(void) = (void(*)())tcc_get_symbol(tcc, "fun");
fun();
}
Выход выглядит как:
got 5
В новой версии tcc (libtcc) из официального репозитория git он работает как положено (выводит «получил 0»). протестировано на gcc 4.9.3 и tcc 0.9.26 (commit 00ba4b).