使用dlopen通过动态库调用函数
CMake构建环境下
目录结构如下:
.
├── CMakeLists.txt
├── include
│ └── add.h
├── main.cc
└── src
├── add.cc
└── CMakeLists.txt
2 directories, 5 files
./CMakeLists.txt
文件:
cmake_minimum_required(VERSION 3.14)
project(DLDEMO)
add_subdirectory(src)
include_directories(include)
add_executable(${PROJECT_NAME} main.cc)
target_link_libraries(${PROJECT_NAME} dl)
include/add.h
文件:
#ifndef __ADD_H_
#define __ADD_H_
#ifdef __cplusplus
extern "C" {
#endif
int add(int a, int b);
#ifdef __cplusplus
}
#endif
./main.cc
文件:
#include <dlfcn.h>
#include <iostream>
typedef int (*inc_func)(int, int);
int main() {
using namespace std;
const char *so_name = "src/libadd.so";
auto *dlhandle = dlopen(so_name, RTLD_LAZY);
if (dlhandle == NULL) {
cout << "ERROR open so";
return -1;
}
dlerror();
int a = 2, b = 3;
inc_func inc = (inc_func)dlsym(dlhandle, "add");
int res = inc(a, b);
cout << a << "+" << b << " = " << res;
dlclose(dlhandle);
cout << so_name << endl;
}
src/add.cc
文件:
#include "add.h"
int add(int a, int b) { return a + b; }
src/CMakeLists.txt
文件:
include_directories(${CMAKE_SOURCE_DIR}/include)
add_library(add SHARED add.cc)
编译并运行:
mkdir build && cmake .. && ./DLDEMO
使用命令行工具验证上述流程
.
├── include
│ └── add.h
├── main.cc
└── src
└── add.cc
命令:
clang++ src/add.cc -fPIC -shared -Iinclude -o src/libadd.so # 编译生成动态库
clang++ main.cc -ldl -o DLDEMO
问题
- 这里的dlopen为c调用,如果我的动态库为C++下的动态库代码能正常调用吗?
答案是可以,你可以修改头文件声明add.h
为:
#pragma once
int add(int a, int b);
然后重新编译运行源代码,这时候你会发现程序出现coredump.我们分别分析c和c++下生成的动态库信息可以看到:
我们可以看到C++下的符号表的名称变成了:_Z3addii
,所以直接调用add函数会找不到此符号,在源代码main.cc中将代码调用改成:
inc_func inc = (inc_func)dlsym(dlhandle, "_Z3addii");
程序将正常运行.