Marcus Brinkmann
2014-08-12 02:57:00 UTC
Hi,
I want to declare and define C++ classes from Cython. Sure, I could
write them in native C++, but it's just small glue code, and I prefer to
let Cython handle the GIL and all the other good stuff.
First, for reference, the following works (c.f.
tests/run/cpp_classes_def.pyx):
== cython --cplus example1.pyx ============
cdef cppclass Foo "Foo":
int _foo
__init__(int foo) nogil:
this._foo = foo
__dealloc__() nogil:
pass
===========================================
This will emit a declaration for Foo and the implementations of the
constructor and destructor (output is truncated to show relevant parts
only):
struct Foo {
int _foo;
Foo(int);
virtual ~Foo(void);
};
Foo::Foo(int __pyx_v_foo) {
this->_foo = __pyx_v_foo;
}
Foo::~Foo(void) {
}
Now, I want to export the class to other cython files. The following
does not work, and I think it's a bug:
== example2.pxd ===========================
cdef extern cppclass Foo:
int _foo
__init__(int foo)
__dealloc__()
===========================================
== cython --cplus example2.pyx ============
cdef cppclass Foo:
__init__(int foo) nogil:
this._foo = foo
__dealloc__() nogil:
pass
===========================================
== cython --cplus example3.pyx ============
from example2 cimport Foo
cdef Foo* foo_p = new Foo(2)
===========================================
This fails for example2 with an obscure error message:
$ cython --cplus example2.pyx
example2.pyx:3:8: undeclared name not builtin: this
...more spurious errors...
For example3, Cython runs through but trying to compile shows the actual
problem (which you can also see in example2 if you shift things around a
bit):
$ g++ -fPIC -shared -o example3.so -I /usr/include/python2.7 example3.cpp
example3.cpp: In function ‘void initexample3()’:
example3.cpp:775:38: error: no matching function for call to ‘Foo::Foo(int)’
__pyx_v_8example3_foo_p = new Foo(2);
This is in the generated code:
/*--- Type declarations ---*/
struct Foo;
struct Foo {
int _foo;
virtual ~Foo(void);
};
It's missing the constructor declaration!
I traced this a bit down the Compiler/Symtab.py and found this part in
CppClassScope::declare_var:
4e07fc52 (Robert Bradshaw 2012-08-21 00:46:00 -0700 2112)
if name != "this" and (defining or name != "<init>"):
4e07fc52 (Robert Bradshaw 2012-08-21 00:46:00 -0700 2113)
self.var_entries.append(entry)
Here defining is 0, so the declaration is skipped. I don't know Cython
internals, so I am hoping someone who does can fix this easily given the
above information or point me in the right direction.
Thanks a lot for Cython, it's very useful!
Marcus Brinkmann
I want to declare and define C++ classes from Cython. Sure, I could
write them in native C++, but it's just small glue code, and I prefer to
let Cython handle the GIL and all the other good stuff.
First, for reference, the following works (c.f.
tests/run/cpp_classes_def.pyx):
== cython --cplus example1.pyx ============
cdef cppclass Foo "Foo":
int _foo
__init__(int foo) nogil:
this._foo = foo
__dealloc__() nogil:
pass
===========================================
This will emit a declaration for Foo and the implementations of the
constructor and destructor (output is truncated to show relevant parts
only):
struct Foo {
int _foo;
Foo(int);
virtual ~Foo(void);
};
Foo::Foo(int __pyx_v_foo) {
this->_foo = __pyx_v_foo;
}
Foo::~Foo(void) {
}
Now, I want to export the class to other cython files. The following
does not work, and I think it's a bug:
== example2.pxd ===========================
cdef extern cppclass Foo:
int _foo
__init__(int foo)
__dealloc__()
===========================================
== cython --cplus example2.pyx ============
cdef cppclass Foo:
__init__(int foo) nogil:
this._foo = foo
__dealloc__() nogil:
pass
===========================================
== cython --cplus example3.pyx ============
from example2 cimport Foo
cdef Foo* foo_p = new Foo(2)
===========================================
This fails for example2 with an obscure error message:
$ cython --cplus example2.pyx
example2.pyx:3:8: undeclared name not builtin: this
...more spurious errors...
For example3, Cython runs through but trying to compile shows the actual
problem (which you can also see in example2 if you shift things around a
bit):
$ g++ -fPIC -shared -o example3.so -I /usr/include/python2.7 example3.cpp
example3.cpp: In function ‘void initexample3()’:
example3.cpp:775:38: error: no matching function for call to ‘Foo::Foo(int)’
__pyx_v_8example3_foo_p = new Foo(2);
This is in the generated code:
/*--- Type declarations ---*/
struct Foo;
struct Foo {
int _foo;
virtual ~Foo(void);
};
It's missing the constructor declaration!
I traced this a bit down the Compiler/Symtab.py and found this part in
CppClassScope::declare_var:
4e07fc52 (Robert Bradshaw 2012-08-21 00:46:00 -0700 2112)
if name != "this" and (defining or name != "<init>"):
4e07fc52 (Robert Bradshaw 2012-08-21 00:46:00 -0700 2113)
self.var_entries.append(entry)
Here defining is 0, so the declaration is skipped. I don't know Cython
internals, so I am hoping someone who does can fix this easily given the
above information or point me in the right direction.
Thanks a lot for Cython, it's very useful!
Marcus Brinkmann