python调用c/c++代码的相关问题

Python调用c/c++代码的ctypes库的使用

编译环境是centos7,ctypes的一些基本用法可以随便百度一下都能找到很多资料,但是很少有提到怎么调用c++函数或者类方法的文章,本文主要介绍的内容包括:
1、怎样调用c++的函数和类方法
2、向c函数中传入回调函数的方法
一、python的ctypes调用c++函数和方法
常规的ctypes调用c函数的方法

//ctest.c
#include <stdio.h>
int func(int a, int b)
{
	int res = a + b;
	printf("%d + %d = %d\n", a, b, res);
	return res;
}

c文件编译:gcc ctest.c -shared -fPIC -o libctest.so
注意:不要加 -c

#pycallc.py
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libctest.so")

lib.func(2, 3)

运行python脚本:python3 pycallc.py
结果如下,能正确运行:
在这里插入图片描述

python调用cpp函数:

//cpptest.cpp   --> libcpptest.cpp
#include <stdio.h>
int func(int a, int b)
{
	int res = a + b;
	printf("%d + %d = %d\n", a, b, res);
	return res;
}

编译指令:g++ cpptest.cpp -shared -fPIC -o libcpptest.so

#pycallcpp.py
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libcpptest.so")

lib.func(2, 3)

执行 python3 pycallcpp.py会报错,显示找不到func函数,原因正是g++编译器将函数的名字加了前后缀,使用nm命令查看,nm libcpptet.so | grep func 可以看到func的函数名变成_Z4funcii,ii正是func函数的两个int参数
在这里插入图片描述
改变python代码里的函数名,然后python代码就能正确的调用c++函数了。

#pycallcpp.py
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libcpptest.so")

lib._Z4funcii(2, 3)

如果使用函数的话使用extern “C”,也可以达到效果,就是让g++编译器使用c的函数编译方式,也就是不加前后缀,但是这种方式c++的函数重载功能就没有了,怀着好奇心,继续研究怎么让python调用c++的类方法。

//cpptest.cpp  -->  libcpptest.so
#include <stdio.h>
class TEST
{
public:
	static int func(int a, int b)
	{
		int res = a + b;
		printf("%d + %d = %d\n", a, b, res);
		return res;
	}
};
//foo()函数在python中不调用
void foo()
{
	TEST t;
	t.func(1, 2);
}

使用nm命令查看func函数名变成了什么:nm libcpptest.so | grep func
在这里插入图片描述

foo()函数的存在是因为其内部初始化了一个类,并调用了func()方法,使得编译出的动态库能生成func的函数名,如果没有此函数,使用nm命令是找不到这个函数的,具体原因我还没弄清楚,期待有大神留言交流,第二个要注意的点是func()函数必须声明为static,因为类的非静态函数的第一个参数是this指针,c++的类无法在python中传递

#pycallcpp.py
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libcpptest.so")

lib._ZN4TEST4funcEii(2, 3)

二、回调函数传递的问题
1、python中写回调函数作为参数传递给c函数

//ctest.c    -->   libctest.so
#include <stdio.h>
typedef int (*ADD)(int, int);
int func(ADD f, int a, int b)
{
	int sum = f(a, b);
	printf("sum = %d\n", sum);
	return sum;
}
from ctypes import *
ll = cdll.LoadLibrary
lib = ll("./libctest.so")

def callback(a, b):
	return a + b;
cfunctype = CFUNCTYPE(c_int, c_int, c_int)
#第一个是函数返回值,后面两个是参数列表
add = cfunctype(callback)

lib.func(add, 5, 6)

2、在c中写回调函数

//ctest.c    -->   libctest.so
#include <stdio.h>
typedef int (*ADD)(int, int);
int func(ADD f, int a, int b)
{
	int sum = f(a, b);
	printf("sum = %d\n", sum);
	return sum;
}

int add(int a, int b)
{
	return a + b;
}
from ctypes import *
ll = cdll.LoadLibrary
lib = ll("./libctest.so")

lib.func(lib.add, 5, 6)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值