From 5893564f46dac0af5ef04926c4ae7cad00a8f0ca Mon Sep 17 00:00:00 2001 From: qianlifeng Date: Fri, 27 Dec 2013 20:06:49 +0800 Subject: [PATCH] Change Python C Wrapper --- PyWinAlfred/Main.cpp | 163 +++++++++++------- PyWinAlfred/PyWinAlfred.vcxproj | 2 +- WinAlfred/MainWindow.xaml.cs | 6 +- WinAlfred/PluginLoader/PythonPluginWrapper.cs | 14 +- WinAlfred/ResultPanel.xaml.cs | 2 +- 5 files changed, 123 insertions(+), 64 deletions(-) diff --git a/PyWinAlfred/Main.cpp b/PyWinAlfred/Main.cpp index 5934d9f01..75306ab75 100644 --- a/PyWinAlfred/Main.cpp +++ b/PyWinAlfred/Main.cpp @@ -1,69 +1,116 @@ #include #include "Python.h" - +#include +#include extern "C" __declspec(dllexport) void InitPythonEnv() { + Py_Initialize(); + PyEval_InitThreads(); +} +char* GetErrorMessage() +{ + char *pStrErrorMessage = NULL; + + if(PyErr_Occurred()){ + PyObject *ptype, *pvalue, *ptraceback; + PyErr_Fetch(&ptype, &pvalue, &ptraceback); + pStrErrorMessage = PyString_AsString(pvalue); + } + + return pStrErrorMessage; +} + + +char* Exec(char* directory, char* file, char* method, char* para) +{ + PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pClass, *pInstance; + char *error; + + PyThreadState* global_state = PyThreadState_Get(); + PyThreadState* ts = Py_NewInterpreter(); + PyThreadState_Swap(ts); + // Initialise the Python interpreter + + // Create GIL/enable threads + + //PyGILState_STATE gstate = PyGILState_Ensure(); + // // Get the default thread state + // PyThreadState* state = PyThreadState_Get(); + // // Once in each thread + //PyThreadState* stateForNewThread = PyThreadState_New(state->interp); + //PyEval_RestoreThread(stateForNewThread); + + // Build the name object + PyObject *sys = PyImport_ImportModule("sys"); + PyObject *path = PyObject_GetAttrString(sys, "path"); + PyList_Append(path, PyString_FromString(directory)); + + pName = PyString_FromString(file); + error = GetErrorMessage(); + if(error != NULL){ + char* err =new char[5000](); + sprintf(error, "%s:%s","PYTHONERROR",error); + return err; + } + + pModule = PyImport_Import(pName); + error = GetErrorMessage(); + if(error != NULL){ + char* err =new char[5000](); + sprintf(err, "%s:%s","PYTHONERROR",error); + return err; + } + + pDict = PyModule_GetDict(pModule); + error = GetErrorMessage(); + if(error != NULL){ + char* err =new char[5000](); + sprintf(err, "%s:%s","PYTHONERROR",error); + return err; + } + + pClass = PyDict_GetItemString(pDict,"PyWinAlfred"); + error = GetErrorMessage(); + if(error != NULL){ + char* err =new char[5000](); + sprintf(err, "%s:%s","PYTHONERROR",error); + return err; + } + + pInstance = PyObject_CallObject(pClass, NULL); + error = GetErrorMessage(); + if(error != NULL){ + char* err =new char[5000](); + sprintf(err, "%s:%s","PYTHONERROR",error); + return err; + } + + // Call a method of the class with two parameters + pValue = PyObject_CallMethod(pInstance,method, "(s)",para); + error = GetErrorMessage(); + if(error != NULL){ + char* err =new char[5000](); + sprintf(err, "%s:%s","PYTHONERROR",error); + return err; + } + + char * str_ret = PyString_AsString(pValue); + + //PyEval_SaveThread(); + + // Finish the Python Interpreter + + PyErr_Clear(); + Py_EndInterpreter(ts); + PyThreadState_Swap(global_state); + + return str_ret; } extern "C" __declspec(dllexport) char* ExecPython(char* directory, char* file, char* method, char* para) { - try{ - PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pClass, *pInstance; - - // Initialise the Python interpreter - Py_Initialize(); - - // Create GIL/enable threads - //PyEval_InitThreads(); - - //PyGILState_STATE gstate = PyGILState_Ensure(); - // // Get the default thread state - // PyThreadState* state = PyThreadState_Get(); - // // Once in each thread - //PyThreadState* stateForNewThread = PyThreadState_New(state->interp); - //PyEval_RestoreThread(stateForNewThread); - - // Build the name object - PyObject *sys = PyImport_ImportModule("sys"); - PyObject *path = PyObject_GetAttrString(sys, "path"); - PyList_Append(path, PyString_FromString(directory)); - - pName = PyString_FromString(file); - - // Load the module object - pModule = PyImport_Import(pName); - - // pDict is a borrowed reference - pDict = PyModule_GetDict(pModule); - - // pFunc is also a borrowed reference - pClass = PyDict_GetItemString(pDict,"PyWinAlfred"); - - if (PyCallable_Check(pClass)) - { - pInstance = PyObject_CallObject(pClass, NULL); - } - else - { - PyErr_Print(); - return "failed"; - } - - // Call a method of the class with two parameters - pValue = PyObject_CallMethod(pInstance,method, "(s)",para); - char * str_ret = PyString_AsString(pValue); - - //PyGILState_Release(gstate); - //PyEval_SaveThread(); - - // Finish the Python Interpreter - //Py_Finalize(); - - return str_ret; - } - catch(int& value){ - PyErr_Print(); - } + auto future = std::async(Exec,directory,file,method,para); + return future.get(); } \ No newline at end of file diff --git a/PyWinAlfred/PyWinAlfred.vcxproj b/PyWinAlfred/PyWinAlfred.vcxproj index 22d14e864..6251ad6ae 100644 --- a/PyWinAlfred/PyWinAlfred.vcxproj +++ b/PyWinAlfred/PyWinAlfred.vcxproj @@ -103,7 +103,7 @@ Level3 Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;PYWINALFRED_EXPORTS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;_USRDLL;PYWINALFRED_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true diff --git a/WinAlfred/MainWindow.xaml.cs b/WinAlfred/MainWindow.xaml.cs index 7eea9d383..0c3d2aa2c 100644 --- a/WinAlfred/MainWindow.xaml.cs +++ b/WinAlfred/MainWindow.xaml.cs @@ -68,8 +68,8 @@ namespace WinAlfred private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e) { string query = tbQuery.Text; - ThreadPool.QueueUserWorkItem(state => - { + //ThreadPool.QueueUserWorkItem(state => + //{ results.Clear(); foreach (PluginPair pair in plugins) { @@ -98,7 +98,7 @@ namespace WinAlfred resultCtrl.AddResults(results.OrderByDescending(o => o.Score).ToList()); resultCtrl.SelectFirst(); })); - }); + //}); } private void HideWinAlfred() diff --git a/WinAlfred/PluginLoader/PythonPluginWrapper.cs b/WinAlfred/PluginLoader/PythonPluginWrapper.cs index bb82e02b8..c9647a573 100644 --- a/WinAlfred/PluginLoader/PythonPluginWrapper.cs +++ b/WinAlfred/PluginLoader/PythonPluginWrapper.cs @@ -25,12 +25,24 @@ namespace WinAlfred.PluginLoader try { string s = Marshal.PtrToStringAnsi(ExecPython(metadata.PluginDirecotry, metadata.ExecuteFileName.Replace(".py", ""), "query", query.RawQuery)); + if (string.IsNullOrEmpty(s)) + { + return new List(); + } + + if (s.StartsWith("PYTHONERROR")) + { + throw new ArgumentException(s); + } List o = JsonConvert.DeserializeObject>(s); List r = new List(); foreach (PythonResult pythonResult in o) { PythonResult ps = pythonResult; - ps.Action = () => ExecPython(metadata.PluginDirecotry, metadata.ExecuteFileName.Replace(".py", ""), ps.ActionName, ps.ActionPara); + if (!string.IsNullOrEmpty(ps.ActionName)) + { + ps.Action = () => ExecPython(metadata.PluginDirecotry, metadata.ExecuteFileName.Replace(".py", ""), ps.ActionName, ps.ActionPara); + } r.Add(ps); } return r; diff --git a/WinAlfred/ResultPanel.xaml.cs b/WinAlfred/ResultPanel.xaml.cs index 9c59fa1dd..40314fcad 100644 --- a/WinAlfred/ResultPanel.xaml.cs +++ b/WinAlfred/ResultPanel.xaml.cs @@ -152,7 +152,7 @@ namespace WinAlfred var resultItemControl = pnlContainer.Children[index] as ResultItem; if (resultItemControl != null) { - resultItemControl.Result.Action(); + if (resultItemControl.Result.Action != null) resultItemControl.Result.Action(); } }