Связывание Cygwin GCC с библиотекой Visual Studio

#c #visual-studio-2012 #gcc #cygwin #static-libraries

#c #visual-studio-2012 #gcc #cygwin #статические библиотеки

Вопрос:

Я создал простую библиотеку (статическую 64-битную — .lib) с использованием Visual Studio 2012 Express. Все, что есть в этой библиотеке, — это одна функция:

 int get_number()
{ 
    return 67; 
}
  

Допустим, вызывается созданная библиотека NumTestLib64.lib .

Я пытаюсь скомпилировать простую программу (назовем ее test.cpp ), используя Cygwin64, которая свяжет NumTestLib64.lib и выведет результат get_number() :

 #include <stdio.h>   

int get_number();

int main()
{
    printf("get_number: %dn", get_number());
    return 0;
}
  

Довольно просто, не так ли? Очевидно, нет.
Компиляция с g -o test test.cpp -L. -lTestLibStatic64 возвратами:

 /tmp/ccT57qc6.o:test.cpp:(.text 0xe): undefined reference to `get_number()'
/tmp/ccT57qc6.o:test.cpp:(.text 0xe): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `get_number()'
collect2: error: ld returned 1 exit status
  

и g -o test test.cpp TestLibStatic64.lib возвращает:

 /tmp/ccMY8yNi.o:test.cpp:(.text 0xe): undefined reference to `get_number()'
/tmp/ccMY8yNi.o:test.cpp:(.text 0xe): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `get_number()'
collect2: error: ld returned 1 exit status
  

Я ищу смелых, которые могут предоставить инструкции, как на стороне Visual Studio, так и на стороне командной строки Cygwin, о том, как это сделать.

Я перепробовал все возможные веб-страницы, поэтому, вероятно, ссылки не помогут, только точные инструкции. Я не против изменить библиотеку на DLL или выполнить какие-либо необходимые изменения, весь код принадлежит мне, как в этом простом примере, так и в реальном приложении, которое я разрабатываю.

Пожалуйста, помогите!

Комментарии:

1. Вы можете попробовать использовать extern "C" перед get_number

2. Я также думаю, что проблема, с которой вы столкнулись, заключается в том, что VS2012 и GCC используют разные модели для искажения имен. ИМХО, единственный способ обойти это — определить все методы API как обычный c (используя extern "C" , как указано выше).

3. Я пробовал. Добавлен внешний символ «C» к объявлению в коде библиотеки. Даже изменил весь проект на проект C (изменен с .cpp на .c). По-прежнему не работает. Я получаю ошибку «неопределенная ссылка на get_num ()».

Ответ №1:

Найден ответ! Ключом является создание файлов * .dll и * .lib. *.lib создается, когда символы фактически экспортируются. Ниже приведен файл заголовка созданной библиотеки DLL (работал только при создании DLL в Visual Studio, создание статической библиотеки пока не работает):

 #ifdef TESTLIB_EXPORTS
#define TESTLIB_API __declspec(dllexport)
#else
#define TESTLIB_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C"
{
#endif

TESTLIB_API int get_num();

#ifdef __cplusplus
}
#endif
  

Конечно, TESTLIB_EXPORTS определяется только в проекте DLL.
Важно, чтобы основной, который ссылается на эту DLL, использовал этот заголовок из-за __declspec(dllimport) части. Кроме того, extern "C" необходимо, как предположили комментаторы, избегать искажений.
Кроме того, мне удалось выполнить связывание на Cygwin32 и MinGW32, а не на Cygwin64.