Python和C/C++互相调用

// PythonInvoke.h
#pragma once
#include <string>
#include "../include/python/Python.h"



class PythonInvoker
{
public:
    // init/uninit
    static void InitPythonEnv();
    static void Uninit();

    static PyObject* PyInit();
    // invoke python
    static int InvokePython(const std::string& strModuleName, const std::string& strFunc, PyObject* pArgs = nullptr);
    // set callback
    static PyObject* set_callback(PyObject* pDummy, PyObject* pArgs);
    // python invoke
    static PyObject* PrintData(PyObject* self, PyObject* args);

private:
    static PyObject* g_callback;

};


// PythonInvoke.cpp
#include "PythonInvoke.h"
#include <Windows.h>



/*****************************************************************************************
*   https://docs.python.org/3/extending/extending.html#intermezzo-errors-and-exceptions  *
******************************************************************************************/
// methods
static PyMethodDef ExtendMethods[]
{
    { "py_Print", &PythonInvoker::PrintData, METH_VARARGS, "Python Extend test" },
    { NULL, NULL, 0, NULL }
};

// moudule init
static struct PyModuleDef ExtendModule =
{
    PyModuleDef_HEAD_INIT,
    "Extend",     // name of module
    NULL,
    -1,
    ExtendMethods
};


/**************************************************************************************
*                                   member function                                   *
***************************************************************************************/
PyObject* PythonInvoker::g_callback = nullptr;
void PythonInvoker::InitPythonEnv()
{
    int nCode = PyImport_AppendInittab("PythonExtend", PyInit);
    if (-1 == nCode)
    {
        printf("Error: can't extend in-build modules table\n");
        return;
    }
    wchar_t szPath[MAX_PATH] = { 0 };
    GetModuleFileName(NULL, szPath, 256);
    wchar_t* p = wcsrchr(szPath, L'\\');
    if (p)
    {
        *p = L'\0';
    }
    wcscat(szPath, L"/libPy");
    Py_SetPythonHome(szPath);
    Py_Initialize();
}

void PythonInvoker::Uninit()
{
    Py_Finalize();
}

PyObject* PythonInvoker::PyInit()
{
    return PyModule_Create(&ExtendModule);
}

int PythonInvoker::InvokePython(const std::string& strModuleName, const std::string& strFunc, PyObject* pArgs/* = nullptr*/)
{
    PyObject* pModule = PyImport_ImportModule(strModuleName.c_str());
    if (nullptr == pModule)
    {
        printf("Python get module failed\n");
        return -1;
    }
    int nCode = 0;
    PyObject* pHelloFunc = nullptr;
    // get function name address
    pHelloFunc = PyObject_GetAttrString(pModule, strFunc.c_str());
    // invoke hello function
    if (!pHelloFunc || !PyCallable_Check(pHelloFunc))
    {
        printf("Can't find funftion %s\n", strFunc.c_str());
        return 0;
    }
    //PyEval_CallObject(pHelloFunc, pArgs);
    PyObject* pRet = PyObject_CallObject(pHelloFunc, pArgs);
    if (pRet != nullptr)
    {
        nCode = PyLong_AsLong(pRet);
        printf("Result: %d\n", nCode);
    }

    return nCode;
}

PyObject* PythonInvoker::set_callback(PyObject* pDummy, PyObject* pArgs)
{
    PyObject* pResult = NULL;
    PyObject* pTemp;

    if (PyArg_ParseTuple(pArgs, "O:set_callback", &pTemp)) {
        if (!PyCallable_Check(pTemp)) {
            PyErr_SetString(PyExc_TypeError, "parameter must be callable");
            return NULL;
        }
        Py_XINCREF(pTemp);         /* Add a reference to new callback */
        Py_XDECREF(g_callback);  /* Dispose of previous callback */
        g_callback = pTemp;       /* Remember new callback */
        /* Boilerplate to return "None" */
        Py_INCREF(Py_None);
        pResult = Py_None;
    }
    return pResult;
}

PyObject* PythonInvoker::PrintData(PyObject* self, PyObject* args)
{
    const char* pData;
    if (!PyArg_ParseTuple(args, "s", &pData)) return nullptr;
    printf("------------------------------------------\n");
    printf("Python invoke Test, data: %s\n\n", pData);
    printf("------------------------------------------\n");
    //PyLong_FromLong(0);
    return Py_BuildValue("i", 0);
}

// main.cpp
#include <iostream>
#include <windows.h>
#include "../include/python/python.h"
#include "PythonInvoke.h"


int InvokePython()
{
    PythonInvoker::InitPythonEnv();
    std::cout << "Invoke python...:\n";

    std::string strModuleName = "Extend";
    PythonInvoker::InvokePython(strModuleName, "HelloWorld");
    auto pArgs = Py_BuildValue("ii", 3, 4);
    auto nCode = PythonInvoker::InvokePython(strModuleName, "Add", pArgs);

    return nCode;
}

int main()
{
    InvokePython();


    std::cout << "Test finished\n";
    getchar();
    return 0;
}
// Extend.py
# import PythonExtend
import PythonExtend


# function HelloWorld
def HelloWorld():
    print('Hello World!')
    # invoke C/C++ function
    PythonExtend.py_Print("Hello")

# function Add
def Add(x, y):
    print('Add', x, 'and', y)
    return x + y

参考官网地址:https://docs.python.org/3/extending/extending.html#intermezzo-errors-and-exceptions

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值