使用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的情况请参考相关资料

posted @ 2022-10-12 16:20  乘舟凉  阅读(569)  评论(0编辑  收藏  举报