DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 541 评论 :: 1613万 阅读
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

c++和python使用混合编程,有四种方式来实现:

  • (1)C++调用python
  • (2)直接调用python文件并执行
  • (3)3.使用Cpython:这是一个第三方库,可以将python代码直接变成c代码
  • (4)使用pybind11库(建议),网址:pybind/pybind1

在这里描述VS写C++中调用python(方法一)的流程。

1.c++在VS中调用python的配置

其中python是一种非常强大的胶水语言,可以灵活的嵌入到c++和java等主流语言中。

1.1安装python

在python的官方网站Welcome to Python.org下载64位的安装包,在安装过程点击设置环境变量(很重要)。在目前的一些版本中,安装python是同时安装了pip的。

安装完python后,打开cmd,在其中输入

pip3 install numpy
pip3 install matplotlib

第一句用来安装numpy库,第二句用来安装绘图matplotlib库。当python为3.0以上版本,采用pip3安装;若为python2.7,则采用pip安装。

1.2在VS中设置调用python

若下载的python版本为64位,则在VS中将Debug修改为X64;若下载的python版本为32位,则在VS中将Debug修改为X86。

然后在VS的项目属性>>配置属性>>C/C++>>添加包含目录中,将Python的根目录下的include文件夹添加进来。(Python的根目录:如果按照默认位置安装,目录在C:\Users\Administrator\AppData\Local\Programs\Python\的路径下)

然后在VS的项目属性>>配置属性>>链接器>>附件库目录中,将Python的根目录下的libs文件夹添加进来。

1.3测试编译运行

在VS中新建一个文件.cpp的源文件,然后复制如下代码:

#include<Python.h>
int main()
{
	Py_Initialize();   

	PyRun_SimpleString("print ('hello')");

	PyRun_SimpleString("import numpy as np");

	Py_Finalize();

	system("pause");
	return 0;

若不报错,同时打印了hello则表明完成。

2.C++调用python

python作为一种强力的胶水语言,可以在其他语言中使用,特别是目前深度学习的快速发展,使用python搭建模型,训练是非常高效的。而在部署过程中使用C++时就出现问题了。但是如何解决部署中的问题,并不是本文的主题。

2.1 基础

python的C、C++外部扩展官方教程,可以在网页的上部选择python的版本:

python提供了一套C的API库,是的开发者能够很方便的从C、C++的程序中调用python中的各个功能模块。

此环境配置是在Windows的环境下,Linux不适用,但是方法思想一致:首先设置python的头文件,然后设置python的库文件。

首先按照1中搭建出c++和python混合编程的环境。

2.1.1 初始化Python解释器

例子:

#include<Python.h>

int main(){
    
    Py_Initialize();  //必要,初始化python解释器
    Py_Initialize();
	if (!Py_IsInitialized()) {
		std::system("pause");
		return -99;
	}//查看是否成功初始化
    
    /*  需要执行的python语句  */
    
    PyRun_SimpleString("import sys");
    PyRun_SimpleString(print('hello!'));
    
    /*  结束需要执行的python  */
    
    Py_Finalize(); //释放Python资源
    
    return 0;
}

2.1.2 调用Python函数(c++不向python传参)

假设你有一个名叫plot3dfun.py的python文件,你想调用其中的名叫print_test的函数。

plot3dfun.py文件为:

import numpy as np
def print_test1():
    print("hello, this is python")

首先,你要将plot3dfun.py文件放到你VS项目的固定位置上:若你使用的是debug(X64)模式,则plot3dfun.py放到你的Project目录>>x64>>Debug目录下;若你使用的是Release目录,则plot3dfun.py放到你的Project目录>>x64>>Release目录下。

C++程序为:

#include<iostream>
#include<Python.h>

int main(){
    Py_Initialize(); //初始化python解释器
	if (!Py_IsInitialized()) {
		std::system("pause");
		return -99;
	} //查看python解释器是否成功初始化
	
	PyObject *pName, *pModule, *pDict, *pFunc; //定义python对象
	
	pName = PyUnicode_FromString("plot3dfun");
	pModule = PyImport_Import(pName); //载入plot3dfun的模块
	if (!pModule) {
		cout << "Can't find plot3dfun.py" << endl;
		std::system("pause");
		return -98;
	} //查看是否载入了模块
	
	PyObject* pFunc = PyObject_GetAttrString(pModule, "print_test1");
	if (!pFunc || !PyCallable_Check(pFunc)) {
		cout << "error: pFunc" << endl;
		std::system("pause");
		return -96;
	}
	
	//调用print_test函数
	PyObject_CallObject(pFunc, NULL );
	
	//销毁python相关
	Py_DECREF(pName);
	Py_DECREF(pModule);
	Py_Finalize();

运行程序,可以看到程序能够输出hello, this is python。

2.1.3 调用Python函数(c++向python传参)

在很多时候,c++需要向python传参,让python执行相关操作。python提供了各种数据类型用于和C中的数据类型进行转换,具体的思想是相同的,这里只举几个例子。

字符串传参

假设你有一个名叫plot3dfun.py的python文件,你想调用其中的名叫print_test的函数。

plot3dfun.py文件为:

import numpy as np
def print_test1():
    print("hello, this is python")
def print_test2(string_in):
    print(string_in)

首先,你要将plot3dfun.py文件放到你VS项目的固定位置上:若你使用的是debug(X64)模式,则plot3dfun.py放到你的Project目录>>x64>>Debug目录下;若你使用的是Release目录,则plot3dfun.py放到你的Project目录>>x64>>Release目录下。

c++文件为:

#include<iostream>
#include<Python.h>

int main(){
    Py_Initialize(); //初始化python解释器
	if (!Py_IsInitialized()) {
		std::system("pause");
		return -99;
	} //查看python解释器是否成功初始化
	
	PyObject *pName, *pModule, *pDict, *pFunc, *pArgs; //定义python对象
	
	pName = PyUnicode_FromString("plot3dfun");
	pModule = PyImport_Import(pName); //载入plot3dfun的模块
	if (!pModule) {
		cout << "Can't find plot3dfun.py" << endl;
		std::system("pause");
		return -98;
	} //查看是否载入了模块
	
	PyObject* pFunc = PyObject_GetAttrString(pModule, "print_test1");
	if (!pFunc || !PyCallable_Check(pFunc)) {
		cout << "error: pFunc" << endl;
		std::system("pause");
		return -96;
	}
	
	//调用print_test2函数
	pArgs = PyTuple_New(1);//创建一个元组,长度为1。
	PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", "this is a test"));//将pArgs的第一(0)个变量设置为字符串(s) “this is a test”
	PyObject_CallObject(pFunc, pArgs);
	
	//销毁python相关
	Py_DECREF(pName);
	Py_DECREF(pModule);
	Py_Finalize();
}

上述程序中,PyObject* PyTuple_New(Py_ssize_t len)返回函数所创建的元组,所创建元组的长度为len。

左边为C++中的输入形式,右边为对应的python中的高级数据结构形式。

#define PY_SSIZE_T_CLEAN  /* Make "s#" use Py_ssize_t rather than int. */
#include <Python.h>

Py_BuildValue("")                        None
Py_BuildValue("i", 123)                  123
Py_BuildValue("iii", 123, 456, 789)      (123, 456, 789)
Py_BuildValue("s", "hello")              'hello'
Py_BuildValue("y", "hello")              b'hello'
Py_BuildValue("ss", "hello", "world")    ('hello', 'world')
Py_BuildValue("s#", "hello", 4)          'hell'
Py_BuildValue("y#", "hello", 4)          b'hell'
Py_BuildValue("()")                      ()
Py_BuildValue("(i)", 123)                (123,)
Py_BuildValue("(ii)", 123, 456)          (123, 456)
Py_BuildValue("(i,i)", 123, 456)         (123, 456)
Py_BuildValue("[i,i]", 123, 456)         [123, 456]
Py_BuildValue("{s,s}", "abc", "def")     {'abc', 'def'}
Py_BuildValue("{s:i,s:i}",
              "abc", 123, "def", 456)    {'abc': 123, 'def': 456}
Py_BuildValue("((ii)(ii)) (ii)",
              1, 2, 3, 4, 5, 6)          (((1, 2), (3, 4)), (5, 6))

上述的一些更详细的操作说明可以查看官方的文档,或者一下的描述:

C/C++调用Python[OpenCV与Numpy]_ziweipolaris的博客-CSDN博客_c++调用numpy

码农自来也:C++调用python脚本

2.2 c++调用numpy和Opencv

首先要查看python的版本是release版本还是debug版本,一般安装的python都是Release版本。VS编写C++时,改为Release模式,这要与python的版本一致,否则会报错:

无法解析的外部符号 __imp___Py_RefTotal

如果将版本调整为相同的Release,则不会存在此问题。

调用numpy首先要将numpy的相关目录包含到VS中,在项目》项目属性页》C/C++》附加包含目录 中添加:

C:\Users\Administrator\AppData\Local\Programs\Python\Python36\Lib\site-packages\numpy\core\include

在调用numpy之前,要初始化一下,载入numpy的各个功能模块,也就是要添加代码并调用:

size_t numpy_init() {
	import_array();
}

给python发送numpy数组代码:

npy_intp Dims[] = { JointType_Count, 3 };
cout << "push data to python numpy!" << endl;
PyObject *PyyArray = PyArray_SimpleNewFromData(2, Dims, NPY_FLOAT, (void *)toPython_XYZ);
PyObject *ArgArray = PyTuple_New(1);
PyTuple_SetItem(ArgArray, 0, PyyArray); //同样定义大小与Python函数参数个数一致的PyTuple对象															///*PyObject *pFuncFive = PyDict_GetItemString(pDict, "PassArrayFromCToPython");*/
PyObject_CallObject(pFunc, ArgArray);

更多的Numpy C API例子可以查看:

2.3 c++动态画图(matplotlib)

想造轮子的刘大胆:C++中使用matplotlib绘图

ref:C++调用python方法及环境配置(Windows环境、VS工具) - 知乎 (zhihu.com)

posted on   DoubleLi  阅读(1805)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
历史上的今天:
2021-01-18 MySQL-使用bin-log日志不停主库,恢复主从同步
2017-01-18 TTL和RS232之间的详细对比
点击右上角即可分享
微信分享提示