2014-10-23 2 views
1

Я пытаюсь запустить libtcc из C++, чтобы использовать C как язык сценариев времени исполнения. Скомпилированный код во время выполнения должен иметь возможность запускать функции из внешнего кода. Это прекрасно работает при передаче int, но при передаче структуры из tcc-кода в gcc-код происходят странные вещи.Совместимость скомпилированных gcc и tcc structs

Минимальный ход Пример:

#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 вместо ints в структуру, он работает. Выводится любой другой тип данных и случайный материал.

Сначала я думал, что это связано с выравниванием или чем-то, но это также происходит при использовании только одной переменной в структуре.

Я использую Linux 3.16 x86_64 и TCC 0.9.26

+0

На какой архитектуре и в какой операционной системе? Tinycc работает лучше на 32 бит x86 (a.k.a. ia32), чем на 64 бит x86-64 (a.k.a. amd64). –

+0

'Arch Linux x86_64'. Но что значит «работать лучше»? Это ошибка в 64-битной версии? – phiresky

+0

Я никогда не мог использовать 'tcc' в серьезных программах на x86-64. Мне кажется, что tinycc очень глючит на 64 бита. –

ответ

3

Оказывается, что проблема центров вокруг так, что 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 
+1

Что. Разве стандарт C не определяет, как работают структуры? Я имею в виду, что ни один из этих кодов не является даже C++. Благодаря! – phiresky

+2

@phiresky: Структуры передаются по значению. (Если компилятор реализует pass-by-value с помощью указателей, это прекрасно, если семантика одинакова.) Если функция с параметром 'struct Vec test' изменяет член' Test', это изменение не должно влиять вызывающий - и быстрый эксперимент с tcc версии 0.9.25 указывает, что tcc получает это право. (Я не знаю, что это за материал TCCState.) –

+0

Ваш код не будет компилироваться; он не содержит разделителей '<' and '>' в директивах '# include'. –

1

В новой версии TCC (libtcc) из официального репозитория мерзавца он работает, как ожидалось (гравюр "получил 0"). тестируется на gcc 4.9.3 и tcc 0.9.26 (commit 00ba4b).