Python C API: Enabling PyObject Type

I have code for the Python interface in C ++ that works fine, but every time I look at it, I think there should be a better way to do this. On the C ++ side, there is a type β€œvariant”, which can deal with a fixed range of basic types - int, real, string, vector variants, etc. I have some code that uses the Python API to convert from equivalent Python types. It looks something like this:

variant makeVariant(PyObject* value) { if (PyString_Check(value)) { return PyString_AsString(value); } else if (value == Py_None) { return variant(); } else if (PyBool_Check(value)) { return value == Py_True; } else if (PyInt_Check(value)) { return PyInt_AsLong(value); } else if (PyFloat_Check(value)) { return PyFloat_AsDouble(value); } // ... etc 

The problem is chained if-else ifs. It seems to be called for a switch statement or a table or map of creation functions that is associated with a type identifier. In other words, I want to write something like:

  return createFunMap[typeID(value)](value); 

Based on viewing the API docs, it was not obvious that the best way to get the β€œtypeID” here is. I see that I can do something like this:

  PyTypeObject* type = value->ob_type; 

This seems to quickly change type information, but what is the cleanest way to use this to communicate with a limited set of types that interest me?

+7
c python python-c-extension python-c-api
source share
1 answer

In a way, I think you answered your question.

Somewhere you will have to choose data-based functionality. The way to do this in C is to use function pointers.

Create an object_type-> map of functions mappers ... where each function has a well-defined interface.

 variant PyBoolToVariant(PyObject *value) { return value == Py_True; } Map<PyTypeObject*,variant* (PyObject*)> function_map; function_map.add(PyBool, PyBoolToVariant); 

Your makeVariant may now look like this.

 variant makeVariant(PyObject *value) { return (*function_map.get(value->ob_type))(value); } 

The hard part will get the syntax for the Map object. In addition, I assume that there is a Map object that you can use that takes parameters of the type ( <PyTypeObject*, variant*(PyObject*) ).

I probably did not quite understand the syntax for the second type of Map. It should be a pointer to a function that takes a single pointer and returns a pointer to a variant.

I hope this will be helpful.

+3
source share

All Articles