首页 > 系统相关 >Linux的多线程下使用c/c++调用Python方法示例

Linux的多线程下使用c/c++调用Python方法示例

时间:2023-01-30 17:58:07浏览次数:42  
标签:调用 函数 示例 Python python state PyThreadStateLock 多线程 PyGILState

首先,所有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

相关文章

  • 通过一个示例形象地理解C# async await异步
    前言相信大家看过不少讲C#asyncawait的文章,博客园就能搜到很多,但还是有很多C#程序员不明白。如果搞不明白,其实也不影响使用。但有人就会疑惑,为什么要用异步?我感觉它更......
  • gdb同时调试python和c++
    说明:当我们的python程序的一些函数的后端实现为C++时(比如Pytorch,TensorFlow或tvm等)可以使用当前方法调试。有两种方式可以安装调试环境:一.搭建环境有两种方式搭建......
  • python的split函数切分字符串时为什么会产生空字符串
    群里的一个小伙伴提了一个问题,他使用split函数切分字符串得到的结果里有空字符串,他对空字符串的出现感到困惑不解。text='1aa2'print(text.split('a'))#['1','',......
  • 使用python的tempfile模块创建临时文件
    什么样的情况下需要我创建临时文件呢?我很早就知道tempfile这个模块,但一直没有使用过它,也没有兴趣去研究它,一度认为自己用不到这个模块。存在即合理,合理的才能存在,想来是我不......
  • python判断一个进程是否存在的3种方法
    在python中,如何判断一个进程是否存在呢?可以使用Popen执行shell命令判断进程是否存在,或者检查/proc目录下是否存在进程相对应的目录,最佳的方法是向进程发送信号0,下面分别介......
  • python读取csv文件的正确方式
    准备数据name,age小明,14小刚,15通常,我们用下面的代码读取csvimportcsvwithopen(r'C:\Users\zhangdongsheng\Desktop\data.csv',encoding='utf-8')asf:reader=csv......
  • 一文看懂python的迭代器和可迭代对象
    阅读完本文,你将收获以下知识点:什么是迭代器和可迭代对象,他们之间有什么关系迭代器可以迭代的底层原理是什么如何自定义可迭代对象和迭代器迭代器和可迭代对象是两个非常难以......
  • 从python列表里删除一个元素会对reversed() 产生怎样的影响
    这是一个在stackoverflow上看到的问题,非常的有趣且值得研究。1.iter使用iter函数返回列表的迭代器,随后从列表里删除一个元素,在遍历迭代器时,输出的内容会是怎样的呢?lst=['......
  • 用python实现一个自动保存复制图片的功能
    由于经常写作,需要为文章准备一些配图,通常这些配图是从百度图片搜索里准备的。在准备图片时,我遇到了两个小麻烦:有些图片的格式是webp,需要在另存为时指定格式有些图片需要剪切......
  • zodb,一个python对象数据库
    1.什么是对象数据库关系型数据库,是指采用了关系模型来组织数据的数据库,以行和列的形式存储数据库,典型如mysql。NoSQL数据库,是指非关系型数据库,典型如mongodb。对象数据库,是......