在 cygwin 中动态链接 gcc 时出现未定义的引用

发布于 2025-01-06 22:03:11 字数 1824 浏览 4 评论 0原文

(这是 Cygwin 上的 gcc 3.3.1 (长话——怪 NIST)。)

我用 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 中。那么为什么在链接 .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

更新以解决 Marco 的答案

有趣/烦人的是,当我尝试为此做一个最小测试示例时,我无法实现它(尽管每次真实的事情都会发生):

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

(This is gcc 3.3.1 (long story -- blame NIST) on Cygwin.)

I have compiled some source files with gcc -c -fPIC ... to get .o files.

Then I did:

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

But when I go to use it:

$ 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

However, if using the same .o files I instead do:

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

The link against that is successful:

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

What is weird to me is that as you can see below, the reference in question is present in both the .a and the .dll. So why the error when linking against the .dll?

Reference is found in the shared library:

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

And it's also in the static library:

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

And here's the reference to the symbol generated in the file that wants to use the function:

$ 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

Updated to address Marco's answer

Interestingly/annoyingly, when I try to make a minimum test example of this I can't make it happen (though it happens every time with the real thing):

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));
}

Then:

$ 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烛影斜 2025-01-13 22:03:11

我在 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

但我仍然很想知道为什么我没有这样做不必为了我的简单而这样做 测试。

I found the answer (in that it solves my link problem) on a Cygwin web page: http://cygwin.com/cygwin-ug-net/dll.html

What I ended up having to do was create the shared library and do the final link like this:

$ 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

But I'd still love to know why I didn't have to do this for my simple test.

别靠近我心 2025-01-13 22:03:11

我不完全确定,但据我所知,Windows 每个模块都有命名空间(如 exe 或 .dll)。静态链接时,您将所有内容放入一个 .exe 中,即一个模块、一个命名空间。

动态链接时,您创建两个模块(1 个 exe,1 个 dll),它们都有自己的名称空间。

您需要从 DLL 中导出符号才能工作 iirc (阅读 importlibs,例如在优秀的 链接器和加载器

I'm not entirely sure, but afaik Windows has namespaces per module (like exe or .dll). When statically linking you are putting everything in one .exe, thus one module, one namespace.

When dynamically linking, you create an two modules (1 exe, 1 dll), and they both have their namespaces.

You need to export the symbol from the DLL for this to work iirc (read up on importlibs, e.g. in the excellent Linkers and Loaders

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文