使用c++调用python(二):传入回调函数
传入回调函数大概的原理是用c++构建一个python模块,并将回调函数定义进去
initializer.h
#pragma once
#include <Python.h>
#ifdef _WIN32
#include <Windows.h>
#elif defined __APPLE__
#endif
PyObject* callBack(PyObject* self, PyObject* args);
extern PyMethodDef module_methods[2];
extern struct PyModuleDef cModPyDem;
PyObject* PyInitCppcallBack(void);
class initializer {
public:
initializer() {
#ifdef _WIN32
#include <Windows.h>
SetDllDirectory(TEXT("python37\\"));
#elif defined __APPLE__
#endif
Py_SetPythonHome((wchar_t*)(L"."));
PyImport_AppendInittab("CppcallBack", &PyInitCppcallBack);
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.argv.append('1')");
PyRun_SimpleString("sys.path.insert(0,'.')");
//PyRun_SimpleString("print(sys.path)");
}
~initializer() {
Py_Finalize();
}
};
initializer.cpp
#include "initializer.h"
#include <iostream>
PyMethodDef module_methods[] = {
{"exec", callBack, METH_VARARGS},
{NULL, NULL}
};
void (*sayHello)();
struct PyModuleDef cModPyDem =
{
PyModuleDef_HEAD_INIT,
"CppcallBack", /* name of module */
"", /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
module_methods
};
PyObject* PyInitCppcallBack(void)
{
return PyModule_Create(&cModPyDem);
}
static PyObject* callBack(PyObject* self, PyObject* args)
{
PyArg_Parse(args, "(L)", &sayHello);
PyErr_Print();
if(sayHello!=0)
sayHello();
return Py_BuildValue("i", 1);;
}
上面的代码主要是定义了一个python模块CppcallBack,该模块含有callBack函数
定义方法
PyMethodDef module_methods[] = {
{"exec", callBack, METH_VARARGS},
... //可以多添加几个函数
{NULL, NULL}
};
定义模块
struct PyModuleDef cModPyDem =
{
PyModuleDef_HEAD_INIT,
"CppcallBack", /* name of module */
"", /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
module_methods
};
main.cpp
#include <iostream>
#include "initializer.h"
using namespace std;
initializer initer;
void setCallback(void (*callback)(void)) {
bool result = true;
PyObject* pModule = PyImport_ImportModule("test");
if (pModule == NULL) {
PyErr_Print();
cout << "module not found" << endl;
return;
}
PyObject* pFunc = PyObject_GetAttrString(pModule, "setCallback");
if (!pFunc || !PyCallable_Check(pFunc)) {
PyErr_Print();
cout << "not found function init" << endl;
return;
}
PyObject* arg_list = Py_BuildValue("(L)", callback);
PyObject* pReturn = PyObject_CallObject(pFunc, arg_list);
PyErr_Print();
}
void useCallback() {
PyObject* pModule = PyImport_ImportModule("test");
if (pModule == NULL) {
PyErr_Print();
cout << "module not found" << endl;
return;
}
PyObject* pFunc = PyObject_GetAttrString(pModule, "useCallback");
if (!pFunc || !PyCallable_Check(pFunc)) {
PyErr_Print();
cout << "not found function init" << endl;
return;
}
PyObject* pReturn = PyObject_CallObject(pFunc, 0);
PyErr_Print();
return;
}
int main() {
setCallback([]() {
std::cout << "hello world!" << endl;
});
useCallback();
getchar();
return 0;
}
test.py
class Cons:
callback = None
def setCallback(callback):
Cons.callback = callback
def useCallback():
import CppcallBack
CppcallBack.exec(Cons.callback)
上面的代码通过setCallback将自定义回调函数传入python,赋值给Cons.callback,在通过python回调函数exec传回c++,在exec内自定义回调函数
在构建项目的时候会遇到 error LNK2019: 无法解析的外部符号 __imp_PyModule_Create2TraceRefs的情况请参考相关资料