Python调用C++程序的方法详解
发布时间 - 2026-01-10 22:46:30 点击率:次前言

大家都知道Python的优点是开发效率高,使用方便,C++则是运行效率高,这两者可以相辅相成,不管是在Python项目中嵌入C++代码,或是在C++项目中用Python实现外围功能,都可能遇到Python调用C++模块的需求,下面列举出集中c++代码导出成Python接口的几种基本方法,一起来学习学习吧。
原生态导出
Python解释器就是用C实现,因此只要我们的C++的数据结构能让Python认识,理论上就是可以被直接调用的。我们实现test1.cpp如下
#include <Python.h>
int Add(int x, int y)
{
return x + y;
}
int Del(int x, int y)
{
return x - y;
}
PyObject* WrappAdd(PyObject* self, PyObject* args)
{
int x, y;
if (!PyArg_ParseTuple(args, "ii", &x, &y))
{
return NULL;
}
return Py_BuildValue("i", Add(x, y));
}
PyObject* WrappDel(PyObject* self, PyObject* args)
{
int x, y;
if (!PyArg_ParseTuple(args, "ii", &x, &y))
{
return NULL;
}
return Py_BuildValue("i", Del(x, y));
}
static PyMethodDef test_methods[] = {
{"Add", WrappAdd, METH_VARARGS, "something"},
{"Del", WrappDel, METH_VARARGS, "something"},
{NULL, NULL}
};
extern "C"
void inittest1()
{
Py_InitModule("test1", test_methods);
}
编译命令如下
g++ -fPIC -shared test1.cpp -I/usr/include/python2.6 -o test1.so
运行Python解释器,测试如下
>>> import test1 >>> test1.Add(1,2) 3
这里要注意一下几点
- 如果生成的动态库名字为test1,则源文件里必须有inittest1这个函数,且Py_InitModule的第一个参数必须是“test1”,否则Python导入模块会失败
- 如果是cpp源文件,inittest1函数必须用extern "C"修饰,如果是c源文件,则不需要。原因是Python解释器在导入库时会寻找initxxx这样的函数,而C和C++对函数符号的编码方式不同,C++在对函数符号进行编码时会考虑函数长度和参数类型,具体可以通过
nm test1.so查看函数符号,c++filt工具可通过符号反解出函数原型
通过boost实现
我们使用和上面同样的例子,实现test2.cpp如下
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
using namespace boost::python;
int Add(const int x, const int y)
{
return x + y;
}
int Del(const int x, const int y)
{
return x - y;
}
BOOST_PYTHON_MODULE(test2)
{
def("Add", Add);
def("Del", Del);
}
其中BOOST_PYTHON_MODULE的参数为要导出的模块名字
编译命令如下
g++ test2.cpp -fPIC -shared -o test2.so -I/usr/include/python2.6 -I/usr/local/include -L/usr/local/lib -lboost_python
注意: 编译时需要指定boost头文件和库的路径,我这里分别是/usr/local/include和/usr/local/lib
或者通过setup.py导出模块
#!/usr/bin/env python
from distutils.core import setup
from distutils.extension import Extension
setup(name="PackageName",
ext_modules=[
Extension("test2", ["test2.cpp"],
libraries = ["boost_python"])
])
Extension的第一个参数为模块名,第二个参数为文件名
执行如下命令
python setup.py build
这时会生成build目录,找到里面的test2.so,并进入同一级目录,验证如下
>>> import test2 >>> test2.Add(1,2) 3 >>> test2.Del(1,2) -1
导出类
test3.cpp实现如下
#include <boost/python.hpp>
using namespace boost::python;
class Test
{
public:
int Add(const int x, const int y)
{
return x + y;
}
int Del(const int x, const int y)
{
return x - y;
}
};
BOOST_PYTHON_MODULE(test3)
{
class_<Test>("Test")
.def("Add", &Test::Add)
.def("Del", &Test::Del);
}
注意:BOOST_PYTHON_MODULE里的.def使用方法有点类似Python的语法,等同于
class_<Test>("Test").def("Add", &Test::Add);
class_<Test>("Test").def("Del", &Test::Del);
编译命令如下
g++ test3.cpp -fPIC -shared -o test3.so -I/usr/include/python2.6 -I/usr/local/include/boost -L/usr/local/lib -lboost_python
测试如下
>>> import test3 >>> test = test3.Test() >>> test.Add(1,2) 3 >>> test.Del(1,2) -1
导出变参函数
test4.cpp实现如下
#include <boost/python.hpp>
using namespace boost::python;
class Test
{
public:
int Add(const int x, const int y, const int z = 100)
{
return x + y + z;
}
};
int Del(const int x, const int y, const int z = 100)
{
return x - y - z;
}
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(Add_member_overloads, Add, 2, 3)
BOOST_PYTHON_FUNCTION_OVERLOADS(Del_overloads, Del, 2, 3)
BOOST_PYTHON_MODULE(test4)
{
class_<Test>("Test")
.def("Add", &Test::Add, Add_member_overloads(args("x", "y", "z"), "something"));
def("Del", Del, Del_overloads(args("x", "y", "z"), "something"));
}
这里Add和Del函数均采用了默认参数,Del为普通函数,Add为类成员函数,这里分别调用了不同的宏,宏的最后两个参数分别代表函数的最少参数个数和最多参数个数
编译命令如下
g++ test4.cpp -fPIC -shared -o test4.so -I/usr/include/python2.6 -I/usr/local/include/boost -L/usr/local/lib -lboost_python
测试如下
>>> import test4 >>> test = test4.Test() >>> print test.Add(1,2) 103 >>> print test.Add(1,2,z=3) 6 >>> print test4.Del(1,2) -1 >>> print test4.Del(1,2,z=3) -1
导出带Python对象的接口
既然是导出为Python接口,调用者难免会使用Python特有的数据结构,比如tuple,list,dict,由于原生态方法太麻烦,这里只记录boost的使用方法,假设要实现如下的Python函数功能
def Square(list_a)
{
return [x * x for x in list_a]
}
即对传入的list每个元素计算平方,返回list类型的结果
代码如下
#include <boost/python.hpp>
boost::python::list Square(boost::python::list& data)
{
boost::python::list ret;
for (int i = 0; i < len(data); ++i)
{
ret.append(data[i] * data[i]);
}
return ret;
}
BOOST_PYTHON_MODULE(test5)
{
def("Square", Square);
}
编译命令如下
g++ test5.cpp -fPIC -shared -o test5.so -I/usr/include/python2.6 -I/usr/local/include/boost -L/usr/local/lib -lboost_python
测试如下
>>> import test5 >>> test5.Square([1,2,3]) [1, 4, 9]
boost实现了boost::python::tuple, boost::python::list, boost::python::dict这几个数据类型,使用方法基本和Python保持一致,具体方法可以查看boost头文件里的boost/python/tuple.hpp及其它对应文件
另外比较常用的一个函数是boost::python::make_tuple() ,使用方法如下
boost::python::tuple(int a, int b, int c)
{
return boost::python::make_tuple(a, b, c);
}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
# python
# 调用c语言
# python如何调用c
# python调用c
# 接口
# Python调用C/C++动态链接库的方法详解
# python调用c++传递数组的实例
# Python调用C/C++的方法解析
# python 与c++相互调用实现
# 在python中调用C/C++的三种方法
# 是在
# 第一个
# 数据结构
# 原生态
# 头文件
# 大家都
# 最多
# 不需要
# 则是
# 效率高
# 可以通过
# 要注意
# 第二个
# 能让
# 采用了
# 相辅相成
# 几种
# 几点
# 在对
# 这篇文章
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法
如何挑选高效建站主机与优质域名?
WordPress 子目录安装中正确处理脚本路径的完整指南
如何基于云服务器快速搭建网站及云盘系统?
Python文件操作最佳实践_稳定性说明【指导】
Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)
电商网站制作价格怎么算,网上拍卖流程以及规则?
微信小程序制作网站有哪些,微信小程序需要做网站吗?
如何用狗爹虚拟主机快速搭建网站?
linux top下的 minerd 木马清除方法
如何快速辨别茅台真假?关键步骤解析
浅谈redis在项目中的应用
Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
JavaScript中的标签模板是什么_它如何扩展字符串功能
如何在 Go 中优雅地映射具有动态字段的 JSON 对象到结构体
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
如何快速搭建自助建站会员专属系统?
Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程
零基础网站服务器架设实战:轻量应用与域名解析配置指南
智能起名网站制作软件有哪些,制作logo的软件?
Swift开发中switch语句值绑定模式
如何在建站之星绑定自定义域名?
实现点击下箭头变上箭头来回切换的两种方法【推荐】
Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives
javascript中的try catch异常捕获机制用法分析
Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置
JS去除重复并统计数量的实现方法
如何注册花生壳免费域名并搭建个人网站?
如何快速打造个性化非模板自助建站?
怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
如何在服务器上配置二级域名建站?
宙斯浏览器视频悬浮窗怎么开启 边看视频边操作其他应用教程
Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧
laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法
网站建设整体流程解析,建站其实很容易!
googleplay官方入口在哪里_Google Play官方商店快速入口指南
Laravel如何编写单元测试和功能测试?(PHPUnit示例)
如何获取免费开源的自助建站系统源码?
,南京靠谱的征婚网站?
Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程
Laravel怎么实现搜索高亮功能_Laravel结合Scout与Algolia全文检索【实战】
如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?
nodejs redis 发布订阅机制封装实现方法及实例代码
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
Laravel Debugbar怎么安装_Laravel调试工具栏配置指南
如何在万网主机上快速搭建网站?
Claude怎样写结构化提示词_Claude结构化提示词写法【教程】
如何在云主机上快速搭建网站?

