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.
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);
}
}
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()
>>s = StringWrapper(" S")
>>s.get()
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);
}
}
Comment