C++ extension problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • pythoncurious@gmail.com

    #1

    C++ extension problem

    Hi,

    I'm having a bit of trouble when writing a python extension. I can't
    seem to figure out what I did wrong.
    I tried to make a minimal example, but it's still quite a bit of
    code.
    It would be very appreciated if anyone could tell me what I've done
    wrong.

    First a short description of what I've done. The extension just wraps
    a string and the class in it will just hold the string data. A 'get'
    method is suppsed to just return the string value.
    There's a python part that will call C/C++ functions in the
    extension.
    I've tried using the same approach SWIG has, so the class in the
    extension doesn't really have any methods,
    it's all done in methods in the module.

    This is what it looks like when I try it out (also tried with
    different python version and compiler):
    % python
    Python 2.4.3 (#1, Aug 1 2006, 16:54:29)
    [GCC 3.4.6] on sunos5
    Type "help", "copyright" , "credits" or "license" for more information.
    >>from example import StringWrapper
    >>s = StringWrapper(" S")
    >>s.get()
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "example.py ", line 7, in get
    def get(self): return _example.get(se lf._s)
    TypeError: argument 1 must be SillyString, not SillyString

    Now this is what confuses me: Why does it say that I have the wrong
    type when it's the same type as it suggests?

    setup.py file:
    ###########
    from distutils.core import setup, Extension
    module1 = Extension('_exa mple',
    sources = ['_example.cc'])
    setup (name = 'example',
    ext_modules = [module1])

    example.py file:
    ############
    #!/usr/bin/env python
    import _example

    class StringWrapper(o bject):
    def __init__(self, value):
    self._s = _example.new_st ring(value)
    def get(self): return _example.get(se lf._s)


    and finally, the c/c++ file '_example.cc':
    (I need to use c++ compiler which means I couldn't use
    'staticforward'
    and the 'cstring is used instead of 'string.h' )
    ############### #########
    #include "Python.h"
    #include <cstring>

    // forward declaration
    extern PyTypeObject SillyStringType ;

    typedef struct {
    PyObject_HEAD
    char s[21];
    } SillyStringObje ct;

    PyObject *
    new_string(PyTy peObject *type, PyObject *args)
    {
    char *value = 0;

    if (!PyArg_ParseTu ple(args, "s", &value))
    return NULL;
    SillyStringObje ct *self = PyObject_NEW(Si llyStringObject ,
    &SillyStringTyp e);
    if (self != NULL) {
    strncpy(self->s, value, 20);
    }
    return (PyObject *)self;
    }

    PyObject *
    get(PyTypeObjec t *type, PyObject *args)
    {
    SillyStringObje ct *o;

    if (!PyArg_ParseTu ple(args, "O!", SillyStringType , &o))
    return NULL;
    return (PyObject *)PyString_From String(o->s);
    }

    PyMethodDef SillyStringMeth ods[] = {
    {"get", (PyCFunction)ge t, METH_VARARGS,
    ""
    },
    {"new_string ", (PyCFunction)ne w_string, METH_VARARGS,
    ""
    },
    {NULL, NULL, 0, NULL} /* Sentinel */
    };

    PyTypeObject SillyStringType = {
    PyObject_HEAD_I NIT(NULL)
    0, /* ob_size */
    (char *)"SillyString" , /* tp_name */
    sizeof(SillyStr ingObject), /* tp_basicsize */
    0, /* tp_itemsize */
    (destructor)0, /* tp_dealloc */
    (printfunc)0, /* tp_print */
    (getattrfunc)0, /* tp_getattr */
    (setattrfunc)0, /* tp_setattr */
    (cmpfunc)0, /* tp_compare */
    (reprfunc)0, /* tp_repr */
    0, /* tp_as_number */
    0, /* tp_as_sequence */
    0, /* tp_as_mapping */
    (hashfunc)0, /* tp_hash */
    (ternaryfunc)0, /* tp_call */
    (reprfunc)0, /* tp_str */
    0, /* tp_getattro */
    0, /* tp_setattro */
    0, /* tp_as_buffer */
    Py_TPFLAGS_DEFA ULT, /* tp_flags */
    "SillyStrin g class." /* tp_doc */
    };

    extern "C"
    {
    PyMODINIT_FUNC
    init_example(vo id)
    {
    PyObject* m;
    SillyStringType .tp_new = PyType_GenericN ew;
    if (PyType_Ready(& SillyStringType ) < 0)
    return;
    m = Py_InitModule3( "_example", SillyStringMeth ods,
    "_example module.");
    Py_INCREF(&Sill yStringType);
    PyModule_AddObj ect(m, "SillyStringObj ect", (PyObject
    *)&SillyStringT ype);
    }
    }

  • Michael Hoffman

    #2
    Re: C++ extension problem

    pythoncurious@g mail.com wrote:
    I'm having a bit of trouble when writing a python extension. I can't
    seem to figure out what I did wrong.
    I tried to make a minimal example, but it's still quite a bit of
    code.
    It would be very appreciated if anyone could tell me what I've done
    wrong.
    I can't answer your question since I have no experience writing
    extension types. I know this is at least partially a learning exercise
    for you, but might I suggest that your time might be better spent
    learning Boost.Python instead? It is "a C++ library which enables
    seamless interoperabilit y between C++ and the Python programming language."


    --
    Michael Hoffman

    Comment

    • =?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

      #3
      Re: C++ extension problem

      Now this is what confuses me: Why does it say that I have the wrong
      type when it's the same type as it suggests?
      When referring to the type, you must *always* form the address of the
      type structure, including, but not limited to, the line
      if (!PyArg_ParseTu ple(args, "O!", SillyStringType , &o))
      HTH,
      Martin

      Comment

      • pythoncurious@gmail.com

        #4
        Re: C++ extension problem

        On Apr 16, 9:31 pm, Michael Hoffman <cam.ac...@mh39 1.invalidwrote:
        I can't answer your question since I have no experience writingextensio ntypes. I know this is at least partially a learning exercise
        for you, but might I suggest that your time might be better spent
        learning Boost.Python instead? It is "aC++librar y which enables
        seamless interoperabilit y betweenC++and the Python programming language."
        >

        --
        Michael Hoffman
        Yes, that's good advice. Unfortunately, boost has not been working
        very well with the tools I'm forced to use (Sun studio). Otherwise I
        would have started there.

        /Matt

        Comment

        • pythoncurious@gmail.com

          #5
          Re: C++ extension problem

          On Apr 16, 11:44 pm, "Martin v. Löwis" <mar...@v.loewi s.dewrote:
          Now this is what confuses me: Why does it say that I have the wrong
          type when it's the same type as it suggests?
          >
          When referring to the type, you must *always* form the address of the
          type structure, including, but not limited to, the line
          >
          if (!PyArg_ParseTu ple(args, "O!", SillyStringType , &o))
          >
          HTH,
          Martin

          Yes, that did help. Thanks.
          I assumed that the compiler would warn me about that kind of problem,
          but I know better know. :)
          Still, the error message is somewhat confusing.





          Comment

          • =?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

            #6
            Re: C++ extension problem

            I assumed that the compiler would warn me about that kind of problem,
            but I know better know. :)
            It's a variable argument list (...). The compiler is not supposed to
            give any warnings for that (although I do have a gcc patch that enables
            warnings for PyArg_ParseTupl e).
            Still, the error message is somewhat confusing.
            Passing incorrect parameters to variable argument lists causes undefined
            behavior. Anything can happen under undefined behavior, including
            mysterious error messages, erasure of your hard disk, and reversal of
            the global warming.

            To understand why the specific error message is printed, you would have
            to debug what values are passed on the stack at what point.

            Regards,
            Martin

            Comment

            Working...