解决python调用c/c++的.so库的段错误问题,和python调c/c++库要点

python中使用ctypes模块可以在python中直接调用C/C++。
首先要将C/C++编译成动态库(.so),之后python中调用即可

特别注意在调用C++函数需要在函数声明时,加入前缀“ extern “C” ”,这是由于C++支持函数重载功能,在编译时会更改函数名。在函数声明时,前缀extern "C"则确保按C的方式编译。

值得注意的是,一定要有函数输入输出类型的声明,int型不用转换,float和double类型需要进行转换,
ctypes中的变量类型与C中对应如下:

ctypes数据类型    C数据类型
c_char                 char
c_short                short
c_int                    int
c_long                 long
c_float                 float
c_double             double
c_void_p             void
c_uint8                unsigned char

这里如果c/c++的.so动态库的接口形参的类型python不存在则会报段错误!!

例如:

      动态库接口为  string Example(string filePath );

python代码:

import ctypes
from ctypes import *
def convert_type(input):
    ctypes_map = {int:ctypes.c_int,
              float:ctypes.c_double,
              str:ctypes.c_char_p
              }
    input_type = type(input)
    if input_type is list:
        length = len(input)
        if length==0:
            print("convert type failed...input is "+input)
            return null
        else:
            arr = (ctypes_map[type(input[0])] * length)()
            for i in range(length):
                arr[i] = bytes(input[i],encoding="utf-8") if (type(input[0]) is str) else input[i]
            return arr
    else:
        if input_type in ctypes_map:
            return ctypes_map[input_type](bytes(input,encoding="utf-8") if type(input) is str else input)
        else:
            print("convert type failed...input is "+input)
            return null
libtestso = cdll.LoadLibrary("./ReadFile.so")

libtestso.Example(convert_type(file))

这时解释器会报段错误,经研究分析是类型不匹配导致解释器报段错

如果.so动态库接口改成char* Example(char filePath[] );

python调用

libtestso = cdll.LoadLibrary("./ReadFile.so")

libtestso.Example(convert_type(file))

就不会出现段错误,但是会导致无法获取的返回字符串,因为返回的地址但是python的变量是动态的所以,

变量被赋值地址,打印变量会认为是int类型,无法打印字符串。

这时我们可以在python中先给变量赋值一个足够大的字符类型数组,然后将数组传参的方式传进去

执行完函数之后可以打印数组,就可以看到传出的字符串啦

c/c++接口代码:

int Example(char file[] ,char* Buf,int *len)

{    

    char ch[] = "hello world";
    memcpy(buf, ch, strlen(ch));
    *len = strlen(ch);

    printf("%s\n",file);

}

 

python 代码:

import ctypes
from ctypes import *
def convert_type(input):
    ctypes_map = {int:ctypes.c_int,
              float:ctypes.c_double,
              str:ctypes.c_char_p
              }
    input_type = type(input)
    if input_type is list:
        length = len(input)
        if length==0:
            print("convert type failed...input is "+input)
            return null
        else:
            arr = (ctypes_map[type(input[0])] * length)()
            for i in range(length):
                arr[i] = bytes(input[i],encoding="utf-8") if (type(input[0]) is str) else input[i]
            return arr
    else:
        if input_type in ctypes_map:
            return ctypes_map[input_type](bytes(input,encoding="utf-8") if type(input) is str else input)
        else:
            print("convert type failed...input is "+input)
            return null
libtestso = cdll.LoadLibrary("./ReadFile.so")
file ="result"
Len = 123
Buf = create_string_buffer(0, Len)
c_bufLen = c_int(Len)

//传入字符串file ,Buf是传出字符串,c_bufLen是传出字符串的长度
libtestso.Example(convert_type(file),Buf,byref(c_bufLen))

print(c_bufLen.value)

print(string_at(Buf))

 

这时应会打印

result

hello world

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫回首�

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值