On 25/09/2007, Stefan Behnel python_capi@behnel.de wrote:
Gustavo Carneiro wrote:
On 25/09/2007, *Stefan Behnel*
mailto:python_capi@behnel.de> wrote: I don't understand what "exact API mapping" means.
What I meant was: is the C(++) API mapped directly to Python or can you write abstraction code in between?
Generally it requires a direct mapping. Why would you want to write code in the middle? Although recently I added support for adding "user functions" to make them appear as methods of objects.
Anyway that's not the point. The PyBindGen design is not set in stone...
But yes, so far you have to write all this by hand. Although would love
to have automatic header file scanning, one day... unfortunately I have not had enough time for that, and would rather focus on the code generation for now. Lots of neat things could be done later on top of the pybindgen python module interface...
But that's what most wrapper generators are there for: move the work from the developer into a generator. If you have to write code for every function/method/class you wrap, I think you're better of with Pyrex/Cython, as Pyrex code is readable and meaningful Python, not just a wrapper writer script.
Come on, I wouldn't say this interface is unreadable. It's stuff like this:
mod = Module('foo')
Foo = CppClass('Foo', automatic_type_narrowing=True)
mod.add_class(Foo)
Foo.add_static_attribute(ReturnValue.new('int'), 'instance_count')
Foo.add_constructor(
CppConstructor([Parameter.new('std::string', 'datum')]))
Foo.add_constructor(CppConstructor([]))
Foo.add_method(CppMethod(ReturnValue.new('std::string'), 'get_datum',
[]))
Not that hard to write this, is it?
I don't like having to learn a new language for this. Just like
Boost.Python users are comfortable with C++ and avoid having to learn a new language, PyBindGen users are comfortable with Python and don't have to learn a new language.
Pyrex is *almost* Python, no new language to learn. And Cython is even closer, as it features a couple of Python 2.5 and Python 3k features.
Besides, pyrex/cython C++ support is poor or nonexistent. Although I acknowledge that if you wrap pure C libraries then this point is moot.
There are a couple of patches that improve the support. Admittedly, Pyrex does not target C++ libraries, so OO support is mostly missing. But nothing keeps you from implementing an object interface against C++ classes. I bet the Cython project would be happy to include it.
Finally, have you ever looked at the code generated by pyrex?
Yes, definitely, it's pretty readable, well optimised (with Cython, that is) and straight forward (ok, loops are ugly and over-optimised - but *very* fast). And I totally like the Cython feature of keeping the surrounding Cython code inside a C comment. That way, you immediately know what you are looking at.
For instance, I don't find this very readable:
static PyObject *__pyx_f_4spam_4Spam_get_amount(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static PyObject *__pyx_f_4spam_4Spam_get_amount(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { PyObject *__pyx_r; PyObject *__pyx_1 = 0; static char *__pyx_argnames[] = {0}; if (unlikely(!PyArg_ParseTupleAndKeywords(__pyx_args, __pyx_kwds, "", __pyx_argnames))) return 0; Py_INCREF(__pyx_v_self);
/* "/Users/robert/sage/pyrex/cython-0.9.6.3/Demos/spam.pyx":16 *
- def get_amount(self):
return self.amount # <<<<<<<<<<<<<<
- def set_amount(self, new_amount): */ __pyx_1 = PyInt_FromLong(((struct __pyx_obj_4spam_Spam *)__pyx_v_self)->amount); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; goto __pyx_L1;} __pyx_r = __pyx_1; __pyx_1 = 0; goto __pyx_L0;
__pyx_r = Py_None; Py_INCREF(Py_None); goto __pyx_L0; __pyx_L1:; Py_XDECREF(__pyx_1); __Pyx_AddTraceback("spam.Spam.get_amount"); __pyx_r = 0; __pyx_L0:; Py_DECREF(__pyx_v_self); return __pyx_r; }
Compared with this code generated by pybindgen:
static PyObject * _wrap_fooinvoke_some_object_get_prefix() { PyObject *py_retval; std::string retval;
retval = invoke_some_object_get_prefix();
py_retval = Py_BuildValue("s#", retval.c_str(), retval.size());
return py_retval;
}
Pybindgen generated code is almost as clean as the code you would write by hand. To me that counts a lot. I know some people don't care what happens underneath the tools they use as long as it works. I am not that kind of person.
-- Gustavo J. A. M. Carneiro INESC Porto, Telecommunications and Multimedia Unit "The universe is always one step beyond logic." -- Frank Herbert