Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的Python线程_Python_C_Multithreading - Fatal编程技术网

C语言中的Python线程

C语言中的Python线程,python,c,multithreading,Python,C,Multithreading,我正在用C编写一个多线程程序。在创建线程之前,通过调用初始化一个全局python环境。然后,在每个创建的线程中,全局python环境是共享的,每个线程使用C语言转换的参数调用python方法 在加载的python模块中使用time.sleep()时,C程序会引发分段错误。此外,加载的python模块应该加载另一个C库以继续工作。我编写了以下愚蠢的计数器库来测试它: python部分,调用计数器函数 lib=ctypes.cdll.LoadLibrary(libpycount.so) 对于X范围内

我正在用C编写一个多线程程序。在创建线程之前,通过调用初始化一个全局python环境。然后,在每个创建的线程中,全局python环境是共享的,每个线程使用C语言转换的参数调用python方法

在加载的python模块中使用
time.sleep()
时,C程序会引发
分段错误。此外,加载的python模块应该加载另一个C库以继续工作。我编写了以下愚蠢的计数器库来测试它:

python部分,调用计数器函数 lib=ctypes.cdll.LoadLibrary(libpycount.so) 对于X范围内的i(10): lib.count()
//C部分,虚拟计数
#包括
int计数器=1;
无效的
计数(){
printf(“计数器:%d\n”,计数器);
计数器++;
}
我想这可能是因为我没有以正确的方式管理复杂的线程创建。我在python文档中找到了


有什么想法或建议吗?

问题是Python解释器是否是线程安全的——这就是文档中关于在同一进程空间中运行多个解释器的内容

错误和警告:因为子解释器(和主解释器) 是同一过程的一部分,它们之间的绝缘层不是 完美--例如,使用低级文件操作,如 os.close()它们可能(意外或恶意)影响彼此的行为 打开文件。因为扩展是在不同用户之间共享的 (副)口译员,某些扩展可能无法正常工作;这是 尤其是当扩展使用(静态)全局 变量,或者当扩展操作其模块的字典时 在初始化之后。可以插入在中创建的对象 将一个子解释器转换为另一个子解释器的名称空间;这 应该非常小心,避免共享用户定义的 子口译员之间的函数、方法、实例或类, 因为这些对象执行的导入操作可能会影响错误的 加载模块的(子)解释器字典。(XXX这是一个 难以修复的bug将在未来版本中解决。)


…我不认为Python线程与C/C++中的本机线程是一回事。

我的问题已经解决了。您可能会遇到更为特殊的问题,因此我在这里尝试以更通用的方式编写解决方案。希望能有帮助


-在主C线程中
  • 从一开始就初始化Python环境:
/*定义一个全局变量来存储python主线程状态*/
PyThreadState*mainThreadState=NULL;
如果(!Py_已初始化())
Py_初始化();
mainThreadState==PyThreadState_Get();
  • 然后启动C线程:
pthread_create(pthread_id,NULL,thread_入口,NULL);


-在每一个线程中,或者我们可以说在线程体中的函数
  • 为环境做好准备:
/*获取锁并创建新的python线程状态*/
PyEval_AcquireLock();
PyExpressorState*MainExpressorState=mainThreadState->interp;
PyThreadState*myThreadState=PyThreadState_New(主解释器状态);
PyEval_ReleaseLock()/*别忘了打开锁*/
/*
*这里有一些C操作
*/
  • 将嵌入的Python代码放在此处:
/*获取锁并将C-Python代码放在此处*/
PyEval_AcquireLock();
PyThreadState_交换(myThreadState)/*交换python线程状态*/
PyEval_调用对象(py_函数,py_参数);
/*或者像PyRun_SimpleString(“打印“hello world”);测试*/
PyThreadState_交换(空)/*离开前清洁线程状态*/
PyEval_ReleaseLock();


-返回主C线程
  • 当每个线程完成工作时,完成python环境
pthread_join(pthread_id,NULL);
PyEval_RestoreThread(主线程状态);
Py_Finalize();

您是否真的遵循了找到的文档中的建议?你是如何在调用Python的代码中获取GIL的?@Thomas Wouters我使用了
PyGILState\u STATE gstate
gstate=PyGILState_sure()和<代码>PyGILState_发布(gstate)如文件中所述。