1

我的应用程序提供 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(状态 =>
{
   ExecPython(目录、文件、查询);
});

因此,我尝试在 C 包装器代码中添加多线程支持。正如你在那个要点中看到的那样。我试图添加:

// 创建 GIL/启用线程
PyEval_InitThreads();
PyGILState_STATE gstate = PyGILState_Ensure();

//python代码

PyGILState_Release(gstate);

但这对我不起作用。当我创建一些线程来调用该 dll 时,我会得到一个异常。

我还尝试了以下代码。仍然没有工作。

PyThreadState* 状态 = PyThreadState_Get();
// 每个线程一次
PyThreadState* stateForNewThread = PyThreadState_New(state->interp);
PyEval_RestoreThread(stateForNewThread);

//python代码

PyEval_SaveThread();

我想知道这是否是因为我输入Py_Initialize();了每个调用。当 thread2 执行时,Py_Initialize();将清除 thread1 可能需要的所有信息。我试图Py_Initialize()在我的应用程序启动时调用,所以它只会被调用一次。但是没有用。看起来这两个调用在 p/invoke 调用中是完全隔离的。

我在C和嵌入python方面很差,有人有相关经验吗?我的项目托管在https://github.com/qianlifeng/WinAlfred如果你们想看我上面描述的代码。

4

1 回答 1

1

最后,我找到了 http://pythonnet.github.io/。您可以在此项目WinAlfred中找到详细信息。我解决了这个项目中的多线程问题。

于 2014-01-25T16:35:59.497 回答