动态库的多重链库方法
因项目需要将c++接口进行封装成c接口调用,实现可执行文件(a.out)去链接b.so(封装的c接口),并且b.so依赖于c.so(c++接口)。
方法一:a.out隐式加载b.so,b.so隐式加载c.so;
源代码:
//cplus.cc 记为c++接口的源文件,编译生成libcplus.so
//g++ cplus.cc -o libcplus.so -shared -fPIC
#include <iostream>
int cplusfunc(std::string str, int n) {
std::cout << "str:" << str << std::endl;
std::cout << "n:" << n << std::endl;
return 0;
}
//cplus.h
#ifndef _CPLUS_H_
#define _CPLUS_H_
#include <iostream>
int cplusfunc(std::string str, int n);
#endif // _CPLUS_H_
//c.cc
//g++ c.cc -o libccc.so -shared -fPIC编译生成libccc.so
//注意了,此处不需要去链接libcplus.so,因为编译生成动态库时,编译器只关心本文件的函数实现,不会去关心
//函数内部调用的其他函数的实现,只需要保证其他函数的声明都能找到就行
#include "c.h"
#include "cplus.h"
#include<iostream>
int cfunc(char* ch, int n) {
std::string s = ch;
//此处调用c++接口库
cplusfunc(s, n);
}
//c.h
#ifndef _C_H_
#define _C_H_
extern "C"{
int cfunc(char* ch, int n);
}
#endif
//main.cc
//g++ main.cc -L./ -lccc -lcplus
//编译main函数的时候指定链接libccc.so与libcplus.so
#include <iostream>
//调用c.h头文件
#include "c.h"
int main() {
std::string s = "zheng";
char* ch =const_cast<char*>( s.c_str());
int k = 7;
cfunc(ch, k);
return 0;
}
方法二:a.out显示加载b.so,b.so隐式加载c.so;
这里对于cplus.h cplus.cc c.h c.cc几个文件都是一样的,唯一的区别就是main函数需要改成显示调用libccc.so
源代码:
//cplus.cc 记为c++接口的源文件,编译生成libcplus.so
//g++ cplus.cc -o libcplus.so -shared -fPIC
#include <iostream>
int cplusfunc(std::string str, int n) {
std::cout << "str:" << str << std::endl;
std::cout << "n:" << n << std::endl;
return 0;
}
//cplus.h
#ifndef _CPLUS_H_
#define _CPLUS_H_
#include <iostream>
int cplusfunc(std::string str, int n);
#endif // _CPLUS_H_
//c.cc
//g++ c.cc -o libccc.so -shared -fPIC编译生成libccc.so
//注意了,此处不需要去链接libcplus.so,因为编译生成动态库时,编译器只关心本文件的函数实现,不会去关心
//函数内部调用的其他函数的实现,只需要保证其他函数的声明都能找到就行
#include "c.h"
#include "cplus.h"
#include<iostream>
int cfunc(char* ch, int n) {
std::string s = ch;
//此处调用c++接口库
cplusfunc(s, n);
}
//这里使用extern "C"是方便main函数显示调用的时候不用考虑g++编译器改变函数名
//c.h
#ifndef _C_H_
#define _C_H_
extern "C"{
int cfunc(char* ch, int n);
}
#endif
//main.cc
//编译main函数的时候,因为libccc.so是显示加载调用的,所以编译的时候根本不用关心有没有libccc.so的存在,只需要在编译的时候加上-ldl即可。但是因为libccc.so又是隐式加载libcplus.so的,所以在编译main函数的时候,必须加上-lcplus,避免再main函数运行的时候找不到c++接口(cplusfunc)的实现。
// g++ main.cc -ldl -L./ -lcplus
#include <iostream>
#include "dlfcn.h"
typedef int(*Fun)(char*, int);
int main() {
void* handle;
Fun fun = NULL;
char* error;
handle = dlopen("./libccc.so", RTLD_LAZY);
if (!handle) {
std::cout << "error" << std::endl;
return 0;
}
dlerror();
fun = (Fun)dlsym(handle, "cfunc");
if ((error = dlerror()) != NULL) {
std::cout << "error" << error << std::endl;
return 0;
}
std::string s = "zheng";
char* ch = const_cast<char*>(s.c_str());
int k = 7;
fun(ch, k);
return 0;
}