【Python】C++ & Python 混合编程(1)-- C++使用Python

使用 Python 官方接口实现 C++内调用 Python 代码
两篇不错的文章:《浅析 C++ 调用 Python 模块》《C++中嵌入python程序——使用API接口,从函数到类》


C++环境配置

Windows下

以VS为例,配置包含目录库目录
          这里写图片描述
                      图1. 目录设置

  • 编译平台(x64和win32)需要与Python版本一致
  • debug模式下需要将python27.lib重命名为python27_d.lib

Linux下

以QT为例,配置包含目录库目录

// xxx.pro
INCLUDEPATH += -I /usr/include/python2.7/
LIBS += -L /usr/lib/python2.7/config-x86_64-linux-gnu/ -lpython2.7

调用示例

分别调用python函数和python类
1)Python 实现具体方法
假设脚本名字为 pyTest.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def add_it(a, b):
    print '[python] add %d and %d'%(a, b)
    return a+b

class cladd:
    def __init__(self, param1, param2):
        print 'param1: ',param1
        print 'param2: ',param2

    def add_it(self, a, b):
        print '[python-class] add %d and %d'%(a, b)
        return a+b

2)C++直接调用 pyTest.py 的函数 add_it

#include "stdafx.h"
#include "iostream"
#include "Python.h"
using namespace std;

void main()
{
    // 初始化
    Py_Initialize();

    // 加载模块
    PyObject* moudleName = PyString_FromString("pyTest");
    PyObject* pModule = PyImport_Import(moudleName);
    if(!pModule){
        cout << "Python get moudle failed" <<endl;
        return;
    }
    cout << "Python get moudle succeed" <<endl;

    // 加载函数
    PyObject* pFunc = PyObject_GetAttrString(pModule, "add_it");
    if(!pFunc || !PyCallable_Check(pFunc)){
        cout << "can not find function"<<endl;
        return;
    }
    cout << "get function succeed" <<endl;

    // 设置参数
    PyObject* args = PyTuple_New(2);
    PyObject* arg1 = PyInt_FromLong(4);
    PyObject* arg2 = PyInt_FromLong(3);
    PyTuple_SetItem(args, 0, arg1);
    PyTuple_SetItem(args, 1, arg2);

    // 调用函数
    PyObject* pRet = PyObject_CallObject(pFunc, args);

    // 获取返回
    if(pRet){
        long result = PyInt_AsLong(pRet);
        cout << "result: "<<result;
    }

    // 释放资源
    Py_Finalize();
}

3)C++ 调用 pyTest.py 的 cladd 类

void main()
{
    // 初始化
    Py_Initialize();

    // 加载模块
    PyObject* moudleName = PyString_FromString("pyTest");
    PyObject* pModule = PyImport_Import(moudleName);
    if(!pModule){
        cout << "Python get moudle failed" <<endl;
        return;
    }
    cout << "Python get moudle succeed" <<endl;

    // 加载类
    PyObject* pClass = PyObject_GetAttrString(pModule, "cladd");
    if(!pClass){
        cout << "can not find class"<<endl;
        return;
    }
    cout << "get class succeed" <<endl;

    // 创建类实例
    PyObject* args = PyTuple_New(2);
    PyObject* arg1 = Py_BuildValue("s", "da");
    PyObject* arg2 = Py_BuildValue("s", "dada");
    PyTuple_SetItem(args, 0, arg1);
    PyTuple_SetItem(args, 1, arg2);
    PyObject* pInstance = PyInstance_New(pClass, args, NULL);

    // 调用方法
    PyObject* pRet = PyObject_CallMethod(pInstance, "add_it", "(ii)", 4, 3);

    // 获取返回
    if(pRet){
        long result = PyInt_AsLong(pRet);
        cout << "result: "<<result;
    }

    // 释放资源
    Py_Finalize();
}

细节

  • 所有Python元素在 C里都是 PyObject 对象
  • Python 类型 XXX 和 C 类型 YYY 的转换使用 PyXXX_AsYYY 和 PyXXX_FromYYY

  • 基本流程是:
    1)初始化 -> Py_Initialize()
    2)加载模块 -> PyImport_Import(PyString_FromString(“python 脚本名”))
    3)加载函数/类 -> PyObject_GetAttrString(…)
    4)创建类实例 -> PyInstance_New(…)
    5)设置参数
    6)调用函数/方法 -> PyObject_CallObject(…) / PyObject_CallMethod(…)
    7)解除对象引用(以便python垃圾回收) -> Py_DECREF(PyObject*)
    8)释放资源 -> Py_Finalize()

  • 设置参数
    Python的参数实际上是元组,因此传参实际就是构造一个合适的元组
    1)使用 PyTuple_New 创建元组,并用 PyTuple_SetItem 设置元组值
PyObject* args = PyTuple_New(3);
PyObject* arg1 = Py_BuildValue("i", 100); // 整数参数
PyObject* arg2 = Py_BuildValue("f", 3.14); // 浮点数参数
PyObject* arg3 = Py_BuildValue("s", "hello"); // 字符串参数
PyTuple_SetItem(args, 0, arg1);
PyTuple_SetItem(args, 1, arg2);
PyTuple_SetItem(args, 2, arg3);

2)直接使用 Py_BuildValue 构造元组

// (ifs)表示 int、float、string 3个值
PyObject* args = Py_BuildValue("(ifs)", 100, 3.14, "hello");
  • Python 脚本名称不要设为“test.py”,会出现错误,原因未知
  • Linux下 C 代码里还需指定 Python 脚本的路径,否则会找不到模块(windows下会默认在工程目录下找)
...
Py_Initialize();    // 初始化

// 指定 python 脚本的目录
string path = string("sys.path.append(\'/home/path-to-python-file\')");
const char* cstr_cmd = path .c_str();
PyRun_SimpleString("import sys");
PyRun_SimpleString(cstr_cmd);

// 加载模块
...

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值