加载共享库时自动执行的功能 [英] Automatically executed functions when loading shared libraries

查看:125
本文介绍了加载共享库时自动执行的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Windows中加载共享库时,LoadLibrary()调用将导致库中的DllMain对于每个新进程和线程库所附加,以及每个进程和线程库从其上附加执行.

When loading shared libraries in Windows, LoadLibrary() call causes DllMain in library to execute for each new process and thread library attaches to, and for each process and thread library deattaches from.

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

Is there similar mechanism for Mac OS X, Linux and possibly other POSIX-compatible OSs?

推荐答案

您可以使用.init机制为linux库定义一个加载函数.这与为二进制文件指定加载时间入口点相同(例如,使用main以外的东西作为程序的入口点).

You can define an on-load function for a linux library using the .init mechanism. This is the same as specifying the load-time entry point for a binary (e.g. using something other than main as the entry point for a program).

直接使用ld链接时,请使用:

When linking using ld directly you use the:

-init <function name>

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

or if you're using cc/gcc to link, you use:

-Wl,-init,<function name>

这是最简单的水平.

修改 对于析构函数/终结器,您可以使用.fini机制.此操作与init选项相同,并且您可以使用:

Edit For destructors/finalizers, you use the .fini mechanism. This operates in the same manner as the init option, and you use:

-fini <function name>

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

when invoking ld. Availability is limited to the -init option on the Mac OSX platform.

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

You should also be able to use the __attribute__((constructor)) syntax for gcc:

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

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

这可能是一种更便携的方法,而不是使用链接器选项.所有构造函数都应在加载时调用,但不要取决于其初始化顺序,这会导致精神错乱和无法再现的错误,从而浪费时间和精力进行调试.

Which is probably a more portable way rather than screwing with the linker options. All constructors should be invoked at load-time, but don't depend on the order of their initialization, that leads to insanity and unreproducible bugs that cost time and effort to debug.

编辑2 对于C/C ++编程语言,使用__attribute__((constructor))/__attribute__((destructor))语义是最可取的机制.

Edit 2 The use of the __attribute__((constructor))/__attribute__((destructor)) semantic is the most preferable mechanism for the C/C++ programming language.

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

For the D programming language you should really use the static module constructor/destructor:

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

编写win32 DLLS 和语言规范 编辑3 您将需要在.o中进行链接,以导出构造函数/析构函数例程,从而允许使用静态初始化程序.它应该做的只是调用Runtime.initialize(),实际上会调用D代码中的所有静态构造函数/析构函数.

Edit 3 You will need to link in a .o that exports constructor/destructor routines, that will allow the use of the static initializers. As all it should do is call Runtime.initialize(), this actually invokes all the static constructors/destructors in the D code.

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

Stub d code for the initializer (in a file called myshared.d):

import core.runtime;

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

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

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

为此存根创建.o:

 dmd -m32 -c myshared.d

检查附加/分离功能的名称:

Check the names of the attach/detach functions:

nm myshared.o

显示(在其他输出中):

Shows (among other output):

0000001c S _D8myshared6attachFZv
00000034 S _D8myshared6detachFZv

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

sample .c code for invoking this (called export.c in this case), we reference the names of the exported routines from the my shared.o file:

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引用需要使用导出函数的错误名称.这些必须匹配,否则代码将不会链接.

Note that the extern void references need to use the mangled name of the exported function. These must match or the code will not link.

使用以下命令编译C代码:

compile the C code using:

gcc -m32 -c export.c

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

link the .c.o and the .d.o files together using:

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

假设phobos2库位于您的标准链接程序搜索路径中.编译器和链接器的-m32选项很少,因为我在本地构建的D编译器版本仅支持32位.

Assuming that the phobos2 library is in your standard linker search path. The smatterings of -m32 options for the compiler and linker are because the version of the D compiler that I built locally only supported 32bit.

这将产生一个可以链接的.dylib.它似乎基于我执行的有限测试而起作用.似乎对共享库/动态库的支持非常有限,因此很有可能还会克服另一个障碍.

This produces a .dylib that can be linked to. It seems to work based on the limited testing I performed. It looks like support for shared objects/dynamic libraries is very limited, so there is a good chance that there will be another hurdle to overcome.

这篇关于加载共享库时自动执行的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆