Linux之动态链接库

    xiaoxiao2021-03-25  94

    Linux下创建与使用动态库

     

    linux动态库的命名规则

    动态链接库的名字形式为 libxxx.so,前缀是lib,后缀名为“.so”。

    l  针对于实际库文件,每个共享库都有个特殊的名字“soname”。在程序启动后,程序通过这个名字来告诉动态加载器该载入哪个共享库。

    l  在文件系统中,soname仅是一个链接到实际动态库的链接。对于动态库而言,每个库实际上都有另一个名字给编译器来用。它是一个指向实际库镜像文件的链接文件(lib+soname+.so)。

    创建动态库(.so

    编写四则运算动态库代码:

    DynamicMath.h头文件

    #pragma once

    class DynamicMath

    {

    public:

            DynamicMath(void);

            ~DynamicMath(void);

     

            static double add(double a, double b);//¼Ó·¨

            static double sub(double a, double b);//¼õ·¨

            static double mul(double a, double b);//³Ë·¨

            static double div(double a, double b);//³ý·¨

            void print();

    };

     

    l  首先,生成目标文件,此时要加编译器选项-fpic

    g++ -fPIC -c DynamicMath.cpp

    -fPIC 创建与地址无关的编译程序(picposition independent code),是为了能够在多个应用程序间共享。

    l  然后,生成动态库,此时要加链接器选项-shared

    g++ -shared -o libdynmath.so DynamicMath.o

    -shared指定生成动态链接库。

    其实上面两个步骤可以合并为一个命令:

    g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp

     

    使用动态库

    编写使用动态库的测试代码:

    测试代码:

    #include "../DynamicLibrary/DynamicMath.h"

     

    #include

    using namespace std;

     

    int main(int argc, char* argv[])

    {

        double a = 10;

        double b = 2;

     

        cout << "a + b = " << DynamicMath::add(a, b) << endl;

        cout << "a - b = " << DynamicMath::sub(a, b) << endl;

        cout << "a * b = " << DynamicMath::mul(a, b) << endl;

        cout << "a / b = " << DynamicMath::div(a, b) << endl;

     

        DynamicMath dyn;

        dyn.print();

        return 0;

    }

    引用动态库编译成可执行文件(跟静态库方式一样):

    g++ TestDynamicLibrary.cpp -L../DynamicLibrary -ldynmath

    然后运行:./a.out,发现竟然报错了!!!

    可能大家会猜测,是因为动态库跟测试程序不是一个目录,那我们验证下是否如此:

    发现还是报错!!!那么,在执行的时候是如何定位共享库文件的呢?

    1)        当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)

    2)        对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH/etc/ld.so.cache文件列表—/lib/,/usr/lib 目录找到库文件后将其载入内存。

    如何让系统能够找到它:

    l  如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。

    l  如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下:

    n  编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

    n  运行ldconfig ,该命令会重建/etc/ld.so.cache文件

    我们将创建的动态库复制到/usr/lib下面,然后运行测试程序。

    Linux下显式调用动态库

    #include ,提供了下面几个接口:

    l  void * dlopen( const char * pathname, int mode ):函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。

    l  void* dlsym(void* handle,const char* symbol)dlsym根据动态链接库操作句柄(pHandle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。

    l  int dlclose (void *handle)dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0,才会真正被系统卸载。

    l  const char *dlerror(void):当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

    本文转自:http://www.cnblogs.com/skynet/p/3372855.html

    转载请注明原文地址: https://ju.6miu.com/read-35175.html

    最新回复(0)