1

I've read the documentation and coded up my own example based on their Noddy example:

https://docs.python.org/3.4/extending/newtypes.html

This is a bit of a departure from usingPy_BuildValue()to build arbitrary objects dynamically. It appears that the underlying assumption is that there’s a C structure backing every object instance you want to create.

Is this really the only (best?) way to create new objects in Python? I was hoping to create a new object and declare members/types similar to how you would create tuples, lists, and dictionaries etc. It seems like it should be possible to declare a new type, declare members and their types, and then plug values in field-by-field w/o all this.

I can't even use the structure defined by the existing API of what I'm gluing because Python objects require the compulsoryPyObject_HEADfield. I have to define a new C structure, copy the relevant elements that were handed back to me from the API call. It just seems like a level of memory management on the C side that should be unnecessary.

jsbueno
  • 99,910
  • 10
  • 151
  • 209
  • 1
    Why not put a pointer in the type and point to the existing structure? – Ignacio Vazquez-Abrams Mar 26 '15 at 18:40
  • Yes, I like this idea! That eliminates any copying, but how do you define the proper offsets into a struct to get the members? `PyMemberDef` requires an`offset`to work properly. This is what sort of confused me about complicated (nested) structures. I wouldn't know how to communicate this field in that case unless I defined my own flat structure. – Clint Olsen Mar 26 '15 at 19:50
  • Define [`tp_getattr` and `tp_setattr`](https://docs.python.org/3.4/extending/newtypes.html#attribute-management) on the type. – Ignacio Vazquez-Abrams Mar 26 '15 at 20:34

2 Answers2

0

Sure, there's another way to create types in Python. Perhaps you've seen it?

class Foo():
    def __init__(self):
        ....

I'm being a little glib, of course. But when exposing a C interface to Python, it's often a good idea to have a Python script doing much of the interfacing; after all, it's quicker to write Python code than CPython binding code. And if what you have is basically an opaque handle type and a set of C functions which create/operate on those handles, you can simply expose those functions as free functions, and use them from your Python-side binding code. (You might even be able to do it without writing a single line of CPython binding code, using ctypes.)

Uyghur Lives Matter
  • 18,820
  • 42
  • 108
  • 144
Sneftel
  • 40,271
  • 12
  • 71
  • 104
  • So, what you're suggesting is creating the scaffolding of the class structure in Python and then use the extensions interface to set the fields via an init() of some kind? – Clint Olsen Mar 26 '15 at 19:47
  • @ClintOlsen Well, `__init__()` or `paintMode` or `engageSpatula()`, depending on your particular needs. Also read about the `@property` decorator (transparent getters/setters). But yeah, IME that's an efficient way to bind to a native library which doesn't have a ton of exposed types. – Sneftel Mar 26 '15 at 19:56
-1

So, rather than creating a new type, I was reading up on manipulating tuples in piecewise fashion and there's a section onstruct sequences. This is sort of what I was originally envisioning:

https://docs.python.org/3.4/c-api/tuple.html

It doesn't have all the power that a new type provides, but for communicating struct-like objects back to the caller with named attributes, this seems like a pretty easy way to go.

I'm curious what you folks think about this...