C/API Clarification

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jeremy Moles

    #1

    C/API Clarification

    First of all, let me say I really do appreciate--and frequently use--the
    ample and easy to read Python documentation. However, there are a few
    things I'm still unclear on, even after asking multiple questions here
    on the list (thanks everyone!) and reading the "Extending" and
    "Reference" docs from start to finish. I'm new to Python extension
    writing--but I'm learning fast. Still, I have a few questions that would
    make my weekend so much better if I had some guidance on them or,
    better, examples of other people's working code. :) (Real code, not
    over-simplified examples that don't ever make sense in the real
    world) :)

    Most of my woes are the result of trying to wrap some highly dynamic C++
    code. People, of course, are quick to say "use Boost"--which I'm sure is
    great--but doesn't actually teach me anything about Python. :)

    1. Nowhere in the docs was I able to see an example of a custom object
    using anything but a METH_NOARGS method. This is pretty silly since I
    would assume that most class methods take a few arguments. I'm using:

    PyObject* foo(cstruct* self, PyObject* args, PyObject* kargs)

    ....and it works, but I'm not even really sure if this is right or where
    in the world I got the idea from! According to the docs, METH_VARARGS is
    (PyObject*, PyObject*)? My prototype shouldn't even compile... but it
    does, even at -Wall. This is an area I really feel like the docs should
    elaborate on. All of the tp_* functions are infinitely easier to
    implement as they have very specific purposes. However, very little
    attention is given to just general type methods, though it could be just
    me missing something. :)

    2. No where in the docs does it show how to "correctly" create an
    instance of your custom PyTypeObject in C (rather than in the
    interpreter). I'm using:

    PyObject* newobject = _PyObject_New(& PyType_myType);
    PyObject* nulltuple = Py_BuildValue(" ()");
    myType_init((cs truct*)(newobje ct), nulltuple, NULL);

    ....and it works (or appears to so far), but I really doubt this is how
    it's done. I'm guessing I'm not supposed to go anywhere near the
    _PyObject_New function. :)

    3. I'm not able to return the "self" argument (useful, for instance,
    when you want to chain a group of method calls) without screwing things
    up really, really bad. For example:

    PyObject* somefunc(cstruc t* self, PyObject* args, PyObject* kargs) {
    self->pointerToDat a->doSomeStuff( );

    return (PyObject*)(sel f);
    }

    ....returns "something" ; it has the methods you would expect, but trying
    to use the object when it gets back to the interpreter is pretty much
    undefined behavior. :) It's seen as a "<refcnt... >" instance in the
    interpreter, even though a dir() shows it still has the methods you
    would expect.

    I'm sorry if I come off as a newb or sound preachy--it certainly isn't
    my intention. I love Python and will continue using it even if I never
    quite grok it's C API. :)

    Weeeeeeeeeee.

  • Sam

    #2
    Re: C/API Clarification

    Jeremy Moles writes:
    [color=blue]
    > in the world I got the idea from! According to the docs, METH_VARARGS is
    > (PyObject*, PyObject*)?[/color]

    Right.
    [color=blue]
    > My prototype shouldn't even compile... but it[/color]

    Why wouldn't it compile?
    [color=blue]
    > 2. No where in the docs does it show how to "correctly" create an
    > instance of your custom PyTypeObject in C (rather than in the
    > interpreter). I'm using:[/color]

    That's what tp_alloc is for. Then you call tp_init to initialize it.

    But, your tp_new handler should already invoke tp_alloc, so it's cleaner to
    call tp_new, followed by tp_init.
    [color=blue]
    > 3. I'm not able to return the "self" argument (useful, for instance,
    > when you want to chain a group of method calls) without screwing things
    > up really, really bad. For example:
    >
    > PyObject* somefunc(cstruc t* self, PyObject* args, PyObject* kargs) {
    > self->pointerToDat a->doSomeStuff( );
    >
    > return (PyObject*)(sel f);
    > }
    >
    > ...returns "something" ; it has the methods you would expect, but trying
    > to use the object when it gets back to the interpreter is pretty much
    > undefined behavior. :) It's seen as a "<refcnt... >" instance in the
    > interpreter, even though a dir() shows it still has the methods you
    > would expect.[/color]

    You need to increment the reference count of the object, in this case.


    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.7 (GNU/Linux)

    iD8DBQBDRxfWx9p 3GYHlUOIRAnuVAJ 98wt1vRCfvFkzg9 BRQgdj1kFBsFACf SukC
    RXCoRc+BCD4D+H1 BYX+8tSg=
    =NQ7s
    -----END PGP SIGNATURE-----

    Comment

    Working...