C++ extension problem

pythoncurious at gmail.com pythoncurious at gmail.com
Mon Apr 16 12:38:46 EDT 2007


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(self._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('_example',
                    sources = ['_example.cc'])
setup (name = 'example',
       ext_modules = [module1])

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

class StringWrapper(object):
    def __init__(self, value):
        self._s = _example.new_string(value)
    def get(self): return _example.get(self._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];
} SillyStringObject;

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

    if (!PyArg_ParseTuple(args, "s", &value))
	return NULL;
    SillyStringObject *self = PyObject_NEW(SillyStringObject,
&SillyStringType);
    if (self != NULL) {
	strncpy(self->s, value, 20);
    }
    return (PyObject *)self;
}

PyObject *
get(PyTypeObject *type, PyObject *args)
{
    SillyStringObject *o;

    if (!PyArg_ParseTuple(args, "O!", SillyStringType, &o))
	return NULL;
    return (PyObject *)PyString_FromString(o->s);
}

PyMethodDef SillyStringMethods[] = {
     {"get", (PyCFunction)get, METH_VARARGS,
      ""
     },
     {"new_string", (PyCFunction)new_string, METH_VARARGS,
      ""
     },
    {NULL, NULL, 0, NULL}        /* Sentinel */
};

PyTypeObject SillyStringType = {
    PyObject_HEAD_INIT(NULL)
    0,				    /* ob_size */
    (char *)"SillyString",          /* tp_name */
    sizeof(SillyStringObject),	    /* 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_DEFAULT,	            /* tp_flags */
    "SillyString class."           /* tp_doc */
};

extern "C"
{
    PyMODINIT_FUNC
    init_example(void)
    {
	PyObject* m;
	SillyStringType.tp_new = PyType_GenericNew;
	if (PyType_Ready(&SillyStringType) < 0)
	    return;
	m = Py_InitModule3("_example", SillyStringMethods,
			   "_example module.");
	Py_INCREF(&SillyStringType);
	PyModule_AddObject(m, "SillyStringObject", (PyObject
*)&SillyStringType);
    }
}




More information about the Python-list mailing list