gpt4 book ai didi

posix - 加载共享库时自动执行的函数

转载 作者:行者123 更新时间:2023-12-03 06:50:47 25 4
gpt4 key购买 nike

在 Windows 中加载共享库时,LoadLibrary() 调用会导致库中的 DllMain 为附加到的每个新进程和线程以及每个进程和线程执行库脱离。

Mac OS X、Linux 以及其他可能兼容 POSIX 的操作系统是否有类似的机制?

最佳答案

您可以使用 .init 机制为 Linux 库定义加载函数。这与指定二进制文件的加载时入口点相同(例如,使用 main 之外的其他内容作为程序的入口点)。

直接使用ld链接时,您可以使用:

-init <function name>

或者如果您使用 cc/gcc 进行链接,则可以使用:

-Wl,-init,<function name>

这是最简单的级别。

编辑对于析构函数/终结器,您可以使用 .fini 机制。它的操作方式与 init 选项相同,您可以使用:

-fini <function name>

调用ld时。可用性仅限于 Mac OSX 平台上的 -init 选项。

您还应该能够使用 gcc 的 __attribute__((constructor)) 语法:

static void con() __attribute__((constructor));

void con() {
printf("I'm a constructor\n");
}

这可能是一种更便携的方式,而不是搞乱链接器选项。所有构造函数都应该在加载时调用,但依赖于它们的初始化顺序,这会导致疯狂和不可重现的错误,从而花费时间和精力进行调试。

编辑 2 使用 __attribute__((constructor))/__attribute__((destructor)) 语义是 C/C++ 编程语言最优选的机制。

对于 D 编程语言,您应该真正使用静态模块构造函数/析构函数:

static this() {
printf("static this for mymodule\n");
}
static ~this() {
printf("static ~this for mymodule\n");
}

或者静态类构造函数:

class Foo {
static this() {
printf("static this for Foo\n");
}
}

writing win32 DLLS 中强烈暗示了这一点并在语言规范中 relating to static constructors/destructors .

编辑 3 您需要链接导出构造函数/析构函数例程的 .o,这将允许使用静态初始值设定项。由于它应该做的就是调用 Runtime.initialize(),这实际上调用了 D 代码中的所有静态构造函数/析构函数。

初始化程序的 stub 代码(在名为 myshared.d 的文件中):

import core.runtime;

extern (C) {
void attach();
void detach();
}

export void attach() {
Runtime.initialize();
}

export void detach() {
Runtime.terminate();
}

为此 stub 创建 .o:

 dmd -m32 -c myshared.d

检查附加/分离函数的名称:

nm myshared.o

显示(以及其他输出):

0000001c S _D8myshared6attachFZv
00000034 S _D8myshared6detachFZv

用于调用此示例的 .c 代码(在本例中称为export.c),我们从 myshared.o 文件引用导出例程的名称:

extern void D8myshared6attachFZv(void);
extern void D8myshared6detachFZv(void);

void __attach(void) __attribute__((constructor));
void __detach(void) __attribute__((destructor));

void __attach(void)
{
D8myshared6attachFZv();
}

void __detach(void)
{
D8myshared6detachFZv();
}

请注意,extern void 引用需要使用导出函数的损坏名称。这些必须匹配,否则代码将无法链接。

使用以下方式编译 C 代码:

gcc -m32 -c export.c

使用以下方法将 .c.o 和 .d.o 文件链接在一起:

cc -o libmyshared.dylib -m32 -shared myshared.o export.o -lphobos2

假设 phobos2 库位于您的标准链接器搜索路径中。编译器和链接器的-m32选项的一些问题是因为我本地构建的D编译器版本仅支持32位。

这会生成一个可以链接到的 .dylib。根据我进行的有限测试,它似乎有效。看起来对共享对象/动态库的支持非常有限,因此很可能还会有另一个障碍需要克服。

关于posix - 加载共享库时自动执行的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9759880/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com