首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

linux c++ 调用.so

Linux C++ 调用 .so 文件的基础概念

在Linux系统中,.so 文件是共享库(Shared Object)的扩展名,类似于Windows中的DLL文件。共享库是一种可以被多个程序同时使用的库文件,它允许程序在运行时动态加载和链接库中的函数和数据。

相关优势

  1. 节省内存:多个程序可以共享同一个库的内存副本,从而减少内存占用。
  2. 便于更新和维护:库文件可以独立于应用程序进行更新,而不需要重新编译整个程序。
  3. 提高可移植性:共享库可以在不同的系统和架构上使用,只要它们遵循相同的接口规范。

类型

  • 静态库.a):在编译时链接到程序中,成为程序的一部分。
  • 动态库.so):在运行时加载到内存中,可以被多个程序共享。

应用场景

  • 大型软件系统:将功能模块化,便于管理和维护。
  • 插件系统:允许第三方开发者编写扩展功能。
  • 性能优化:通过延迟加载某些模块来提高启动速度。

调用 .so 文件的方法

1. 编译时链接

在编译时指定库文件的位置和名称:

代码语言:txt
复制
g++ -o my_program my_program.cpp -L/path/to/library -lmylib
  • -L 指定库文件的搜索路径。
  • -l 指定库文件的名称(去掉前缀 lib 和后缀 .so)。

2. 运行时加载

使用 dlopen, dlsym, 和 dlclose 函数在运行时动态加载和使用库:

代码语言:txt
复制
#include <dlfcn.h>
#include <iostream>

int main() {
    // 打开共享库
    void* handle = dlopen("/path/to/library/libmylib.so", RTLD_LAZY);
    if (!handle) {
        std::cerr << "Cannot open library: " << dlerror() << std::endl;
        return 1;
    }

    // 清除之前的错误
    dlerror();

    // 获取函数指针
    typedef int (*my_function_t)(int, int);
    my_function_t my_function = (my_function_t)dlsym(handle, "my_function");
    const char* dlsym_error = dlerror();
    if (dlsym_error) {
        std::cerr << "Cannot load symbol 'my_function': " << dlsym_error << std::endl;
        dlclose(handle);
        return 1;
    }

    // 调用函数
    int result = my_function(10, 20);
    std::cout << "Result: " << result << std::endl;

    // 关闭共享库
    dlclose(handle);
}

常见问题及解决方法

1. 找不到库文件

原因:库文件路径未正确指定或库文件不存在。

解决方法

  • 确保库文件存在于指定路径。
  • 使用 LD_LIBRARY_PATH 环境变量添加库文件搜索路径:
  • 使用 LD_LIBRARY_PATH 环境变量添加库文件搜索路径:

2. 符号未定义

原因:库文件中不存在指定的函数或变量。

解决方法

  • 确保库文件中确实包含所需的符号。
  • 使用 nm 工具检查库文件中的符号:
  • 使用 nm 工具检查库文件中的符号:

3. 版本冲突

原因:系统中存在多个版本的库文件,导致链接错误。

解决方法

  • 使用 ldconfig 工具管理库文件的缓存:
  • 使用 ldconfig 工具管理库文件的缓存:
  • 在编译时明确指定库文件的版本。

示例代码

假设有一个简单的共享库 libmylib.so,其中包含一个函数 int add(int a, int b)

库文件 (mylib.cpp)

代码语言:txt
复制
extern "C" int add(int a, int b) {
    return a + b;
}

编译库文件

代码语言:txt
复制
g++ -shared -fPIC -o libmylib.so mylib.cpp

主程序 (main.cpp)

代码语言:txt
复制
#include <dlfcn.h>
#include <iostream>

int main() {
    void* handle = dlopen("./libmylib.so", RTLD_LAZY);
    if (!handle) {
        std::cerr << "Cannot open library: " << dlerror() << std::endl;
        return 1;
    }

    dlerror();

    typedef int (*add_t)(int, int);
    add_t add = (add_t)dlsym(handle, "add");
    const char* dlsym_error = dlerror();
    if (dlsym_error) {
        std::cerr << "Cannot load symbol 'add': " << dlsym_error << std::endl;
        dlclose(handle);
        return 1;
    }

    int result = add(10, 20);
    std::cout << "Result: " << result << std::endl;

    dlclose(handle);
}

编译主程序

代码语言:txt
复制
g++ -o main main.cpp -ldl

通过以上步骤,你可以在Linux系统中成功调用 .so 文件。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Java调用so文件

---- 公司的硬件让我帮忙调用一个so文件,想着一直都没机会自己写一个jni,于是就答应了,在调用的过程中还踩了不少坑,特地写一篇博客记录一下。...---- 一、使用技术 原本是想直接用java自带的jni,但是我们硬件只给了一个so文件,而且里面的函数命名等规则不符合java的jni调用标准,于是就打算使用框架jna来调用。...,查看调用结果 四、将项目部署到Linux 我将项目直接部署到Linux是无法正常运行的,需要修改 Clibrary.java 类,因为Linux下使用getResource()方法获取到的路径是正确的...,只有在Windows上调用getResource()方法才会多出一条斜杠,所以在Linux下需要将类中的.subString(1)方法的调用删掉,为了让代码兼容Windows和Linux操作系统,我将...但在代码运行时,还是报错了: 参考王小草的博客,发现在Windows下生成的so文件是无法在Linux上运行的,因为不同系统生成的文件的ELF header可能是不一样的,所以让硬件工程师在Linux

9.5K11
  • Android如何调用so文件

    使用C\C++开发的代码通常编译成so文件对外提供,以便在安卓或其他类型平台上使用。...下面通过一个安卓调用C++代码打印字符串的实例介绍一下在Android Studio中使用最新的编译方式编译出so文件的步骤。 第一步:新建工程 新建工程:打开AS,新建工程。 ? ?...第二步:JNI编程 JNI是java调用C\C++代码的接口定义规范,是实现安卓调用C\C++代码必不可少的一部分,下面是本实例中JNI实现相关代码。...第三步:配置编译文件 Gradle需要通过调用CMake编译脚本将C\C++代码编译为java可以调用的外部链接库,所以接下来需要进行Gradle和CMake的配置。...调用JNI:现在在我们声明的getHelloString()方法之前加载刚才声明产生的so库,然后再在程序中调用getHelloString()方法就可以执行so库中对应的C++代码了。 ?

    10.6K81

    unidbg调用so文件生成xgorgon

    也用过 jtype 启动JVM,然后通过 native 对so文件进行调用,因为每次都需要启动JVM,所以效率也不高。...unidbg 他不需要运行 app,也无需逆向 so 文件,通过在 app 中找到对应的 JNI 接口,然后用 unicorn 引擎直接调用 so 文件,所以效率相对要高不少。...《抖音xgorgon(0401)》 下面准备调用libcms.so文件中的 leviathan 函数 首先在 src/test/resources 目录下新建文件夹dylib,放入libcms.so文件...“leviathan(II[B)[B” 需要调用的函数名,名字是smali语法,可通过jadx等工具查看 “vm.loadLibrary(new File)” so文件的路径,需要自行修改,最好为绝对路径...; import com.github.unidbg.linux.android.AndroidResolver; import com.github.unidbg.linux.android.dvm.

    3.3K30

    linux 什么是SO文件

    下面的内容大多都是连接中的,穿插我自己的笔记 牵扯到ELF格式,gcc编译选项待补,简单实用的说明一下,对Linux下的so文件有个实际性的认识。 1.so文件是什么?...———————————————————————- 链接:得到输出文件libs.so gcc -g -shared -Wl,-soname,libs.so -o libs.so libs.o -lc...这个特性使得在Linux下,升级使得共享库的程序和定位错误变得十分容易。   ...在Linux中,应用程序通过使用soname,来指定所希望库的版本,库作者可以通过保留或改变soname来声明,哪些版本是兼容的,这使得程序员摆脱了共享库版本冲突问题的困扰。...下面的还没细看,汗 4.库的初始化,解析: windows下的动态库加载,卸载都会有初始化函数以及卸载函数来完成库的初始化以及资源回收,linux当然也可以实现。

    5.8K20

    python调用调用Linux命令

    如何调用Linux命令 下面代码演示了调用一个shell命令, 其中,命令的输出会存储到result变量中, 而命令的返回值,则存储到exitcode中,由此可见,调用shell命令还是很方便的: import...C/C++ 写一个c++文件api.cpp: #include class MyClass { public:     int add(int x,int y) { return...++ -fPIC api.cpp -o api.so -shared -I/usr/include/python2.7 -I/usr/lib/python2.7/config 在python中调用add...函数: import ctypes plib = ctypes.CDLL('/tmp/api.so') print "result: %d" %(plib.add(1,2)) 系统调用 虽然需求好像有点...“过份”,但是强大的python是可以调用诸如ioctl这类的Linux系统调用的, 以下的例子是让蜂鸣器响: import fcntl fd = open('/dev/pwm', 'r') fcntl.ioctl

    5.2K20

    c#封装动态库_nginx调用so动态库

    库一般分为两种:静态库(.a 、.lib)动态库(.so 、.dll )所谓静态、动态是指链接过程。 3、静态库与动态库 区别: (1)lib是编译时用到的,dll是运行时用到的。...DLL即动态链接库(Dynamic-Link Libaray)的缩写,相当于Linux下的共享对象。Windows系统中大量采用了DLL机制,甚至内核的结构很大程度依赖与DLL机制。...(1)导出与导入 在ELF(Linux下动态库的格式),共享库中所有的全局函数和变量在默认情况下都可以被其他模块使用,即ELF默认导出所有的全局符号。...指定符号的导入导出一般有如下两种方法: 1)MSVC编译器提供了一系列C/C++的扩展来指定符号的导入导出,即__declspec属性关键字。...MYDLL_API被设置为 __declspec(dllexport)修饰符,This modifier enables the function to be exported by the DLL so

    2.8K20
    领券