动态库使用实例:dlopen

动态库使用实例:dlopen

1, File main.c 

#include <dlfcn.h>
#include <stdio.h>

#define NONE         "\033[m"
#define RED          "\033[0;32;31m"

extern int g_count;

int main(int argc, char **argv)
{
        void* pdlhandle;
        char* pszerror;

        int (*mytest)(int num);

        pdlhandle = dlopen("./libtest.so", RTLD_LAZY);
        pszerror = dlerror();
        if (0 != pszerror)
        {
            printf("%s", pszerror);
            return 1;
        }

        mytest = dlsym(pdlhandle, "test");
        pszerror = dlerror();
        if (0 != pszerror)
        {
            printf("%s", pszerror);
            return 1;
        }

        mytest(3);   //defined in test.c (libtest.c)
        printf(RED"[%s %s]"NONE": g_count=%d\n",__FILE__, __FUNCTION__, g_count); //[%s %s]以红色打印

        dlclose(pdlhandle);
        return 0;
}

2, File test.c

#include "add.h"

#define NONE         "\033[m"
#define BLUE         "\033[0;32;34m"

int test(int num)
{
   add(num); //defined in add.c (libadd.so)
   printf(BLUE"[%s %s]"NONE": g_count=%d\n",__FILE__, __FUNCTION__, g_count); //[%s %s]以蓝色打印

   return 0;
}

3, File add.c

#include "add.h"

int   g_count;

int add(int num)
{
     g_count +=num;
     printf("[%s %s]: g_count=%d\n",__FILE__, __FUNCTION__, g_count);

     return 0;
}

4, File add.h

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

extern int g_count;
int add(int num);

5, Makefile


CROSS=
#CROSS=/gcc-4.2/arm-linux-
CC = $(CROSS)gcc
LDFLAGS = -L. -Wl,-rpath,./
LIBS = -ltest -ladd -ldl

OBJS   = main.o
DYNLIB = libadd.so libtest.so
TARGET = test

ALL: $(DYNLIB) $(TARGET)

$(TARGET): $(OBJS)
        $(CC) $(LDFLAGS) $(LIBS) $(OBJS) -o $(TARGET)

$(OBJS): main.c
        $(CC) -c $^ $<

$(DYNLIB):
        $(CC) -fPIC -shared add.c -o libadd.so 
        $(CC) -fPIC -shared test.c -o libtest.so 

clean:
        rm -f *.o
        rm -f *.so
        rm -f $(TARGET)

运行:
[guowenxue@15 ~/programe/dynamic-lib]$ make
gcc -fPIC -shared add.c -o libadd.so 
gcc -fPIC -shared test.c -o libtest.so 
gcc -c main.c main.c
gcc -L. -Wl,-rpath,./ -ltest -ladd -ldl main.o -o test
[guowenxue@15 ~/programe/dynamic-lib]$ ./test 
[add.c add]: g_count=3
[test.c test]: g_count=3
[main.c main]: g_count=3

注:
关于printf打印字符的颜色定义:
  1. #define NONE          "\033[m"
  2. #define RED           "\033[0;32;31m"
  3. #define LIGHT_RED     "\033[1;31m"
  4. #define GREEN         "\033[0;32;32m"
  5. #define LIGHT_GREEN   "\033[1;32m"
  6. #define BLUE          "\033[0;32;34m"
  7. #define LIGHT_BLUE    "\033[1;34m"
  8. #define DARY_GRAY     "\033[1;30m"
  9. #define CYAN          "\033[0;36m"
  10. #define LIGHT_CYAN    "\033[1;36m"
  11. #define PURPLE        "\033[0;35m"
  12. #define LIGHT_PURPLE "\033[1;35m"
  13. #define BROWN         "\033[0;33m"
  14. #define YELLOW        "\033[1;33m"
  15. #define LIGHT_GRAY    "\033[0;37m"
  16. #define WHITE         "\033[1;37m"


Makefile中 -Wl,-rpath,./ 将加载动态库的路径写到代码里,这就不需要使用 export LD_LIBRARY_PATH=./ 来指定查找共享库的路径。

libtest.so 依赖libadd.so, 这时在main()中调用dlopen()来加载libtest.so时,碰到不能解析的符号(g_count)时,他会加载libadd.so. 并不是自己之前天真地认为 ,dlopen()只会加载libtest.so, 而不去解析libadd.so中的符号.

之前在编译libmusclecard.so时, 由于在生成动态库时没有添加-lpcsclite这个选项,导致在Openvpn/pkcs11.c中使用dlopen()加载libmusclecard.so时出现错误:
can't resolve symbol 'g_rgSCardRawPci'
而g_rgSCardRawPci定义在libpcsclite.so中。

在开发板上可以使用ldd命令查看依赖的动态库:
/mnt/pcsclite >: ldd /usr/lib/libmusclecard.so
checking sub-depends for '/usr/lib/libpcsclite.so.1'
checking sub-depends for '/lib/libdl.so.0'
checking sub-depends for '/lib/libgcc_s.so.1'
checking sub-depends for '/lib/libpthread.so.0'
checking sub-depends for '/lib/libc.so.0'
        libpcsclite.so.1 => /usr/lib/libpcsclite.so.1 (0x00000000)
        libdl.so.0 => /lib/libdl.so.0 (0x00000000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00000000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x00000000)
        libc.so.0 => /lib/libc.so.0 (0x00000000)
        /lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x00000000)

而没有添加-lpcsclite的libmusclecard.so显示为:
/mnt/pcsclitebak >: ldd libmusclecard.so.1.0.0 
checking sub-depends for '/lib/libdl.so.0'
checking sub-depends for '/lib/libgcc_s.so.1'
checking sub-depends for '/lib/libpthread.so.0'
checking sub-depends for '/lib/libc.so.0'
        libdl.so.0 => /lib/libdl.so.0 (0x00000000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00000000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x00000000)
        libc.so.0 => /lib/libc.so.0 (0x00000000)
        /lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x00000000)

总结:
   在出现错误: can't resolve symbol 'XXXX' 时,不妨考虑是否有动态库忘记加载了!
   导处静态库libmusclecard中的符号列表: objdump -x libmusclecard.a > text
    将静态库中的目标文件解压缩出来: /gcc/arm-linux-ar -x libmusclecard.s
    查看静态库中包含了哪些目标文件:
[guowenxue@15 libmusclecard-1.3.3/src/.libs]$ /gcc-4.2/arm-linux-ar -t libmusclecard.a 
libmusclecard_la-debug.o
libmusclecard_la-musclecard.o
libmusclecard_la-tokenfactory.o
libmusclecard_la-tokenparser.o
libmusclecard_la-dyn_hpux.o
libmusclecard_la-dyn_macosx.o
libmusclecard_la-dyn_unix.o
libmusclecard_la-strlcpy.o
libmusclecard_la-strlcat.o
libmusclecard_la-thread_unix.o
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值