如何在运行时解析 dll 中的外部符号,而不是使用 Cygwin 进行链接时

Posted

技术标签:

【中文标题】如何在运行时解析 dll 中的外部符号,而不是使用 Cygwin 进行链接时【英文标题】:How to resolve external symbols in dll at run time, instead of link time with Cygwin 【发布时间】:2020-04-28 16:36:22 【问题描述】:

我正在将一组程序从 linux 移植到 Windows+Cygwin。集合的主共享库是指在使用共享库的程序中声明的一些常量外部符号。我没有找到用 Cygwin 做同样事情的方法。 ld 在构建共享库时抱怨未解析的符号。 Windows+Cygwin 是否不支持 --allow-shlib-undefined 选项?

例子:

mydll.c

#include <stdio.h>

extern const int a;

void f(void)

  printf("%d\n", a);

myprog.c

const int a = 1;

extern void f(void);

int main(int argc, char** argv)

  f();

用于构建 dll 的命令:

 gcc -shared -o libmydll.so -Xlinker --allow-shlib-undefined mydll.c

【问题讨论】:

请添加构建dll的命令 命令添加到初始帖子。 【参考方案1】:

不简单,循环依赖在Windows下是一团糟

https://www.lurklurk.org/linkers/linkers.html#wincircular

解决方法:

$ ar sqc  libmyprog.dll.a myprog.o
$ gcc --shared mydll.o -Wl,--out-implib=libmydll.dll.a -Wl,--export-all-symbols -o mydll.dll -L. -lmyprog
$ gcc myprog.o -Wl,--out-implib=libmyprog.dll.a -Wl,--export-all-symbols  -o myprog.exe -L. -lmydll
$ gcc --shared mydll.o -Wl,--out-implib=libmydll.dll.a -Wl,--export-all-symbols -o mydll.dll -L. -lmyprog
$ ./myprog.exe
1

验证它们是否交叉依赖:

$ objdump.exe -x mydll.dll  | grep "DLL Name"
        DLL Name: myprog.exe
        DLL Name: cygwin1.dll
        DLL Name: KERNEL32.dll

$ objdump.exe -x myprog.exe  | grep "DLL Name"
        DLL Name: mydll.dll
        DLL Name: cygwin1.dll
        DLL Name: KERNEL32.dll

【讨论】:

【参考方案2】:

非常感谢您提供此解决方法。我将尝试将其扩展到我的真实案例:一个由许多目标文件和许多链接到该 dll 的程序组成的 dll。据我了解,可能有必要为每个程序创建一个 dll。

【讨论】:

使用 cmets,而不是回复您的答案。所有程序的数据是否始终相同? 不,如果数据相同,我会在 dll 中创建常量。我重写了 main dll(运行时库)和程序生成器(从 Basic 语言到 C++ 的翻译器)的一部分,以在 main() 的开头动态修复几个常量的值。但是,仍然有 2 个非关键常量无法动态设置,因为它们用于全局变量的构造函数。每个常量不能取两个值,0 或 1。要么我为所有 4 种可能的组合创建一组 dll,要么我将常量强制设置为限制较少的值。

以上是关于如何在运行时解析 dll 中的外部符号,而不是使用 Cygwin 进行链接时的主要内容,如果未能解决你的问题,请参考以下文章

DLL 注入编译“未解析的外部符号”Visual Studio C++

在 Windows 上构建 C++ 项目时,Tensorflow 2.3 无法解析机器生成的文件中的外部符号

由于 VC9 编译器符号名称不匹配而导致无法解析的外部符号

LNK2019:未解析的外部符号——隐式 DLL [重复]

从 DLL 访问类成员(不是 LIB !!!)

VC++ LNK2001:仅在 64 位编译时无法解析外部符号