Skip to content

Commit

Permalink
UPBGE: Implement python fast keyword parsing.
Browse files Browse the repository at this point in the history
The usage of undocumented python function _PyArg_ParseTupleAndKeywordsFast
(already used in blender) helps to improve performance spend during
function argument parsing. After some test this new function is 2/3 of
the runnign time of the previous parsing function.

But this function has a drawback: it request more code and variable to be
used especially a python parser pre created. To avoid to write this code
each time the template function EXP_ParseTupleArgsAndKeywords is used.
This function receive the args and kwds tuples, the format, the keywords
name and pointers converted values.
  • Loading branch information
panzergame committed Nov 13, 2017
1 parent 5577969 commit 3f9e0b5
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 36 deletions.
8 changes: 8 additions & 0 deletions source/gameengine/Expressions/EXP_PyObjectPlus.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#include "EXP_Python.h"
#include <string>
#include <initializer_list>
#include "MT_Vector3.h"
#include <stddef.h>

Expand Down Expand Up @@ -516,6 +517,13 @@ typedef struct EXP_PYATTRIBUTE_DEF {
#define EXP_PYATTRIBUTE_ARRAY_RO_FUNCTION(name, object, length, getfunction) \
{ name, EXP_PYATTRIBUTE_TYPE_FUNCTION, EXP_PYATTRIBUTE_RO, 0, 0, 0.f, 0, f, false, false, 0, 0, length, nullptr, nullptr, &object::getfunction, {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr} }

template <class ... Args>
inline bool EXP_ParseTupleArgsAndKeywords(PyObject *pyargs, PyObject *pykwds, const char *format, std::initializer_list<const char *> keyword, Args ... args)
{
BLI_assert((keyword.size() - 1) == (sizeof...Args));
static _PyArg_Parser _parser = {format, keyword.begin(), 0};
return _PyArg_ParseTupleAndKeywordsFast(pyargs, pykwds, &_parser, args ...);
}

/*------------------------------
* EXP_PyObjectPlus
Expand Down
8 changes: 4 additions & 4 deletions source/gameengine/Ketsji/KX_2DFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,10 @@ EXP_PYMETHODDEF_DOC(KX_2DFilter, addOffScreen, " addOffScreen(slots, depth, widt
int mipmap = 0;
int flag = 0;

static const char *kwlist[] = {"slots", "depth", "width", "height", "hdr", "mipmap", nullptr};

if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiii:addOffScreen", const_cast<char**>(kwlist),
&slots, &depth, &width, &height, &hdr, &mipmap)) {
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "i|iiiii:addOffScreen",
{"slots", "depth", "width", "height", "hdr", "mipmap", 0},
&slots, &depth, &width, &height, &hdr, &mipmap))
{
return nullptr;
}

Expand Down
42 changes: 22 additions & 20 deletions source/gameengine/Ketsji/KX_GameObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2003,9 +2003,8 @@ PyObject *KX_GameObject::PyReplaceMesh(PyObject *args, PyObject *kwds)
int use_gfx= 1, use_phys= 0;
RAS_MeshObject *new_mesh;

static const char *kwlist[] = {"mesh", "useDisplayMesh", "usePhysicsMesh", nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii:replaceMesh", const_cast<char**>(kwlist),
&value, &use_gfx, &use_phys))
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "O|ii:replaceMesh",
{"mesh", "useDisplayMesh", "usePhysicsMesh", 0}, &value, &use_gfx, &use_phys))
{
return nullptr;
}
Expand Down Expand Up @@ -2034,8 +2033,8 @@ PyObject *KX_GameObject::PyReinstancePhysicsMesh(PyObject *args, PyObject *kwds)
PyObject *gameobj_py= nullptr;
PyObject *mesh_py= nullptr;

static const char *kwlist[] = {"gameObject", "meshObject", "dupli", nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:reinstancePhysicsMesh", const_cast<char**>(kwlist), &gameobj_py, &mesh_py, &dupli) ||
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "|OOi:reinstancePhysicsMesh",
{"gameObject", "meshObject", "dupli", 0}, &gameobj_py, &mesh_py, &dupli) ||
(gameobj_py && !ConvertPythonToGameObject(logicmgr, gameobj_py, &gameobj, true, "gameOb.reinstancePhysicsMesh(obj, mesh, dupli): KX_GameObject")) ||
(mesh_py && !ConvertPythonToMesh(logicmgr, mesh_py, &mesh, true, "gameOb.reinstancePhysicsMesh(obj, mesh, dupli): KX_GameObject")))
{
Expand Down Expand Up @@ -3587,8 +3586,9 @@ PyObject *KX_GameObject::PySetParent(PyObject *args, PyObject *kwds)
KX_GameObject *obj;
int addToCompound=1, ghost=1;

static const char *kwlist[] = {"parent", "compound", "ghost", nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii:setParent", const_cast<char**>(kwlist), &pyobj, &addToCompound, &ghost)) {
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "O|ii:setParent", {"parent", "compound", "ghost", 0},
&pyobj, &addToCompound, &ghost))
{
return nullptr; // Python sets a simple error
}
if (!ConvertPythonToGameObject(logicmgr, pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject"))
Expand Down Expand Up @@ -3695,8 +3695,9 @@ PyObject *KX_GameObject::PyAlignAxisToVect(PyObject *args, PyObject *kwds)
int axis = 2; //z axis is the default
float fac = 1.0f;

static const char *kwlist[] = {"vect", "axis", "factor", nullptr};
if (PyArg_ParseTupleAndKeywords(args, kwds, "O|if:alignAxisToVect", const_cast<char**>(kwlist), &pyvect, &axis, &fac)) {
if (EXP_ParseTupleArgsAndKeywords(args, kwds, "O|if:alignAxisToVect", {"vect", "axis", "factor", 0},
&pyvect, &axis, &fac))
{
MT_Vector3 vect;
if (PyVecTo(pyvect, vect)) {
if (fac > 0.0f) {
Expand Down Expand Up @@ -3887,8 +3888,9 @@ EXP_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
const char *propName = "";
SCA_LogicManager *logicmgr = GetScene()->GetLogicManager();

static const char *kwlist[] = {"other", "dist", "prop", nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|fs:rayCastTo", const_cast<char**>(kwlist), &pyarg, &dist, &propName)) {
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "O|fs:rayCastTo", {"other", "dist", "prop", 0},
&pyarg, &dist, &propName))
{
return nullptr; // python sets simple error
}

Expand Down Expand Up @@ -4005,9 +4007,9 @@ EXP_PYMETHODDEF_DOC(KX_GameObject, rayCast,
int mask = (1 << OB_MAX_COL_MASKS) - 1;
SCA_LogicManager *logicmgr = GetScene()->GetLogicManager();

static const char *kwlist[] = {"objto", "objfrom", "dist", "prop", "face", "xray", "poly", "mask", nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Ofsiiii:rayCast", const_cast<char**>(kwlist), &pyto, &pyfrom,
&dist, &propName, &face, &xray, &poly, &mask))
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "O|Ofsiiii:rayCast",
{"objto", "objfrom", "dist", "prop", "face", "xray", "poly", "mask", 0},
&pyto, &pyfrom, &dist, &propName, &face, &xray, &poly, &mask))
{
return nullptr; // Python sets a simple error
}
Expand Down Expand Up @@ -4129,8 +4131,9 @@ EXP_PYMETHODDEF_DOC(KX_GameObject, sendMessage,
char* body = (char *)"";
char* to = (char *)"";

static const char *kwlist[] = {"subject", "body", "to", nullptr};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ss:sendMessage", const_cast<char**>(kwlist), &subject, &body, &to)) {
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "s|ss:sendMessage", {"subject", "body", "to", 0},
&subject, &body, &to))
{
return nullptr;
}

Expand Down Expand Up @@ -4159,10 +4162,9 @@ EXP_PYMETHODDEF_DOC(KX_GameObject, playAction,
short play_mode=0;
short blend_mode=0;

static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", "blend_mode", nullptr};

if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhfh:playAction", const_cast<char**>(kwlist),
&name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed, &blend_mode))
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "sff|hhfhfhfh:playAction", {"name", "start_frame", "end_frame", "layer",
"priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", "blend_mode", 0},
&name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed, &blend_mode))
{
return nullptr;
}
Expand Down
9 changes: 3 additions & 6 deletions source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,12 +505,9 @@ static PyObject *gPyCreateConstraint(PyObject *self,
int flag = 0;
float pivotX = 0.0f, pivotY = 0.0f, pivotZ = 0.0f, axisX = 0.0f, axisY = 0.0f, axisZ = 0.0f;

static const char *kwlist[] = {"physicsid_1", "physicsid_2", "constraint_type", "pivot_x", "pivot_y", "pivot_z",
"axis_x", "axis_y", "axis_z", "flag", nullptr};

if (!PyArg_ParseTupleAndKeywords(args, kwds, "KKi|ffffffi:createConstraint", (char **)kwlist,
&physicsid, &physicsid2, &constrainttype,
&pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag))
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "KKi|ffffffi:createConstraint", {"physicsid_1", "physicsid_2",
"constraint_type", "pivot_x", "pivot_y", "pivot_z", "axis_x", "axis_y", "axis_z", "flag", 0},
&physicsid, &physicsid2, &constrainttype, &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag))
{
return nullptr;
}
Expand Down
9 changes: 5 additions & 4 deletions source/gameengine/Ketsji/KX_PythonInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,11 +628,12 @@ static PyObject *gLibLoad(PyObject *, PyObject *args, PyObject *kwds)
short options=0;
int load_actions=0, verbose=0, load_scripts=1, async=0;

static const char *kwlist[] = {"path", "group", "buffer", "load_actions", "verbose", "load_scripts", "async", "scene", nullptr};

if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|y*iiIiO:LibLoad", const_cast<char**>(kwlist),
&path, &group, &py_buffer, &load_actions, &verbose, &load_scripts, &async, &pyscene))
if (!EXP_ParseTupleArgsAndKeywords(args, kwds, "ss|y*iiIiO:LibLoad",
{"path", "group", "buffer", "load_actions", "verbose", "load_scripts", "async", "scene", 0},
&path, &group, &py_buffer, &load_actions, &verbose, &load_scripts, &async, &pyscene))
{
return nullptr;
}

if (!ConvertPythonToScene(pyscene, &kx_scene, true, "invalid scene")) {
return nullptr;
Expand Down
1 change: 0 additions & 1 deletion source/gameengine/Ketsji/KX_Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1829,7 +1829,6 @@ PyMethodDef KX_Scene::Methods[] = {
EXP_PYMETHODTABLE(KX_Scene, suspend),
EXP_PYMETHODTABLE(KX_Scene, resume),
EXP_PYMETHODTABLE(KX_Scene, drawObstacleSimulation),


/* dict style access */
EXP_PYMETHODTABLE(KX_Scene, get),
Expand Down
1 change: 0 additions & 1 deletion source/gameengine/Ketsji/KX_Scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,6 @@ class KX_Scene : public EXP_Value, public SCA_IScene
EXP_PYMETHOD_DOC(KX_Scene, get);
EXP_PYMETHOD_DOC(KX_Scene, drawObstacleSimulation);


/* attributes */
static PyObject* pyattr_get_name(EXP_PyObjectPlus *self_v, const EXP_PYATTRIBUTE_DEF *attrdef);
static PyObject* pyattr_get_objects(EXP_PyObjectPlus *self_v, const EXP_PYATTRIBUTE_DEF *attrdef);
Expand Down

0 comments on commit 3f9e0b5

Please sign in to comment.