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
_______________________________________________
cython-devel mailing list
cython-devel@python.org
https://mail.python.org/mailman/listinfo/cython-devel

Reply via email to