Python: implement support for marshalling arrays

Fixes #3858
This commit is contained in:
Gunnar Beutner 2013-03-14 14:00:10 +01:00
parent 5b0a413f32
commit 016a881634
2 changed files with 38 additions and 18 deletions

View File

@ -27,7 +27,7 @@ REGISTER_SCRIPTLANGUAGE("Python", PythonLanguage);
PyMethodDef PythonLanguage::m_NativeMethodDef[] = { PyMethodDef PythonLanguage::m_NativeMethodDef[] = {
{ "RegisterFunction", &PythonLanguage::PyRegisterFunction, METH_VARARGS, NULL }, { "RegisterFunction", &PythonLanguage::PyRegisterFunction, METH_VARARGS, NULL },
{ NULL, NULL } /* sentinel */ { NULL, NULL, NULL, NULL } /* sentinel */
}; };
PythonLanguage::PythonLanguage(void) PythonLanguage::PythonLanguage(void)
@ -60,12 +60,11 @@ void PythonLanguage::InitializeOnce(void)
PyEval_ReleaseLock(); PyEval_ReleaseLock();
String name; String name;
ScriptFunction::Ptr function; BOOST_FOREACH(tie(name, tuples::ignore), ScriptFunction::GetFunctions()) {
BOOST_FOREACH(tie(name, function), ScriptFunction::GetFunctions()) { RegisterNativeFunction(name);
RegisterNativeFunction(name, function);
} }
ScriptFunction::OnRegistered.connect(boost::bind(&PythonLanguage::RegisterNativeFunction, this, _1, _2)); ScriptFunction::OnRegistered.connect(boost::bind(&PythonLanguage::RegisterNativeFunction, this, _1));
ScriptFunction::OnUnregistered.connect(boost::bind(&PythonLanguage::UnregisterNativeFunction, this, _1)); ScriptFunction::OnUnregistered.connect(boost::bind(&PythonLanguage::UnregisterNativeFunction, this, _1));
m_Initialized = true; m_Initialized = true;
@ -153,9 +152,26 @@ PyObject *PythonLanguage::MarshalToPython(const Value& value)
PyObject *dv = MarshalToPython(value); PyObject *dv = MarshalToPython(value);
PyDict_SetItemString(pdict, key.CStr(), dv); PyDict_SetItemString(pdict, key.CStr(), dv);
Py_DECREF(dv);
} }
return pdict; return pdict;
} else if (value.IsObjectType<Array>()) {
Array::Ptr arr = value;
ObjectLock olock(arr);
PyObject *plist = PyList_New(0);
BOOST_FOREACH(const Value& value, arr) {
PyObject *dv = MarshalToPython(value);
PyList_Append(plist, dv);
Py_DECREF(dv);
}
return plist;
} }
Py_INCREF(Py_None); Py_INCREF(Py_None);
@ -177,13 +193,24 @@ Value PythonLanguage::MarshalFromPython(PyObject *value)
Py_ssize_t pos = 0; Py_ssize_t pos = 0;
while (PyDict_Next(value, &pos, &dk, &dv)) { while (PyDict_Next(value, &pos, &dk, &dv)) {
String ik = PyString_AsString(dk); String ik = PyString_AsString(dk);
Value iv = MarshalFromPython(dv); Value iv = MarshalFromPython(dv);
dict->Set(ik, iv); dict->Set(ik, iv);
} }
return dict; return dict;
} else if (PyList_Check(value)) {
Array::Ptr arr = boost::make_shared<Array>();
for (Py_ssize_t pos = 0; pos < PyList_Size(value); pos++) {
PyObject *dv = PyList_GetItem(value, pos);
Value iv = MarshalFromPython(dv);
arr->Add(iv);
}
return arr;
} else if (PyTuple_Check(value) && PyTuple_Size(value) == 2) { } else if (PyTuple_Check(value) && PyTuple_Size(value) == 2) {
PyObject *ptype, *pname; PyObject *ptype, *pname;
@ -287,8 +314,6 @@ PyObject *PythonLanguage::PyCallNativeFunction(PyObject *self, PyObject *args)
try { try {
ScriptTask::Ptr task = boost::make_shared<ScriptTask>(function, arguments); ScriptTask::Ptr task = boost::make_shared<ScriptTask>(function, arguments);
task->Start(); task->Start();
task->Wait();
result = task->GetResult(); result = task->GetResult();
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
PyEval_RestoreThread(tstate); PyEval_RestoreThread(tstate);
@ -308,9 +333,8 @@ PyObject *PythonLanguage::PyCallNativeFunction(PyObject *self, PyObject *args)
* Registers a native function. * Registers a native function.
* *
* @param name The name of the native function. * @param name The name of the native function.
* @param function The function.
*/ */
void PythonLanguage::RegisterNativeFunction(const String& name, const ScriptFunction::Ptr& function) void PythonLanguage::RegisterNativeFunction(const String& name)
{ {
ObjectLock olock(this); ObjectLock olock(this);
@ -357,7 +381,7 @@ void PythonLanguage::UnregisterNativeFunction(const String& name)
(void) PyThreadState_Swap(tstate); (void) PyThreadState_Swap(tstate);
} }
PyObject *PythonLanguage::PyRegisterFunction(PyObject *self, PyObject *args) PyObject *PythonLanguage::PyRegisterFunction(PyObject *, PyObject *args)
{ {
char *name; char *name;
PyObject *object; PyObject *object;
@ -390,8 +414,6 @@ PyObject *PythonLanguage::PyRegisterFunction(PyObject *self, PyObject *args)
*/ */
PythonInterpreter *PythonLanguage::GetCurrentInterpreter(void) PythonInterpreter *PythonLanguage::GetCurrentInterpreter(void)
{ {
ObjectLock olock(this);
return m_CurrentInterpreter; return m_CurrentInterpreter;
} }
@ -402,7 +424,5 @@ PythonInterpreter *PythonLanguage::GetCurrentInterpreter(void)
*/ */
void PythonLanguage::SetCurrentInterpreter(PythonInterpreter *interpreter) void PythonLanguage::SetCurrentInterpreter(PythonInterpreter *interpreter)
{ {
ObjectLock olock(this);
m_CurrentInterpreter = interpreter; m_CurrentInterpreter = interpreter;
} }

View File

@ -58,7 +58,7 @@ private:
PyObject *m_TracebackModule; PyObject *m_TracebackModule;
static PythonInterpreter *m_CurrentInterpreter; static PythonInterpreter *m_CurrentInterpreter;
void RegisterNativeFunction(const String& name, const ScriptFunction::Ptr& function); void RegisterNativeFunction(const String& name);
void UnregisterNativeFunction(const String& name); void UnregisterNativeFunction(const String& name);
static PyObject *PyCallNativeFunction(PyObject *self, PyObject *args); static PyObject *PyCallNativeFunction(PyObject *self, PyObject *args);