c调⽤python_C++调⽤python⽅法及环境配置(Windows环
境、VS⼯具)
请注明转⾃:想造轮⼦的刘⼤胆:C++调⽤python⽅法及环境配置(Windows环境、VS⼯具)
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 下载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的项⽬属性
添加包含⽬录中,将Python的根⽬录下的include⽂件夹添加进来。(Python的根⽬录:
C/C++>>添加包含⽬录
配置属性>>C/C++
项⽬属性>>配置属性
如果按照默认位置安装,⽬录在C:UsersAdministratorAppDataLocalProgramsPython的路径下)
链接器>>附件库⽬录
配置属性>>链接器
附件库⽬录中,将Python的根⽬录下的libs⽂件夹添加进来。
然后在VS的项⽬属性
项⽬属性>>配置属性
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的版本:
/3.6/extending/embedding.html d
python提供了⼀套C的API库,是的开发者能够很⽅便的从C、C++的程序中调⽤python中的各个功能模块。
此环境配置是在Windows的环境下,Linux不适⽤,但是⽅法思想⼀致:⾸先设置python的头⽂件,然后设置python的库⽂件。
⾸先按照11中搭建出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⽂件为:
plot3dfun.py
import numpy as np
def print_test1():
print("hello, this is python")
Project⽬录⾸先,你要将plot3dfun.py⽂件放到你VS项⽬的固定位置上:若你使⽤的是debug(X64)模式,则plot3dfun.py放到你的Project⽬录
Project⽬录>>x64>>Release⽬录下。
>>x64>>Debug⽬录下;若你使⽤的是Release⽬录,则plot3dfun.py放到你的Project⽬录>>x64>>Release⽬录
>>x64>>Debug⽬录
C++程序为:
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
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++⽂件为:
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'
java调用python模型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
Release模式,这
⾸先要查看python的版本是release版本还是debug版本,⼀般安装的python都是Release版本。VS编写C++时,改为Release模式
要与python的版本⼀致,否则会报错:
⽆法解析的外部符号 __imp___Py_RefTotal
如果将版本调整为相同的Release,则不会存在此问题。
在项⽬》项⽬属性页》C/C++》附加包含⽬录 中添加:
调⽤numpy⾸先要将numpy的相关⽬录包含到VS中,在项⽬》项⽬属性页》C/C++》附加包含⽬录
C:UsersAdministratorAppDataLocalProgramsPythonPython36Libsite-packagesnumpycoreinclude
在调⽤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 PyObject_CallObject(pFunc, ArgArray);
更多的Numpy C API例⼦可以查看:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。