Python调用C/C++之动态链接库(.dll)(vs2019+pycharm)

本文档详细介绍了如何在Windows环境下使用Visual Studio 2019创建C/C++动态链接库(DLL),并将其函数封装在其中。接着,文章演示了如何使用Python的ctypes库调用DLL中的函数,特别强调了数据类型转换的重要性。最后,提供了查看DLL函数的命令,并给出了Python调用DLL的示例代码。

  由于实验需要发送固定字节大小的数据,且python不太适合做底层,故使用c/c++来作为底层处理数据,记录一下整个过程。须知dll文件仅仅是windows系统下动态链接库,linux或mac系统下是另一种类型的文件,本文也仅在windows系统下使用vs2019编译生成动态链接库。

一.将C/C++函数封装成动态库(.dll)

  先给出vs官网给出的教学文档(我参考了官网的,但是按照流程生成dll之后dll文件内并没有封装的函数,可能是我哪一步出错了,大家可以按照教学去试一试):
https://docs.microsoft.com/zh-cn/cpp/build/dlls-in-visual-cpp?view=msvc-170

  下面介绍我的整个流程:
  1.创建编译dll文件的项目,在上面的官网介绍的更详细,这里就不多做介绍了。注意在vs之中新建一个项目,项目选择动态链接库(DLL)
在这里插入图片描述
  2.在源文件中添加cpp文件并写好函数,例如我简单写了一个加法(add)函数:

#include "pch.h"      //导入该文件是编译提醒,不加会报错
#include<iostream>   

#define MATHLIBRARY_API extern "C" __declspec(dllexport)   //主要就是加入这个宏定义

 MATHLIBRARY_API int add(int x, int y)   //在自己的函数前面加上定义的宏名,在编译成dll文件时就能将该函数加入动态链接库
{
	return x + y;
}

  3.根据自己的系统及需要选择平台,然后生成解决方案即可。我的python是64位的,所以选择x64。若不匹配,在python端调用该dll文件就会报错。
在这里插入图片描述
  4.如果生成成功,则在该项目的路径下会产生一个x64的文件夹,在该文件夹的debug里面就有dll文件,至此生成动态链接库就完成了。下面再教大家如何查看该dll文件是否有我们的函数。
  打开VS2019的 developer powershell
在这里插入图片描述
  输入下面命令就能查看到该dll文件内有哪些函数

dumpbin /exports  绝对路径(C:\Users\source\repos\Mathlibrary\x64\Debug\Mathlibrary.dll)

在这里插入图片描述

二.Python调用动态链接库(dll)

  Python调用dll文件需要用到ctypes库,这个库并不需要下载,python3就已经自带了。将生成的dll文件复制到python项目下,一定要和调用dll文件的python文件在同一个目录下。

import ctypes
from ctypes import *

mydll = CDLL("./demo.dll")    # 一定要有./ 否则无法调用成功
result = mydll.add(1, 2)      
print(result)

  上面的代码就实现了调用c/c++动态链接库内的add函数,需要注意在c++中定义add函数传入的变量是int类型,在python之中就不需要转换类型。但是如果定义add函数传入的变量是float类型,那么python端就需要先将数值转换为c_float类型:

import ctypes
from ctypes import *

mydll = CDLL("./demo.dll")    # 一定要有./ 否则无法调用成功
result = mydll.add(ctypes.c_float(1.345), ctypes.c_float(2.232))
print(result)

  所以利用ctypes调用dll动态链接库需要注意C/C++函数传入变量的数据类型。下面给大家列出了ctypes、C/C++、python对应的数据类型,大家按照自己函数的需要转换类型:
在这里插入图片描述
  如果C/C++返回的是指针类型的呢,辣么就需要在调用函数前告知python返回的数据的类型

import ctypes
from ctypes import *

mydll = CDLL("./demo.dll")    # 一定要有./ 否则无法调用成功
mydll.couculate.restype = POINTER(c_int)   #声明返回的数据类型为整数指针
result = mydll.add(ctypes.c_float(1.345), ctypes.c_float(2.232))
# 如果返回的数组指针,就在转化为list,[0:8]表示数组8个数据
# result = list(mydll.add(ctypes.c_float(1.345), ctypes.c_float(2.232))[0:8])
print(result)

  暂时就这些了,我对数据类型的转换也很头大,写的也可能不太清楚、有错或者遗漏,希望大家指导。

<think>我们正在处理一个系统环境问题:当Python调用C++编译的.so共享库时,出现`libstdc++.so.6: version 'GLIBCXX_3.4.32' not found`错误。这个错误通常是因为系统中用于运行环境的libstdc++库版本低于编译.so文件时使用的g++版本所要求的版本。 根据引用[1][2][3]中的经验,我们可以通过以下步骤解决: 1. **确认问题**:错误信息表明运行时需要的GLIBCXX_3.4.32版本在当前的libstdc++.so.6中不存在。 2. **查找系统中是否存在更高版本的libstdc++库**:通常,我们可以通过更新系统或安装更高版本的gcc来获得,但有时我们也可以从其他位置(如Anaconda环境)找到。 3. **替换或更新软链接**:将libstdc++.so.6指向一个包含所需版本GLIBCXX的库文件。 具体步骤: ### 步骤1:检查当前libstdc++.so.6提供的GLIBCXX版本 在终端执行: ```bash strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX ``` 或者,如果错误提示的是其他路径,则检查该路径下的对应文件。 ### 步骤2:查找系统中是否包含所需版本的库文件 使用`locate`命令查找所有libstdc++.so.6文件: ```bash sudo updatedb # 更新数据库(如果locate命令找不到新文件) locate libstdc++.so.6 ``` 然后逐一检查这些文件是否包含`GLIBCXX_3.4.32`: ```bash strings /path/to/libstdc++.so.6 | grep GLIBCXX_3.4.32 ``` ### 步骤3:替换软链接 假设我们在`/usr/lib/x86_64-linux-gnu/`目录下找到了一个包含`GLIBCXX_3.4.32`的库文件(例如`libstdc++.so.6.0.32`),那么我们可以按照以下步骤操作: 1. 备份原来的软链接(可选): ```bash sudo mv /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.bak ``` 2. 创建新的软链接: ```bash sudo ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.32 /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ``` 注意:如果错误发生在其他路径(例如在Anaconda环境中),则需要在对应的路径下进行替换。例如,如果错误发生在Anaconda环境中,那么可能需要操作Anaconda目录下的lib目录(如`/home/username/anaconda3/lib`)中的文件。 ### 步骤4:验证 再次运行Python程序,看是否解决问题。 ### 备选方案:更新系统gcc 如果系统中没有找到包含所需GLIBCXX版本的库文件,那么可能需要更新gcc编译器。 对于Ubuntu系统,可以添加PPA安装最新版gcc: ```bash sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt update sudo apt install gcc-12 g++-12 ``` 安装完成后,新的libstdc++库通常位于`/usr/lib/gcc/x86_64-linux-gnu/12`(版本号可能不同)目录下。然后可以将该目录下的`libstdc++.so.6`复制(或软链接)到系统库目录,或者将新库的路径添加到`LD_LIBRARY_PATH`中。 ### 备选方案:使用Anaconda的库 如果使用Anaconda,可以尝试安装`libgcc`包来更新环境中的libstdc++: ```bash conda install -c conda-forge libgcc ``` 这会将较新的libstdc++安装到Anaconda的lib目录中,然后Anaconda环境中的程序会优先使用该目录下的库。 ### 注意事项 - 在替换系统库文件时要小心,因为可能会影响其他程序的运行。建议在替换前备份。 - 如果是在多用户系统上,最好与系统管理员协商。 ### 总结 出现`GLIBCXX_3.4.32 not found`错误的原因是运行时链接的libstdc++.so.6版本过旧。通过更新软链接指向一个包含所需版本的库文件即可解决。解决过程中需要找到包含所需GLIBCXX版本的库文件,然后调整软链接。 §§相关问题§§ 1. 如何检查Linux系统中已安装的GLIBC版本? 2. 如何安全地升级Ubuntu系统中的gcc编译器? 3. 在Anaconda环境中如何管理共享库依赖? 4. 如何设置LD_LIBRARY_PATH环境变量以优先使用特定路径的共享库? 5. 编译C++共享库时如何指定依赖库的路径?</think>### 解决Python调用C++共享库时`GLIBCXX_3.4.32 not found`错误 当Python调用C++编译的.so文件时出现`libstdc++.so.6: version 'GLIBCXX_3.4.32' not found`错误,这通常是因为系统使用的libstdc++库版本低于编译.so文件所需的版本。以下是完整的解决步骤: #### 1. **确认问题根源** ```bash # 查看当前libstdc++.so.6支持的GLIBCXX版本 strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX # 检查错误信息中指定的库文件 strings /path/to/problem/libstdc++.so.6 | grep GLIBCXX_3.4.32 ``` 如果输出中不包含`GLIBCXX_3.4.32`,则确认是版本缺失问题[^1][^2]。 #### 2. **查找包含所需版本的库文件** ```bash # 搜索系统中所有libstdc++.so.6文件 sudo updatedb # 更新文件数据库 locate libstdc++.so.6 # 检查每个文件是否包含所需版本 strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX_3.4.32 strings /path/to/anaconda/lib/libstdc++.so.6 | grep GLIBCXX_3.4.32 ``` #### 3. **替换或更新库文件(三种方案)** **方案一:使用Anaconda中的库文件(推荐)** ```bash # 1. 找到Anaconda中的libstdc++.so.6.0.32 sudo find / -name "libstdc++.so.6.0.32" 2>/dev/null # 2. 复制到系统库目录 sudo cp /path/to/anaconda/lib/libstdc++.so.6.0.32 /usr/lib/x86_64-linux-gnu/ # 3. 重建软链接 sudo rm /usr/lib/x86_64-linux-gnu/libstdc++.so.6 sudo ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.32 /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ``` **方案二:更新系统GCC编译器** ```bash # 添加Ubuntu Toolchain PPA sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt update # 安装GCC 12(支持GLIBCXX_3.4.32) sudo apt install gcc-12 g++-12 # 更新系统默认编译器 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 100 ``` **方案三:仅针对Python环境修复** ```bash # 在Python环境中指定库路径 export LD_LIBRARY_PATH=/path/to/anaconda/lib:$LD_LIBRARY_PATH # 或永久添加到~/.bashrc echo 'export LD_LIBRARY_PATH=/path/to/anaconda/lib:$LD_LIBRARY_PATH' >> ~/.bashrc source ~/.bashrc ``` #### 4. **验证修复结果** ```bash # 检查新库支持的版本 strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX_3.4.32 # 测试Python调用 python -c "import ctypes; ctypes.CDLL('./your_library.so')" ``` #### 5. **预防措施** 1. **编译时指定兼容性**: ```bash g++ -shared -fPIC source.cpp -o libexample.so \ -static-libstdc++ # 静态链接C++标准库 ``` 2. **控制编译环境**: ```bash # 使用Docker保持编译环境一致性 docker run -v $(pwd):/src -it ubuntu:20.04 \ bash -c "apt update && apt install -y g++ && g++ -shared -fPIC /src/source.cpp -o /src/libexample.so" ``` 3. **版本兼容性检查**: ```bash # 查看.so文件依赖 ldd your_library.so # 查看符号版本要求 objdump -p your_library.so | grep GLIBCXX ``` > **关键提示**:如果使用Anaconda,运行`conda update libgcc`可自动解决环境内的库版本问题[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值