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的版本:
https://docs.python.org/3.6/extending/embedding.htmldocs.python.org/3.6/extending/embedding.htmlpython提供了一套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
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例子可以查看:
How to extend NumPynumpy.org/devdocs/user/c-info.how-to-extend.html2.3 c++动态画图(matplotlib)
ref:C++调用python方法及环境配置(Windows环境、VS工具) - 知乎 (zhihu.com)
标签:BuildValue,python,Py,C++,Windows,VS,numpy From: https://www.cnblogs.com/lidabo/p/17059485.html