// 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