2016-12-12 5 views
0

Я хотел бы создать оболочку для класса cpp с Cython. Но этот класс агрегирует другой, и я не знаю, нужно ли мне также создавать оболочку для этого класса, поскольку я не хочу вызывать этот второй класс из Python.cython - wrap a cpp class aggregating other

Есть СРР классы:

testclass.hpp

#ifndef TESTCLASS_H 
#define TESTCLASS_H 
#include "ocean.hpp" 

class TestClass { 
    private: 
     Ocean _ocean; 

    public: 
     int x, y; 
     TestClass(); 
     ~TestClass(); 
     int Multiply(int a, int b); 
}; 
#endif 

testclass.cpp

#include "testclass.hpp" 
TestClass::TestClass() 
{ 
    x = 5; 
    y = 1; 
    _ocean = Ocean(); 
} 

TestClass::~TestClass() 
{ 
    std::cout << "Calling destructor" << std::endl; 
} 

int TestClass::Multiply(int a, int b) 
{ 
    return a*b; 
} 

ocean.hpp

#ifndef OCEAN_H 
#define OCEAN_H 
class Ocean { 
    public: 
     double _depth; 
     double _rho; 

     Ocean(); 
     virtual ~Ocean(); 
     void setwaterdepth(double d); 
}; 
#endif 

Я хотел бы, чтобы обернуть только тестовый класс, T его то, что я пробовал:

ocean.pxd

cdef extern from "ocean.hpp": 
cdef cppclass Ocean: 
    Ocean() 

test.pyx

from ocean cimport Ocean 

cdef extern from "testclass.hpp": 
    cdef cppclass TestClass: 
     TestClass() 
     int x 
     int y 
     int Multiply(int a, int b) 

cdef class pyTestClass: 
    cdef TestClass* thisptr # hold a C++ instance 

    def __cinit__(self): 
     self.thisptr = new TestClass() 

    def __dealloc__(self): 
     del self.thisptr 

    def Multiply(self, a, b): 
     return self.thisptr.Multiply(a, b) 

setup.py

from distutils.core import setup, Extension 
from Cython.Build import cythonize 

ext = Extension("test", 
       sources=["test.pyx", "testclass.cpp"], 
       language="c++") 

setup(name="test", 
     ext_modules=cythonize(ext)) 

Q1) Является ли правильный способ сделать это ? (Когда я компилирую это я получаю следующее сообщение об ошибке, и я не понимаю эту ошибку.)

C:\MinGW\bin\gcc.exe -mdll -O -Wall -IC:\Python27\include -IC:\Python27\PC -c testclass.cpp -o build\temp.win32-2.7\Release\testclass.o 
writing build\temp.win32-2.7\Release\test.def 
C:\MinGW\bin\g++.exe -shared -s build\temp.win32-2.7\Release\test.o build\temp.win32-2.7\Release\testclass.o build\temp.win32-2.7\Release\test.def -LC:\Python27\libs -LC:\Python27\PCbuild -LC:\Python27\PC\VS9.0 -lpython27 -lmsv 
cr90 -o E:\00-Projets\InWave\Couplage\PYW\C++\test3\test.pyd 
build\temp.win32-2.7\Release\testclass.o:testclass.cpp:(.text+0x97): undefined reference to `Ocean::~Ocean()' 
build\temp.win32-2.7\Release\testclass.o:testclass.cpp:(.text+0xa3): undefined reference to `Ocean::~Ocean()' 
build\temp.win32-2.7\Release\testclass.o:testclass.cpp:(.text+0xe4): undefined reference to `Ocean::Ocean()' 
build\temp.win32-2.7\Release\testclass.o:testclass.cpp:(.text+0xfa): undefined reference to `Ocean::Ocean()' 
build\temp.win32-2.7\Release\testclass.o:testclass.cpp:(.text+0x11a): undefined reference to `Ocean::~Ocean()' 
build\temp.win32-2.7\Release\testclass.o:testclass.cpp:(.text+0x196): undefined reference to `Ocean::~Ocean()' 
collect2.exe: error: ld returned 1 exit status 
error: command 'C:\\MinGW\\bin\\g++.exe' failed with exit status 1 
+0

Извините! Я редактировал журнал ошибок, потому что он был неправильным. Добавлено: и я все еще получаю сообщение об ошибке в сгенерированном файле test.cpp. –

+0

Это не изменяет ошибку. –

+0

Я пробовал, у меня есть только ошибка от установки. Я замечаю, что вы забыли включить 'iostream' в' testclass.cpp', и вы не предоставляете реализацию 'Ocean'. Почему вы «из океана cimport Ocean»? Обратите внимание: я ничего не знаю о cython. – Stargateur

ответ

0

я, наконец, удалось заставить его работать.

Нет необходимости обертывать класс Ocean и, следовательно, создавать для него файл .pxd. Но в setup.py важно включить все зависимости .cpp.

Как сказано в предыдущих комментариях, также важно добавить включить охрану в файл заголовков.

Так вот рабочий код (скомпилирован с python setup.py build_ext --inplace)

ocean.hpp

#ifndef OCEAN_H 
#define OCEAN_H 

class Ocean { 
    public: 
     double _depth; 
     double _rho; 

     Ocean(); 
     virtual ~Ocean(); 
     void setwaterdepth(double d); 
}; 

#endif 

testclass.hpp

#ifndef TESTCLASS_H 
#define TESTCLASS_H 
#include "ocean.hpp" 

class TestClass { 
    private: 
     Ocean _ocean; 

    public: 
     int x, y; 
     TestClass(); 
     virtual ~TestClass(); 
     int Multiply(int a, int b); 
     void _set_x(int x); 
}; 

#endif 

testclass.cpp

#include <iostream> 
#include "testclass.hpp" 
#include "ocean.hpp" 

TestClass::TestClass() 
{ 
    x = 5; 
    y = 1; 
    _ocean = Ocean(); 
    std::cout << "Calling constructor" << std::endl; 
} 

TestClass::~TestClass() 
{ 
    std::cout << "Calling destructor" << std::endl; 
} 

int TestClass::Multiply(int a, int b) 
{ 
    return a*b; 
} 

void TestClass::_set_x(int new_x) 
{ 
    x = new_x; 
} 

тест .pyx

cdef extern from "testclass.hpp": 
    cdef cppclass TestClass: 
     TestClass() 
     int x 
     int y 
     int Multiply(int a, int b) 

cdef class pyTestClass: 
    cdef TestClass* thisptr # hold a C++ instance 

    def __cinit__(self): 
     self.thisptr = new TestClass() 

    def __dealloc__(self): 
     del self.thisptr 

    def Multiply(self, a, b): 
     return self.thisptr.Multiply(a, b) 

    property y: 

     # Here we use a property to expose the public member 
     # y of TestClass to Python 

     def __get__(pyTestClass self): 
      return self.thisptr.y 

     def __set__(pyTestClass self, value): 
      self.thisptr.y = <int> value 

setup.ру

from distutils.core import setup, Extension 
from Cython.Build import cythonize 

ext = Extension("test", 
      sources=["test.pyx", "testclass.cpp", "ocean.cpp"], 
      language="c++") 

setup(name="test", ext_modules=cythonize(ext)) 

испытание оберточной

import test as wrapper 

T = wrapper.pyTestClass() 
print T.Multiply(3, 5) 
print T.y 
T.y = 3 
print T.y 

выходы

Calling ocean constructor 
Calling ocean constructor 
Calling ocean destructor 
Calling constructor 
15 
1 
3 
Calling destructor 
Calling ocean destructor