|
@@ -1,98 +1,117 @@
|
|
|
#include "StdAfx.h"
|
|
|
#include "CallPython.h"
|
|
|
+#include "CharEncoding.h"
|
|
|
|
|
|
-namespace CallPython {
|
|
|
- void InitPython()
|
|
|
- {
|
|
|
- if (!Py_IsInitialized())
|
|
|
- Py_Initialize();
|
|
|
- }
|
|
|
+CCallPython::CCallPython()
|
|
|
+{
|
|
|
+ _state = PyGILState_Ensure();
|
|
|
+}
|
|
|
|
|
|
- void FreePython()
|
|
|
- {
|
|
|
- Py_Finalize();
|
|
|
- }
|
|
|
+CCallPython::~CCallPython()
|
|
|
+{
|
|
|
+ PyGILState_Release(_state);
|
|
|
+}
|
|
|
|
|
|
- void PySetItem(PyObject* args, _variant_t var, int nIndex)
|
|
|
- {
|
|
|
- if (args == NULL || nIndex < 0)
|
|
|
- return;
|
|
|
+void CCallPython::Init()
|
|
|
+{
|
|
|
+ Py_Initialize();
|
|
|
+ if (!Py_IsInitialized())
|
|
|
+ return;
|
|
|
+ // 不用多线程,不用开启下面功能;
|
|
|
+ // 初始化线程支持
|
|
|
+ //PyEval_InitThreads();
|
|
|
+ // 启动子线程前执行,为了释放PyEval_InitThreads获得的全局锁,否则子线程可能无法获取到全局锁。
|
|
|
+ //PyEval_ReleaseThread(PyThreadState_Get());
|
|
|
+}
|
|
|
|
|
|
- switch (var.vt)
|
|
|
- {
|
|
|
+void CCallPython::Free()
|
|
|
+{
|
|
|
+ // 保证子线程调用都结束后
|
|
|
+ PyGILState_Ensure();
|
|
|
+ Py_Finalize();
|
|
|
+}
|
|
|
+
|
|
|
+void PySetItem(PyObject* args, _variant_t var, int nIndex)
|
|
|
+{
|
|
|
+ if (args == NULL || nIndex < 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ PyObject* pValue;
|
|
|
+ switch (var.vt)
|
|
|
+ {
|
|
|
case VT_BSTR:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("s", var.bstrVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("u", var.bstrVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_LPSTR:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("s", var.bstrVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("s", var.bstrVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_I1:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("b", var.cVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("b", var.cVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_I2:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("h", var.iVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("h", var.iVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_I4:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("i", var.lVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("i", var.lVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_I8:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("k", var.lVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("k", var.lVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_INT:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("i", var.intVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("i", var.intVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_UI1:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("B", var.cVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("B", var.cVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_UI2:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("H", var.iVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("H", var.iVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_UI4:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("I", var.lVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("I", var.lVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_UI8:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("K", var.lVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("K", var.lVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_UINT:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("I", var.intVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("I", var.intVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_R4:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("f", var.fltVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("f", var.fltVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_R8:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("f", var.dblVal));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("f", var.dblVal));
|
|
|
break;
|
|
|
}
|
|
|
case VT_BOOL:
|
|
|
{
|
|
|
- PyTuple_SetItem(args, nIndex, Py_BuildValue("b", (var.boolVal == false) ? 0 : 1));
|
|
|
+ PyTuple_SetItem(args, nIndex, pValue = Py_BuildValue("b", (var.boolVal == false) ? 0 : 1));
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
@@ -100,65 +119,115 @@ namespace CallPython {
|
|
|
TRACE("UnSupport type for Python: %d\n", var.vt);
|
|
|
break;
|
|
|
}
|
|
|
- }
|
|
|
+
|
|
|
+ if (pValue)
|
|
|
+ Py_DECREF(pValue);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- PyObject* CallPython(std::string strPyPath, std::string strPyFuncName, int argc, ...)
|
|
|
- {
|
|
|
- if (!Py_IsInitialized())
|
|
|
- Py_Initialize();
|
|
|
-
|
|
|
- if (!PathFileExists(strPyPath.c_str()) || !strPyFuncName.size())
|
|
|
- return NULL;
|
|
|
-
|
|
|
- TCHAR szDrive[_MAX_DRIVE] = { 0 };
|
|
|
- TCHAR szDir[_MAX_DIR] = { 0 };
|
|
|
- TCHAR szExt[_MAX_EXT] = { 0 };
|
|
|
- TCHAR szFilename[_MAX_FNAME] = { 0 };
|
|
|
- TCHAR szScriptDir[MAX_PATH] = { 0 };
|
|
|
- _tsplitpath_s(strPyPath.c_str(), szDrive, szDir, szFilename, szExt);
|
|
|
- _stprintf_s(szScriptDir, _T("%s%s"), szDrive, szDir);
|
|
|
- int len = _tcslen(szScriptDir);
|
|
|
- for (int i = 0; i < len; i++) {
|
|
|
- if (szScriptDir[i] == '\\')
|
|
|
- szScriptDir[i] = '/';
|
|
|
- }
|
|
|
-
|
|
|
- if (szScriptDir[0] == '\0')
|
|
|
- _tcscpy_s(szScriptDir, _T("./"));
|
|
|
-
|
|
|
- TCHAR szExecuteDir[MAX_PATH] = { 0 };
|
|
|
- _stprintf_s(szExecuteDir, _T("sys.path.append('%s')"), szScriptDir);
|
|
|
- PyRun_SimpleString("import sys");
|
|
|
- PyRun_SimpleString(szExecuteDir);
|
|
|
-
|
|
|
- PyObject* pModule = PyImport_ImportModule(szFilename);
|
|
|
- if (!pModule)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- PyObject* pFunc = PyObject_GetAttrString(pModule, strPyFuncName.c_str());
|
|
|
- if (!pFunc || !PyCallable_Check(pFunc))
|
|
|
- return NULL;
|
|
|
-
|
|
|
- PyObject* pRet = NULL;
|
|
|
- if (argc != 0) {
|
|
|
- va_list ap;
|
|
|
- va_start(ap, argc);
|
|
|
- PyObject* args = PyTuple_New(argc);
|
|
|
- if (!args) {
|
|
|
- va_end(ap);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- for (int i = 0; i < argc; i++) {
|
|
|
- PySetItem(args, va_arg(ap, _variant_t), i);
|
|
|
- }
|
|
|
+PyObject* CCallPython::CallPython(std::string strPyPath, std::string strPyFuncName, int argc, ...)
|
|
|
+{
|
|
|
+ if (!Py_IsInitialized())
|
|
|
+ Py_Initialize();
|
|
|
+
|
|
|
+ if (!PathFileExists(strPyPath.c_str()) || !strPyFuncName.size())
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ TCHAR szDrive[_MAX_DRIVE] = { 0 };
|
|
|
+ TCHAR szDir[_MAX_DIR] = { 0 };
|
|
|
+ TCHAR szExt[_MAX_EXT] = { 0 };
|
|
|
+ TCHAR szFilename[_MAX_FNAME] = { 0 };
|
|
|
+ TCHAR szScriptDir[MAX_PATH] = { 0 };
|
|
|
+ _tsplitpath_s(strPyPath.c_str(), szDrive, szDir, szFilename, szExt);
|
|
|
+ _stprintf_s(szScriptDir, _T("%s%s"), szDrive, szDir);
|
|
|
+ int len = _tcslen(szScriptDir);
|
|
|
+ for (int i = 0; i < len; i++) {
|
|
|
+ if (szScriptDir[i] == '\\')
|
|
|
+ szScriptDir[i] = '/';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (szScriptDir[0] == '\0')
|
|
|
+ _tcscpy_s(szScriptDir, _T("./"));
|
|
|
+
|
|
|
+ TCHAR szExecuteDir[MAX_PATH] = { 0 };
|
|
|
+ _stprintf_s(szExecuteDir, _T("sys.path.append('%s')"), szScriptDir);
|
|
|
+ PyRun_SimpleString("import sys");
|
|
|
+ PyRun_SimpleString("sys.path.append('./')");
|
|
|
+ PyRun_SimpleString("reload(sys)");
|
|
|
+ PyRun_SimpleString(szExecuteDir);
|
|
|
+ _stprintf_s(szExecuteDir, _T("reload('%s')"), szScriptDir);
|
|
|
+ PyRun_SimpleString(szExecuteDir);
|
|
|
+
|
|
|
+ PyObject* args = NULL;
|
|
|
+ PyObject* pRet = NULL;
|
|
|
+ PyObject* pFunc = NULL;
|
|
|
+ PyObject* pModule = PyImport_ImportModule(szFilename);
|
|
|
+ if (!pModule)
|
|
|
+ goto over;
|
|
|
+
|
|
|
+ pFunc = PyObject_GetAttrString(pModule, strPyFuncName.c_str());
|
|
|
+ if (!pFunc || !PyCallable_Check(pFunc))
|
|
|
+ goto over;
|
|
|
+
|
|
|
+ if (argc != 0) {
|
|
|
+ va_list ap;
|
|
|
+ va_start(ap, argc);
|
|
|
+ args = PyTuple_New(argc);
|
|
|
+ if (!args) {
|
|
|
va_end(ap);
|
|
|
- pRet = PyObject_CallObject(pFunc, args);
|
|
|
+ goto over;
|
|
|
}
|
|
|
- else
|
|
|
- pRet = PyEval_CallObject(pFunc, NULL);
|
|
|
|
|
|
- return pRet;
|
|
|
+ for (int i = 0; i < argc; i++) {
|
|
|
+ PySetItem(args, va_arg(ap, _variant_t), i);
|
|
|
+ }
|
|
|
+ va_end(ap);
|
|
|
+ pRet = PyObject_CallObject(pFunc, args);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ pRet = PyEval_CallObject(pFunc, NULL);
|
|
|
+
|
|
|
+over:
|
|
|
+ if (args)
|
|
|
+ Py_DECREF(args);
|
|
|
+
|
|
|
+ if (pFunc)
|
|
|
+ Py_DECREF(pFunc);
|
|
|
+
|
|
|
+ if (pModule)
|
|
|
+ Py_DECREF(pModule);
|
|
|
+
|
|
|
+ return pRet;
|
|
|
+}
|
|
|
+
|
|
|
+int CCallPython::GetIntegerValue(PyObject* pValue)
|
|
|
+{
|
|
|
+ int value = 0;
|
|
|
+ if (pValue) {
|
|
|
+ PyArg_Parse(pValue, "i", &value);
|
|
|
+ }
|
|
|
+
|
|
|
+ return value;
|
|
|
+}
|
|
|
+
|
|
|
+std::string CCallPython::GetUnicodeString(PyObject* pValue)
|
|
|
+{
|
|
|
+ std::string strValue;
|
|
|
+ if (pValue) {
|
|
|
+ char* pszValue;
|
|
|
+ PyArg_Parse(pValue, "s", &pszValue);
|
|
|
+ CharEncoding::UNICODE2ASCII((LPWCH)pszValue, strValue);
|
|
|
+ }
|
|
|
+ return strValue;
|
|
|
+}
|
|
|
+
|
|
|
+std::string CCallPython::GetUTF8String(PyObject* pValue)
|
|
|
+{
|
|
|
+ std::string strValue;
|
|
|
+ if (pValue) {
|
|
|
+ char* pszValue;
|
|
|
+ PyArg_Parse(pValue, "s", &pszValue);
|
|
|
+ CharEncoding::UTF82ASCII(pszValue, strValue);
|
|
|
}
|
|
|
-}
|
|
|
+ return strValue;
|
|
|
+}
|