From 29064590c538792c2dfa50cafbf1723518ef2354 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 28 Jan 2012 08:49:35 -0500 Subject: [PATCH 1/2] Add PyUnicode support to ptPlayer.__init__ --- .../FeatureLib/pfPython/pyPlayerGlue.cpp | 79 ++++++++++--------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyPlayerGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyPlayerGlue.cpp index dced2f27..e64ee87f 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyPlayerGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyPlayerGlue.cpp @@ -49,6 +49,23 @@ PYTHON_CLASS_DEFINITION(ptPlayer, pyPlayer); PYTHON_DEFAULT_NEW_DEFINITION(ptPlayer, pyPlayer) PYTHON_DEFAULT_DEALLOC_DEFINITION(ptPlayer) +static char* ConvertString(PyObject* obj) +{ + if (PyString_Check(obj)) + { + return hsStrcpy(PyString_AsString(obj)); + } else if (PyUnicode_Check(obj)) { + size_t size = PyUnicode_GetSize(obj); + wchar_t* temp = new wchar_t[size + 1]; + PyUnicode_AsWideChar((PyUnicodeObject*)obj, temp, size); + temp[size] = 0; + char* buf = hsWStringToString(temp); + delete[] temp; + return buf; + } else + return NULL; // You suck. +} + PYTHON_INIT_DEFINITION(ptPlayer, args, keywords) { // we have two sets of arguments we can use, hence the generic PyObject* pointers @@ -63,56 +80,46 @@ PYTHON_INIT_DEFINITION(ptPlayer, args, keywords) PyErr_SetString(PyExc_TypeError, "__init__ expects one of two argument lists: (ptKey, string, unsigned long, float) or (string, unsigned long)"); PYTHON_RETURN_INIT_ERROR; } - if (pyKey::Check(firstObj)) // arg set 1 + + pyKey* key = NULL; + char* name = NULL; + uint32_t pid = -1; + float distSeq = -1; + + if (pyKey::Check(firstObj)) { - // make sure the remaining objects fit the arg list - if ((!thirdObj) || (!fourthObj)) - { - // missing arguments - PyErr_SetString(PyExc_TypeError, "__init__ expects one of two argument lists: (ptKey, string, unsigned long, float) or (string, unsigned long)"); - PYTHON_RETURN_INIT_ERROR; - } - if ((!PyString_Check(secondObj)) || (!PyLong_Check(thirdObj)) || (!PyFloat_Check(fourthObj))) + key = pyKey::ConvertFrom(firstObj); + if (!(name = ConvertString(secondObj))) { - // incorrect types PyErr_SetString(PyExc_TypeError, "__init__ expects one of two argument lists: (ptKey, string, unsigned long, float) or (string, unsigned long)"); PYTHON_RETURN_INIT_ERROR; } - // all args are correct, convert and init - pyKey* key = pyKey::ConvertFrom(firstObj); - char* name = PyString_AsString(secondObj); - unsigned long pid = PyLong_AsUnsignedLong(thirdObj); - float distsq = (float)PyFloat_AsDouble(fourthObj); - self->fThis->Init(key->getKey(), name, pid, distsq); - PYTHON_RETURN_INIT_OK; - } - else if (PyString_Check(firstObj)) // arg set 2 - { - // make sure there are only two args - if (thirdObj || fourthObj) + if (!(PyLong_Check(thirdObj) && PyFloat_Check(fourthObj))) { - // too many arguments + delete[] name; PyErr_SetString(PyExc_TypeError, "__init__ expects one of two argument lists: (ptKey, string, unsigned long, float) or (string, unsigned long)"); PYTHON_RETURN_INIT_ERROR; } - char* name = PyString_AsString(firstObj); - unsigned long pid = 0; - if (PyLong_Check(secondObj)) - pid = PyLong_AsUnsignedLong(secondObj); - else if (PyInt_Check(secondObj)) - pid = (unsigned long)PyInt_AsLong(secondObj); - else + + pid = PyLong_AsUnsignedLong(thirdObj); + distSeq = (float)PyFloat_AsDouble(fourthObj); + } else if (name = ConvertString(firstObj)){ + if (!PyLong_Check(secondObj) || thirdObj || fourthObj) { - // incorrect type + delete[] name; PyErr_SetString(PyExc_TypeError, "__init__ expects one of two argument lists: (ptKey, string, unsigned long, float) or (string, unsigned long)"); PYTHON_RETURN_INIT_ERROR; } - self->fThis->Init(nil, name, pid, -1); - PYTHON_RETURN_INIT_OK; + + pid = PyLong_AsUnsignedLong(secondObj); + } else { + PyErr_SetString(PyExc_TypeError, "__init__ expects one of two argument lists: (ptKey, string, unsigned long, float) or (string, unsigned long)"); + PYTHON_RETURN_INIT_ERROR; } - // some other args came in - PyErr_SetString(PyExc_TypeError, "__init__ expects one of two argument lists: (ptKey, string, unsigned long, float) or (string, unsigned long)"); - PYTHON_RETURN_INIT_ERROR; + + self->fThis->Init(key, name, pid, distSeq); + delete[] name; + PYTHON_RETURN_INIT_OK; } PYTHON_RICH_COMPARE_DEFINITION(ptPlayer, obj1, obj2, compareType) From a64b909f4f3240246cee97dc3e1f655c7259fe6f Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 28 Jan 2012 21:36:38 -0500 Subject: [PATCH 2/2] Now all the kids can play with ConvertString (and some others) --- .../Plasma/FeatureLib/pfPython/CMakeLists.txt | 1 + .../FeatureLib/pfPython/pyGlueHelpers.cpp | 63 +++++++++++++++++++ .../FeatureLib/pfPython/pyGlueHelpers.h | 6 ++ .../FeatureLib/pfPython/pyPlayerGlue.cpp | 21 +------ 4 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.cpp diff --git a/Sources/Plasma/FeatureLib/pfPython/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfPython/CMakeLists.txt index c005002c..b390708f 100644 --- a/Sources/Plasma/FeatureLib/pfPython/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfPython/CMakeLists.txt @@ -38,6 +38,7 @@ set(pfPython_SOURCES pyEnum.cpp pyGameScore.cpp pyGeometry3.cpp + pyGlueHelpers.cpp pyGrassShader.cpp pyGUIControl.cpp pyGUIControlButton.cpp diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.cpp b/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.cpp new file mode 100644 index 00000000..e6dbf4a9 --- /dev/null +++ b/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.cpp @@ -0,0 +1,63 @@ +/*==LICENSE==* + +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ + +#include "HeadSpin.h" +#include "pyGlueHelpers.h" + +char* PyString_AsStringEx(PyObject* obj) +{ + if (PyString_Check(obj)) + return hsStrcpy(PyString_AsString(obj)); + else if (PyUnicode_Check(obj)) + { + PyObject* utf8 = PyUnicode_AsUTF8String(obj); + char* buf = hsStrcpy(PyString_AsString(utf8)); + Py_DECREF(utf8); + return buf; + } else + return NULL; // You suck. +} + +bool PyString_CheckEx(PyObject* obj) +{ + return (PyString_Check(obj) || PyUnicode_Check(obj)); +} diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.h b/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.h index 1184c1ce..26cf4d5f 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyGlueHelpers.h @@ -42,6 +42,12 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #ifndef _pyGlueHelpers_h_ #define _pyGlueHelpers_h_ +#include + +// Useful string functions +char* PyString_AsStringEx(PyObject*); +inline bool PyString_CheckEx(PyObject*); + // A set of macros to take at least some of the tediousness out of creating straight python glue code ///////////////////////////////////////////////////////////////////// diff --git a/Sources/Plasma/FeatureLib/pfPython/pyPlayerGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyPlayerGlue.cpp index e64ee87f..f2dd94bd 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyPlayerGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyPlayerGlue.cpp @@ -49,23 +49,6 @@ PYTHON_CLASS_DEFINITION(ptPlayer, pyPlayer); PYTHON_DEFAULT_NEW_DEFINITION(ptPlayer, pyPlayer) PYTHON_DEFAULT_DEALLOC_DEFINITION(ptPlayer) -static char* ConvertString(PyObject* obj) -{ - if (PyString_Check(obj)) - { - return hsStrcpy(PyString_AsString(obj)); - } else if (PyUnicode_Check(obj)) { - size_t size = PyUnicode_GetSize(obj); - wchar_t* temp = new wchar_t[size + 1]; - PyUnicode_AsWideChar((PyUnicodeObject*)obj, temp, size); - temp[size] = 0; - char* buf = hsWStringToString(temp); - delete[] temp; - return buf; - } else - return NULL; // You suck. -} - PYTHON_INIT_DEFINITION(ptPlayer, args, keywords) { // we have two sets of arguments we can use, hence the generic PyObject* pointers @@ -89,7 +72,7 @@ PYTHON_INIT_DEFINITION(ptPlayer, args, keywords) if (pyKey::Check(firstObj)) { key = pyKey::ConvertFrom(firstObj); - if (!(name = ConvertString(secondObj))) + if (!(name = PyString_AsStringEx(secondObj))) { PyErr_SetString(PyExc_TypeError, "__init__ expects one of two argument lists: (ptKey, string, unsigned long, float) or (string, unsigned long)"); PYTHON_RETURN_INIT_ERROR; @@ -103,7 +86,7 @@ PYTHON_INIT_DEFINITION(ptPlayer, args, keywords) pid = PyLong_AsUnsignedLong(thirdObj); distSeq = (float)PyFloat_AsDouble(fourthObj); - } else if (name = ConvertString(firstObj)){ + } else if (name = PyString_AsStringEx(firstObj)){ if (!PyLong_Check(secondObj) || thirdObj || fourthObj) { delete[] name;