IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 在C++中使用python -> 正文阅读

[Python知识库]在C++中使用python

最近需要在C++中调用一些神经网络相关的东西,开始研究一下怎么在C++中使用python

Python.h

python的开发者已经给出了关于C/C++的接口,为了简洁他们称之为“Python/C API”,与其相关的所有函数、类型和宏定义都包含在了头文件“Python.h”中,我们只需在代码中加入

#include <Python.h>

即可在使用其中的接口在C++中使用python啦
在Ubuntu中,Python.h头文件可以在"usr/include/pythonx.x"中找到,如果你安装了Anaconda,那么你在"${YOUR_ANACONDA_PATH}/anaconda3/include/pythonx.x"中也能找到一个。在使用时我们需要在CmakeLists.txt(使用CMAKE的话)或c_cpp_propertirs.json(使用VScode)中设定,以帮助程序找到Python.h并确定其版本。

CmakeLists.txt

需要加入以下三行

find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
include_directories(${Python3_INCLUDE_DIRS})
target_link_libraries(${Python3_LIBRARIES})

如果需要调用python2版本,上面的3全部改成2即可。
我用Python3的时候Cmake自动找到的是Anaconda中的python3而不是系统中的python3,经过测试暂时没有发现怎么通过find_package找到系统自带的python,如果想使用系统的python可以直接指定路径,找到python路径和.so文件路径并设置就好了

SET(Python3_INCLUDE_DIRS "/usr/include/python3.6m")
SET(Python3_LIBRARIES "/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu/libpython3.6.so")
message("Python3: " ${Python3_INCLUDE_DIRS})
message("Python3: " ${Python3_LIBRARIES})

c_cpp_propertirs.json

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                // "/usr/include/python2.7"
                // "/usr/include/python3.6"
                // "${YOUR_ANACONDA_PATH}/anaconda3/include/python3.9"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu11",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "linux-gcc-x64",
            "configurationProvider": "ms-vscode.cmake-tools",
            "compileCommands": "${workspaceFolder}/build/compile_commands.json"
        }
    ],
    "version": 4
}

带有//的三行中选一行即可,分别对应系统的python2、python3和anaconda的python3

具体使用

我们有如下的代码结构
请添加图片描述
hello.py的形式如下

def printHello():
    print("Hello world")

def printStr(a, b):
    return a+b

有两种调用hello.py的方式

对模块、函数都保存为python中的给出的PyObject类的指针进行使用

void cpython1(){
    Py_Initialize();                                                                                                                    // 初始化python接口 
    PyRun_SimpleString("import sys");																			// 指定根目录
    PyRun_SimpleString("sys.path.append('./')");
    PyObject* pModule = PyImport_ImportModule("hello");								// 取hello模块
    if( pModule == NULL ){
		cout <<"module not found" << endl;
		return;
	}
    PyObject* pFunc = PyObject_GetAttrString(pModule, "printHello");			// 取printHello函数
    if( !pFunc || !PyCallable_Check(pFunc)){
		cout <<"function not found" << endl;
		return;
	}
    PyEval_CallObject(pFunc, nullptr);
    Py_Finalize();                                                                                                                      // 结束python接口
}

PyImport_ImportModule和PyObject_GetAttrString的作用顾名思义

利用PyRun_SimpleString直接通过python代码形式的字符串调用python内容

void cpython2(){
    Py_Initialize();
    PyRun_SimpleString("import sys");																		// 通上
    PyRun_SimpleString("sys.path.append('./')");
    PyRun_SimpleString("import hello");																	// 导入模块
    PyRun_SimpleString("hello.printHello()");															// 调用函数
    Py_Finalize();
}

代用需要参数的函数

上面知道了如何调用函数,现在补充如何给出函数需要的参数块,代码如下

void cpythonWithPra(string& a, string& b){
    Py_Initialize();
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");
    PyObject* pModule = PyImport_ImportModule("hello");
    if(pModule == NULL){
        cout << "module not found" << endl;
        return;
    }
    PyObject* pFunc = PyObject_GetAttrString(pModule, "printStr");
    if(!pFunc || !PyCallable_Check(pFunc)){
        cout << "function not found" << endl;
        return;
    }
    PyObject* pArgs = PyTuple_New(2);																// PyTuple_New构造输入的Tuple参数块,指定为2维
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", a.c_str()));					// 对每个参数赋值,通过Py_BuildValue构造
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("s", b.c_str()));
    PyObject* pReturn = PyEval_CallObject(pFunc, pArgs);						// 将参数块传入函数,取得返回值

    char* result;
    PyArg_Parse(pReturn, "s", &result);
    cout << "result: " << result << endl;

    Py_Finalize();
}

这里需要说明的是Py_BuildValue()需要两个参数,第一个为数据的类型,第二个为数据,更详细的信息可以在[1][2]中找到。由于Python.h主要是针对C语言的,所以只接受char不接受string类型,所以对字符串a,b需要调用.c_str()同时返回值需要用char类型保存。

总结

main函数如下

int main(){
    cout << "cpython1: " << endl;
    cpython1();
    cout << "cpython2: " << endl;
    cpython2();
    string a = "c++";
    string b = "python";
    cpythonWithPra(a, b);
    return 0;
}

最后的结果为
请添加图片描述

本文的代码在github仓库中的Cpython中,后续会补充一些对神经网络的调用和碰到的Python.h中的API更详细的个人理解

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 16:14:01  更:2022-04-06 16:15:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 17:27:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码