[Cython] bug: constructor declarations not working

Robert Bradshaw robertwb at gmail.com
Sun Aug 17 07:12:08 CEST 2014


On Sat, Aug 16, 2014 at 9:07 PM, Marcus Brinkmann
<marcus.brinkmann at ruhr-uni-bochum.de> wrote:
> Hi,
>
> ok, this is not as easy as I originally thought.  I fixed a couple of things
> that prevented the suggested syntax from working, but the linking stage has
> additional challenges, as there is currently no support for cimporting a
> native cppclass from one module to another (akin to the "api" feature or the
> "public" symbol import function feature).  It's also not sure how this
> should work exactly, so I am giving up.
>
> I settled on a work around using "cdef public" C functions and making use of
> cimport and the automatic symbol import feature.  This does not give access
> to the full type, but it's sufficient for my use case.
>
> The following two changes were somewhat useful in my explorations:
>
> 1. Fix the "this" pointer misreference.  This is an actual bug, so I made a
> pull request:
>
> https://github.com/cython/cython/pull/316
>
> 2. The missing constructor declaration generated when cimporting the pxd
> file is easy to fix by not testing for "defining or name != "<init>") in
> CppClassScope.  However, this breaks a test case, because
> NewExprNode.inferType adds the implicit default constructor under the name
> "<init>" without a proper cname.  So I made a larger change that fixes this,
> too:
>
> https://github.com/lambdafu/cython/tree/lambdafu/cpp_declare_constructor
>
> I didn't make a pull request, because currently cimport'ing an external
> cppclass declaration is not useful without some way to add the runtime
> dependency as well...
>
> Thanks and sorry for the noise.  It wasn't entirely clear to me what the
> state of cppclass support in Cython is until I read the source code.

Thanks.

As you observed, defining C++ classes in Cython is still somewhat of a
beta feature.

> On 08/12/2014 04:57 AM, Marcus Brinkmann wrote:
>>
>> 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 at python.org
>> https://mail.python.org/mailman/listinfo/cython-devel
>
>
> _______________________________________________
> cython-devel mailing list
> cython-devel at python.org
> https://mail.python.org/mailman/listinfo/cython-devel


More information about the cython-devel mailing list