加载共享库
当在Windows加载共享库时自动执行功能,LoadLibrary()
调用导致DllMain
库执行为每个新进程和线程库重视,并为每个进程和线程库deattaches。加载共享库
是否有类似的机制,适用于Mac OS X,Linux和其他可能的POSIX兼容的操作系统?
您可以定义一个带载功能使用.init
机制的Linux库。这与指定二进制文件的加载时间入口点相同(例如,使用除main以外的内容作为程序的入口点)。
当使用ld
链接直接使用:
-init <function name>
,或者如果你正在使用CC/gcc的链接,您可以使用:
-Wl,-init,<function name>
这是在它的最简单的层面。
编辑 对于析构函数/终结器,可以使用.fini
机制。这个工作在相同的方式初始化选项,并使用:
-fini <function name>
调用ld
时。可用性仅限于Mac OSX平台上的-init
选项。
你也应该能够使用__attribute__((constructor))
语法GCC:
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
代码中的所有静态构造函数/析构函数。用于初始化
存根d代码(在一个名为myshared.d
):
dmd -m32 -c myshared.d
检查的附加/分离功能的名称:
import core.runtime;
extern (C) {
void attach();
void detach();
}
export void attach() {
Runtime.initialize();
}
export void detach() {
Runtime.terminate();
}
这个存根创建的.o: (其他输出):
用于调用这个(在这种情况下,所谓的export.c)0000001c S _D8myshared6attachFZv
00000034 S _D8myshared6detachFZv
样本.C代码,我们引用了出口程序的名称从my shared.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。它似乎基于我执行的有限测试工作。看起来对共享对象/动态库的支持非常有限,所以很有可能会有另一个障碍需要克服。
看来你的解决方案对我来说是最可以接受的,因为我用D编写而不用C编写,而且你的解决方案不涉及GCC特定的东西。在这些构造函数和析构函数中唯一要调用的是D运行时初始化和终止。 – toriningen 2012-03-18 17:18:39
你还可以提示,指定析构函数的ld标志是什么? – toriningen 2012-03-18 17:20:13
终结器/析构函数的等价物是使用-fini 选项。 – Petesh 2012-03-18 21:03:41
要具有每当共享库加载或卸载执行的功能,则可以使用特定GCC-属性语法标记构造和析构函数:
__attribute__((constructor)) void init(void) { ... }
__attribute__((destructor)) void fini(void) { ... }
因为一个C环境的各个部分依赖于事被GCC在后台添加的标准.init
代码初始化后,直接使用-Wl,-init,<function name>
可能会导致你的程序崩溃。
欲了解更多信息,请参阅Library constructor and destructor functions的Libary HOWTO。
对于C++,您可以创建一个类并使用其构造函数和析构函数初始化该库。
之后,你只需要为这个类定义一个变量。在图书馆
实例初始化的OpenSSL:
class InitLibrary {
public:
InitLibrary() {
CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use
SSL_library_init(); // Initialize OpenSSL's SSL libraries
SSL_load_error_strings(); // Load SSL error strings
ERR_load_BIO_strings(); // Load BIO error strings
OpenSSL_add_all_algorithms(); // Load all available encryption algorithms
}
~InitLibrary() {
ERR_remove_state(0);
CRYPTO_cleanup_all_ex_data();
ENGINE_cleanup();
}
};
和只添加这行CPP文件: InitLibrary InitLib;
https://*.com/q/2053029/4361073 – parasrish 2018-01-08 10:07:35