Python3.7调用C++动态库遇OSError内存访问违规问题求助
解决Python调用C++共享库时的访问违规问题
问题原因
- 参数不匹配:
main函数要求两个参数int argc和char* argv[],你调用时只传了一个字符串,导致argc被赋予随机值,argv[1]访问非法内存,触发访问违规。 - C++名字修饰:C++编译器会对函数名进行修饰(比如
main会变成类似_Z4mainiPPc的符号),ctypes无法直接通过main找到正确的函数入口。 - 字符串类型不兼容:Python默认字符串是Unicode,直接传递会和C的
char*类型不匹配,需要转换为字节串。
解决方案
推荐不要用main作为共享库导出函数,而是编写专门的导出函数并禁用C++名字修饰,具体步骤如下:
1. 修改C++代码
编写专用的导出函数,用extern "C"避免名字修饰:
#include <iostream> extern "C" { // 定义简单的导出函数,接收const char*类型参数 void say_hello(const char* name) { std::cout << "hello," << name << std::endl; } }
2. 编译共享库
执行编译命令生成共享库:
g++ -shared -Wl,-soname,hello -o hello.so -fPIC hello.cpp
3. Python调用代码
正确传递字节串参数,并指定函数参数类型:
import ctypes as C # 加载共享库 so = C.cdll.LoadLibrary("./hello.so") # 明确指定函数的参数类型,避免类型不匹配 so.say_hello.argtypes = [C.c_char_p] # 传递字节串(对应C的const char*) so.say_hello(b"world")
若坚持调用main函数(不推荐)
如果一定要调用main,需要严格匹配参数类型和数量:
import ctypes as C from ctypes import POINTER so = C.cdll.LoadLibrary("./hello.so") # 声明main函数的参数类型和返回值 so.main.argtypes = [C.c_int, POINTER(C.c_char_p)] so.main.restype = C.c_int # 构造argv数组:第一个元素是程序名(可随意填写),第二个是你的参数 argv = (C.c_char_p * 2)() argv[0] = b"hello" argv[1] = b"world" # 调用main,传入argc=2和构造好的argv so.main(2, argv)
内容的提问来源于stack exchange,提问作者hljjj
相关产品推荐
相关产品推荐

