15°

C++中与python脚本交互

再记录一下以前做过的一个任务,在c++中与python脚本交互。其实很简单,其核心是找到python相关的开发头文件和库。下面以ubuntu为例给出样例代码,在c++中调用并执行python脚本,并传参给python获得执行结果。该样例稍作修改即可用在windows下。为了明确编译条件,makefile文件也给出了。

 

直接上代码,c++代码如下

#include "python2.7/Python.h"

int numOfArgs = 2; char* Args[2] = { "3", "5" };

void simpleCall() { FILE* fp = fopen("MyTest.py", "r");

PyRun_SimpleString("from time import time, ctime\n"
"print('today is', ctime(time())) \n");
PyRun_SimpleFile(fp, "MyTest.py");
PyRun_SimpleString("execfile('MyTest.py')");

fclose(fp);
fp = NULL;

}

void pureEmbed() { PyObject *pName, *pModule, *pDict, *pFunc; PyObject *pArgs, *pValue; int i;

pName = PyUnicode_FromString("MyTest");

pModule = PyImport_Import(pName);
Py_DECREF(pName);

if (pModule != NULL)
{

// pDict = PyModule_GetDict(pModule); // pFunc = PyDict_GetItemString(pDict, "add"); pFunc = PyObject_GetAttrString(pModule, "add");

    if (pFunc && PyCallable_Check(pFunc))
    {
        pArgs = PyTuple_New(numOfArgs);
        for (i = 0; i < numOfArgs; ++i)
        {
            pValue = PyLong_FromLong(atoi(Args[i]));
            if (!pValue)
            {
                Py_DECREF(pArgs);
                Py_DECREF(pModule);
                fprintf(stderr, "Cannot convert argument\n");
                return;
            }

            PyTuple_SetItem(pArgs, i, pValue);
        }

        pValue = PyObject_CallObject(pFunc, pArgs);
        Py_DECREF(pArgs);
        if (pValue != NULL)
        {
            printf("Result of call: %ld\n", PyLong_AsLong(pValue));
            Py_DECREF(pValue);
        }
        else
        {
            Py_DECREF(pFunc);
            Py_DECREF(pModule);
            PyErr_Print();
            fprintf(stderr, "Call failed\n");
            return;
        }
    }
    else
    {
        if (PyErr_Occurred())
            PyErr_Print();
    }

    Py_XDECREF(pFunc);
    Py_DECREF(pModule);
}
else
{
    PyErr_Print();
    return;
}

}

// ================ cpp api for python ================== static int numargs = 5; static PyObject* emb_numargs(PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":numargs")) return NULL; return Py_BuildValue("i", numargs); }

static PyMethodDef EmbMethods[] = { {"numargs", emb_numargs, METH_VARARGS, "Return the number of arguments received by the process."}, {NULL, NULL, 0, NULL} }; // ======================================================

int main(int argc, char* argv[]) { // == initialize, the path append is necessary! == Py_Initialize(); PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')"); // ===============================================

// --------- open c++ api to python ----------- Py_InitModule("emb", EmbMethods); // --------------------------------------------

// ----------- simple call python ------------ simpleCall(); // -------------------------------------------

// ------------- embed python ------------ pureEmbed(); // ---------------------------------------

// ============= finalize and clean ============== Py_Finalize(); return 0; }

simpleCall调用并执行了下面的MyTest.py脚本,pureEmbed则调用了MyTest.py中的add函数,并且构造了一个emb模块,其中定义了一个方法numargs,供python调用。

 

然后是python脚本MyTest.py

#!/usr/bin/env python

def Hello(): print("Hello, Python!")

def multiply(a, b): print("will compute", a, "times", b) c = 0 for i in range(0, a): c = c + b return c

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

Hello()

import emb print ("Number of arguments", emb.numargs())

其中导入了c++中定义的emb模块,调用了该模块中的方法numargs。

 

makefile文件如下

OBJS = main.o
LIBS = -lpython2.7
EXE = run.exe

all: $(OBJS) g++ -o $(EXE) $(OBJS) $(LIBS)

$(OBJS): %.o:%.cpp g++ -c $< -o $@

.PHONY: clean clean: rm $(OBJS) $(EXE)

 

运行结果如下

 

样例代码可在如下网址下载

https://download.csdn.net/download/u014559935/12108901

本文由【propagator】发布于开源中国,原文链接:https://my.oschina.net/propagator/blog/3159401

全部评论: 0

    我有话说: