#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打印字符的颜色定义:
- #define NONE "\033[m"
- #define RED "\033[0;32;31m"
- #define LIGHT_RED "\033[1;31m"
- #define GREEN "\033[0;32;32m"
- #define LIGHT_GREEN "\033[1;32m"
- #define BLUE "\033[0;32;34m"
- #define LIGHT_BLUE "\033[1;34m"
- #define DARY_GRAY "\033[1;30m"
- #define CYAN "\033[0;36m"
- #define LIGHT_CYAN "\033[1;36m"
- #define PURPLE "\033[0;35m"
- #define LIGHT_PURPLE "\033[1;35m"
- #define BROWN "\033[0;33m"
- #define YELLOW "\033[1;33m"
- #define LIGHT_GRAY "\033[0;37m"
- #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