2012-06-25 2 views
4

Я видел ссылку GCC с общей библиотекой C++, но я не могу воспроизвести ее самостоятельно. Таким образом, первым я создаю библиотеку C++ с функцией тестом:Как связать общую библиотеку C++ с gcc

g++ -shared -o libtest.so test.c 

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

gcc -o prog.out main.c -L. -ltest 

Тогда я получаю ошибку

undefined reference to 'testfunc' 

, который, как я думаю, вызван разными ссылками в библиотеке ... C называет функцию testfunc и C++ называет функцию [некоторые вещи] __ testfunc [возможно, снова некоторые вещи].

Я также попытался использовать

gcc -o prog.out main.c -l:libtest.so 

, но это приводит к одной и той же ошибки.

Поэтому, мой вопрос: как можно связать библиотеку C++ с gcc с c-файлом?

Обновление: Я знаю, что могу использовать extern "C", но это не так, как оно разрешено. Может быть, есть некоторые параметры для компоновщика?

Update2: Просто подумал, что также возможно, что первая часть просто скомпилирована с C++ и связана с gcc. Также попробовал это:

g++ -c testlib.c -o testlib.o 
gcc -shared -o libtest.so testlib.o 
gcc -o prog.out -l:libtest.so 

все еще не работает. Что-то не так с флагами?

+1

дубликат http://stackoverflow.com/questions/1068129/c-library-not-linking-using-gcc-g –

+2

Что вы имеете в виду «это не так, как это решено»? Я говорю вам, что ** это так, как это решено, если только вы не сказали нам. –

+0

@ Dietrich Epp Похоже, что все сделано так, как я писал в Update2. И я уверен, что это не сделано с «extern» - если вы хотите взглянуть на проект: [openjdk] (http://openjdk.java.net/) –

ответ

8

Да, проблема не имеет ничего общего с общими библиотеками (я думаю ...) и все, что связано с изменением имени.

В вашем заголовке, вы должны объявить функцию следующим образом:

#ifdef __cplusplus 
extern "C" { 
#endif 

void testfunc(void); 

#ifdef __cplusplus 
} 
#endif 

Это заставит testfunc иметь один и тот же символ и соглашения о вызовах как для C и C++.

О системе я использую сейчас, имя символа C будет _testfunc и имя C++ символа (предполагается, что вы сделать не использования extern "C") будет __Z8testfuncv, который кодирует информацию о типах параметров, так перегрузки будет работать правильно. Например, void testfunc(int x) становится __Z8testfunci, который не сталкивается с __Z8testfuncv.

2

Когда вы используете g ++, он компилирует ВСЕ источник как C++. Это означает, что все функции используют C++ ABI (это также включает в себя изменение имени). Когда вы используете gcc, он скомпилирует * .c файлы с использованием C ABI (без имени).

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

Чтобы заставить г ++ скомпилировать функцию, используя префикс C ABI его с extern "C"

extern "C" void testfunc(char*); 

В качестве альтернативы использовать версию блока

extern "C" { 
<multiple Functions> 
} 

Честно говоря, я никогда ничего с НКУ не компилируйте больше (если есть некоторые жесткие требования сделать это (в этом случае я обычно исправляю код, чтобы он работал на C++)). Если вы скомпилируете все файлы с помощью g ++, просто упростите процессы.

0

Если вы уверены, что это не из-за изменения имени. Тогда это означает, что gcc не смог найти библиотеку, пытающуюся предоставить полный путь библиотеки, если файл .so находится в стандартном расположении. Если вы не уверены, то перепроверьте любой конфликт в имени переменной (функции). Используйте пространства имен для группировки классов и определения функций внутри классов, чтобы избежать конфликта имен.

Смежные вопросы