so文件的编译与使用

C使用so文件

共写了两个c文件和两个h文件。

文件一:calculate.c
#include "min.h"
int max(int a,int b){
        return a>b?a:b;
}
int whoissmall(int a,int b){
        return min(a,b);
}

文件二:calculate.h
int max(int a,int b);
int whoissmall(int a,int b);

文件三:min.c
int min(int a,int b){
        return a<b?a:b;
}

文件四:min.h
int min(int a,int b);

方法一

  1. 利用以下命令将两个c文件生成一个so文件,此处生成的so文件为libcalculate.so,(so文件名要求前缀为lib,扩展名为so)
    gcc -shared -fPIC min.c calculate.c -o libcalculate.so。

  2. 接着新建一个main.c,其中用到了so文件中的calculate.c中实现的函数,需要将头文件include进来。

文件名:main.c
#include <stdio.h>
#include <stdlib.h>
#include "calculate.h"
int main() {
        printf("%d\n", whoissmall(1,2));
}
  1. 用以下命令编译,
gcc main.c -lcalculate -L testso/ -I testso/  -o main
1. -l代表所连接的so文件的名字,因为我这里用的是libcalculate.so,连接的时候需要去掉lib和.so。
2. -L是代表so文件所在的位置
3. -I是代表编译的c文件(这里是main.c)所include的头文件的位置。这里使用的whoissmall函数是calculate.c中实现的,所以include calculate.h。(同样,若想用min.h中的min函数,在main.c中include min.h即可)。

扩展:
1. 对于-L,可通过以下命令来添加gcc寻找so文件的位置。
export LIBRARY_PATH=/home/haimiao/testso:$LIBRARY_PATH 
这样编译的时候直接写gcc main.c -lcalculate -I testso/  -o main即可。
gcc在寻找so文件时的寻找顺序为-L > /lib和/usr/lib和/usr/local/lib > LIBRARY_PATH。
2. 对于-I ,gcc默认寻找头文件的位置/usr/include和本目录下,因而若希望找到头文件在别的目录下,需要加-I。 
  1. 直接运行main即可。

方法二

  1. 使用方法一的so文件,改写main.c。
main2.c

#include <stdio.h>
#include <dlfcn.h>
int main(){
        void* handle;
        int(*func) (int, int);
        char* error;
        handle = dlopen("libcalculate.so", RTLD_LAZY);
        if (!handle) {
                printf("%s\n", dlerror());
                return -1;
        }
        func = dlsym(handle, "whoissmall");
        if ((error = dlerror()) != NULL) {
                printf("%s\n", error);
                return -1;
        }
        printf("%d\n,", func(1, 2));
        return 0;
}

以下介绍所用到的函数:
包含头文件:
#include <dlfcn.h>
函数定义:
void * dlopen( const char * pathname, int mode );
函数描述:
在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。
mode:分为这两种
RTLD_LAZY 暂缓决定,等有需要时再解出符号
RTLD_NOW 立即决定,返回前解除所有未决定的符号。
RTLD_LOCAL
RTLD_GLOBAL 允许导出符号
RTLD_GROUP
RTLD_WORLD
返回值:
打开错误返回NULL
成功,返回库引用

void* dlsym(void* handle,const char* symbol)
该函数在<dlfcn.h>文件中。
handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用

dlerror()
包含头文件:
#include <dlfcn.h>
函数原型:
const char *dlerror(void);
函数描述:
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

dlclose()
包含头文件:
#include <dlfcn.h>
函数原型为:
int dlclose (void *handle);
函数描述:
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

  1. 编译时需要加上-ldl选项。
gcc main2.c -ldl 

若执行时报以下错误
在这里插入图片描述说明so文件找不到,需要设置一下LD_LIBRARY_PATH(为什么方法一时用LD_LIBRARY_PATH不行,只能用LIBRARY_PATH),如下

export LD_LIBRARY_PATH=/home/haimiao/testso:$LD_LIBRARY_PATH
其中冒号前是so文件所在位置,冒号是路径的分隔符。

使用这种方法不需要include头文件。

python使用so文件

这里使用的python版本为2.7.12

  1. 使用的so文件同样如上。改写main.py
from ctypes import cdll
cur = cdll.LoadLibrary('./libcalculate.so')
print cur.whoissmall(1,2)

直接执行即可。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值