我的应用程序提供了python插件系统。为了从c#调用python。我编写了一个嵌入python dll的C包装器。你可以在这里找到要点 C wrapper gist 。
然后我在C#中使用P / Invoke来调用C dll。像这样:
[DllImport("PyWinAlfred.dll")] private extern static IntPtr ExecPython(string directory, string file, string query);
如果我没有在C#创建的多个线程中执行上面的代码,那就没关系。问题是如果我没有使用线程,c#中的主线程将被阻塞,而python代码需要很长时间才能执行。
这是我使用的C#多线程代码:
ThreadPool.QueueUserWorkItem(state => { ExecPython(directory,file,query); });
所以,我尝试在C包装器代码中添加多个线程支持。正如你在那个要点中看到的那样。我试着添加:
// Create GIL/enable threads PyEval_InitThreads(); PyGILState_STATE gstate = PyGILState_Ensure(); //python codes PyGILState_Release(gstate);
但这对我不起作用。当我创建一些线程来调用那个dll时,我会得到一个异常。
我也试过以下代码。仍然没有奏效。
PyThreadState* state = PyThreadState_Get(); // Once in each thread PyThreadState* stateForNewThread = PyThreadState_New(state->interp); PyEval_RestoreThread(stateForNewThread); //python codes PyEval_SaveThread();
我想知道这是否是因为我在每次调用中都放了Py_Initialize();
。当thread2执行Py_Initialize();
时,将清除thread1可能需要的所有信息。我尝试在应用程序启动时调用Py_Initialize()
,因此它只会调用一次。但没有奏效。看起来这两个调用在p / invoke调用中是完全隔离的。
我在C中很差并且嵌入了python,有没有人有相关经验?我的项目主持人https://github.com/qianlifeng/WinAlfred如果你们想看到我上面描述的代码。