Неопределенная ссылка при динамическом соединении с gcc в cygwin - PullRequest
5 голосов
/ 16 февраля 2012

(Это gcc 3.3.1 (длинная история - виноват NIST) на Cygwin.)

Я собрал некоторые исходные файлы с помощью gcc -c -fPIC ... для получения файлов .o.

ЗатемЯ сделал:

$ gcc -shared -o foo.dll foo.o bar.o

Но когда я использую его:

$ gcc -o usefoo.exe usefoo.o -L. -lfoo
  usefoo.o:usefoo.cpp:(.text+0x2e0): undefined reference to `_get_template_size'
  collect2: ld returned 1 exit status

Однако, если использует те же файлы .o , я вместо этого:

$ ar rcs libfoo-static.a foo.o bar.o

Ссылка на это успешна:

$ gcc -o foo.exe foo.o -L. -lfoo-static

Что странно для меня, так это то, что, как вы можете видеть ниже, рассматриваемая ссылка присутствует как в .a, так и в.длл.Так почему же ошибка при связывании с .dll?

Ссылка находится в общей библиотеке:

$ nm foo.dll|grep get_template
1001b262 T _get_template_size

А также в статической библиотеке:

$ nm libfoo-static.a |grep get_template
00000352 T _get_template_size

А вот ссылка на символ, сгенерированный в файле, который хочет использовать функцию:

$ nm usefoo.o
00000000 b .bss
00000000 d .data
00000000 t .text
0000012c T __Z12ErrorMessagei
         U ___main
         U __alloca
         U _atoi
         U _get_template_size
0000026c T _main
         U _printf

Обновлено с учетом ответа Марко

Интересно /досадно, когда я пытаюсь сделать минимальный тестовый пример этого, я не могу этого сделать (хотя это случается каждый раз с реальной вещью):

func1.h :

#ifndef FUNC1_H
#define FUNC1_H

int func1(int i);

#endif

func1.c :

#include "func1.h"

int func1(int i) {
  return 2*i;
}

usefunc.c :

#include <stdio.h>
#include "func1.h"

int main() {
  printf("%d\n", func1(10));
}

Тогда:

$ rm *.o *.dll *.a

$ gcc -fPIC -I. -c func1.c usefunc.c

$ gcc -shared -o func.dll func1.o

$ gcc -L. -o usefunc.exe usefunc.o -lfunc

$ ./usefunc.exe
20

Ответы [ 2 ]

6 голосов
/ 18 февраля 2012

Я нашел ответ (в том, что он решает мою проблему со ссылкой) на веб-странице Cygwin: http://cygwin.com/cygwin-ug-net/dll.html

В конечном итоге мне пришлось создать общую библиотеку и создать окончательную ссылку следующим образом:

$ gcc -shared -o cygfoo.dll \
      -Wl,--out-implib=libfoo.dll.a \
      -Wl,--export-all-symbols \
      -Wl,--enable-auto-import \
      -Wl,--whole-archive *.o \
      -Wl,--no-whole-archive

$ gcc -L. -o usefoo.exe usefoo.o -lfoo

Но я все равно хотел бы знать, почему мне не пришлось делать это для моего простого теста.

2 голосов
/ 17 февраля 2012

Я не совсем уверен, но в Windows есть пространства имен на модуль (например, exe или .dll).При статическом линковании вы помещаете все в один .exe, то есть в один модуль, в одно пространство имен.

При динамическом линковании вы создаете два модуля (1 exe, 1 dll), и оба имеют свои пространства имен.

Вам нужно экспортировать символ из DLL, чтобы он работал в iirc (читайте на importlibs, например, в превосходных компоновщиках и загрузчиках

...