首先,所有python的函数都是用extern "C"定义的,因此对于C和C++,其使用是一样的。
c语言调用python必须要有的API(不管有没有多线程):
PyRun_SimpleString //执行一段python代码 PyImport_Import //导入python模块 PyModule_GetDict//因为python一个模块就是一个命名空间,命名空间由dict对象实现的 PyDict_GetItemString PyTuple_New//创建一个元组,c语言和python之间通过元组传参 Py_BuildValue PyTuple_SetItem PyObject_Call//调用python函数对象
python类型xx转为C语言的类型yy: 用PyxxAsyy函数
C类型YY转为python的XX类型要用:PyXXFromYY函数
C语言调用python之前要初始化,用完之后要销毁:
Py_Initialize(); //初始化 do_something..... Py_Finalize(); //销毁,此后不能再调用有关python的API
众所周知,python有一个臭名昭著的GIL全局解释锁,拿到这个锁的线程才能执行python程序。所以在用C语言的多线程调用python之前,还需要调用下面的函数:
PyEval_InitThreads(); 以下两个函数的效果相当,用于释放GIL锁 // PyEval_ReleaseThread(PyThreadState_Get()); // PyEval_ReleaseLock(); do_something()..... PyGILState_Ensure();
调用PyEval_InitThreads()函数的线程(一般是主线程),也就拿到了这个GIL锁,必须主动地释放这个锁,以便它创建的线性能够拿到这把锁。所以上边的代码加上了两行注释。
在子线程函数中,必须主动去获得这个GIL, 用完之后进行释放,最好的方法是定义一个类。用完之后自动析构。
class PyThreadStateLock { public: PyThreadStateLock() { state = PyGILState_Ensure(); //获得锁 } ~PyThreadStateLock() { PyGILState_Release(state); //释放锁 } private: PyGILState_STATE state; };
我写了一个python程序,接受一个int型变量的参数,然后打印它。命名为mypy.py
#_*_ coding:utf-8 _*_ #!/usr/bin/python2.7 def my_pFun(a): print "a = :" + str(a)
然后是c++程序,主线程创建三个线程,分别调用这个python 程序。命名为helloPython.cpp
#include <Python.h> #include <pthread.h> #include <iostream> using namespace std; class PyThreadStateLock { public: PyThreadStateLock() { state = PyGILState_Ensure(); } ~PyThreadStateLock() { PyGILState_Release(state); } private: PyGILState_STATE state; }; PyObject* pFunc = NULL;//全局可调用的python程序中的函数 void pFunc_init() { PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')"); PyObject* pyModule = PyImport_Import(PyString_FromString("mypy")); if(pyModule == NULL) { printf("load mypy failed\n"); exit(0); } PyObject* pDict = PyModule_GetDict(pyModule); pFunc = PyDict_GetItemString(pDict, "my_pFun"); } void * threadFunc(void* arg) { //PyEval_ReleaseLock(); pthread_detach(pthread_self()); PyObject* pkwargs = NULL; PyThreadStateLock PyThreadLock; int a = *(int*)arg; delete (int*)arg; cout << "in thread:" << pthread_self() << " ****" << a << endl; PyObject* pArgs = PyTuple_New(1); PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a)); PyObject_Call(pFunc, pArgs, pkwargs); cout << "sleep" << endl; sleep(3); //exit(0);//如果使用这个函数,直接退出该进程 //pthread_exit(NULL); } int main(int argc, char *argv[]) { Py_Initialize(); PyEval_InitThreads(); pFunc_init(); pthread_t tid[3]; PyEval_ReleaseThread(PyThreadState_Get()); for(int i = 0; i < 3; i++) { int* j = new int(i); //这里不能传&i进去,否则所有的线程获得同一个地址 pthread_create(&tid[i], NULL, threadFunc, j); } for(int i = 0; i < 3; i++) { pthread_join(tid[i], NULL);//使用了pthread_detach还是要join,或者sleep也可以 } PyGILState_Ensure(); Py_Finalize(); return 0; }
编译过程:
<span style="font-size:16px;">g++ -I /usr/include/python2.7/ helloPython.cpp -o main -lpython2.7 -lpthread -g</span>
运行结果:
标签:调用,函数,示例,Python,python,state,PyThreadStateLock,多线程,PyGILState From: https://www.cnblogs.com/lidabo/p/17076820.html