在cython

时间:2017-02-22 09:41:41

标签: cython

我用Cython在Python中包装C ++类。 Cython构建共享库没有问题(有3个警告,但我检查了它们,显然是正常的)。从Python导入工作也很好。但是当我运行Python代码时,我会在调用其中一个类的析构函数后获得Bus error。经过一些研究,我发现bus errors是由内存管理问题引起的。

我首先想到的是我的C ++指针和类存在问题。我写了一个类似于Python的main.cpp代码来重现Segmentation fault,但该程序运行良好。

从那里我推断这是一个cython问题。在我的.pxd文件中,我没有声明复制构造函数,复制分配运算符和析构函数(我从Cython文档中激发了我的代码)。在我的.pyx文件中,我有__cinit____dealloc__方法。

我的问题是来自Cython cppclass中非复制构造函数和复制分配运算符的声明吗?如果是,请如何在.pyx文件中实现此方法?我试过但是Cython不会识别这些符号......

cppCotest.h

 #ifndef __CORAL2_H_INCLUDED__
 #define __CORAL2_H_INCLUDED__

 class CoralBranch{
   public:
     CoralBranch(); //nullary constructor
     CoralBranch(int st); //constructor
     ~CoralBranch(); //destructor
     CoralBranch(const CoralBranch&); //copy constructor
     CoralBranch& operator=(const CoralBranch&); //copy assignement
     CoralBranch *left; //Pointer to left child
     CoralBranch *right; //Pointer to right child
     int state;
   };

class Coral{
  public:
    Coral(); //constructor
    ~Coral(); //destructor
    Coral(const Coral&); //copy constructor
    Coral& operator=(const Coral&); //copy assignement
    void add_left(CoralBranch *leaf); //adds left son to coral-branch*leaf
    void add_right(CoralBranch *leaf); //adds right son to coral-branch *leaf
    void grow(CoralBranch *branch);
    CoralBranch *trunk;
   };

   #endif

cppCotest.cpp

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include "cppCotest.h"
    #include <math.h>
    using namespace std;

    CoralBranch::CoralBranch():left(NULL),right(NULL),state(1)
    {
    }

    CoralBranch::CoralBranch(int st):left(NULL),right(NULL),state(st)
    {
    }

    CoralBranch::~CoralBranch(){
      delete left;
      delete right;
    }

    CoralBranch::CoralBranch(const CoralBranch& cb){
      left=new CoralBranch(cb.left->state);
      right=new CoralBranch(cb.right->state);
      state=cb.state;
    }

    CoralBranch& CoralBranch::operator=(const CoralBranch& cb){
      if(this!=&cb){
        delete[] left;
        delete[] right;
        left=new CoralBranch(cb.left->state);
        right=new CoralBranch(cb.right->state);
        state=cb.state;
      }
      return *this;
    }

    Coral::Coral():trunk(new CoralBranch())
    {
    }

    Coral::~Coral(){
      delete trunk;
    }

    Coral::Coral(const Coral& c){
      trunk=new CoralBranch(c.trunk->state);
    }

    Coral& Coral::operator=(const Coral& c){

       if(this!=&c){
         delete[] trunk;
         trunk=new CoralBranch(c.trunk->state);
       }
       return *this;
     }

     void Coral::add_left(CoralBranch *leaf){
        leaf->left=new CoralBranch();
     }

     void Coral::add_right(CoralBranch *leaf){
        leaf->right=new CoralBranch();
     }

    void Coral::grow(CoralBranch *branch){

      if(branch!=NULL){

        if (branch->state==1){

          add_left(branch);
          add_right(branch);
          branch->state=0;
      }

      grow(branch->left);
      grow(branch->right);
    }
  }

cyCotest.pxd

#cython: language_level=3
#cython: wraparound=False
#cython: boundscheck=False
#cython: cdivision=True
#distutils: language=c++

import sys
import cython

cdef extern from "cppCotest.h":

  cdef cppclass CoralBranch:
    CoralBranch() except +
    CoralBranch(int st) except +
    #CoralBranch(const CoralBranch&)
    #CoralBranch& operator=(const CoralBranch&)
    CoralBranch *left
    CoralBranch *right
    int state

  cdef cppclass Coral:
    Coral() except +
    #Coral(const Coral&)
    #Coral& operator=(const Coral&)
    void add_left(CoralBranch *leaf)
    void add_right(CoralBranch *leaf)
    void grow(CoralBranch *growingbranch)
    CoralBranch *trunk

pyCotest.pyx

#cython: language_level=3
#cython: wraparound=False
#cython: boundscheck=False
#cython: cdivision=True
#distutils: language=c++
#distutils: sources=cppCotest.cpp

import sys
import cython
from cyCotest cimport Coral
from cyCotest cimport CoralBranch


cdef class PyCoral:
  cdef Coral c_coral
  def __cinit__(self):
    self.c_coral=Coral()
  c_coralbranch=PyCoralBranch(1)
  def add_left(self, PyCoralBranch leaf):
    self.c_coral.add_left(leaf.c_coralbranch)
  def add_right(self,PyCoralBranch leaf):
    self.c_coral.add_right(leaf.c_coralbranch)
  def grow(self,PyCoralBranch branch):
    self.c_coral.grow(branch.c_coralbranch)

cdef class PyCoralBranch:
  cdef CoralBranch* c_coralbranch
  def __cinit__(self,int st):
    self.c_coralbranch=new CoralBranch(st)
  def __dealloc__(self):
    del self.c_coralbranch

pyCotestmain.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from pyCotest import PyCoral

N_generations=2

coral=PyCoral()

for i in range(N_generations):
    coral.grow(coral.trunk)

setup.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

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

ext_modules = [
    Extension(
        "pyCotest",
        sources=["pyCotest.pyx", "cppCotest.cpp"],
        extra_compile_args=["-fopenmp","-fPIC"],
        extra_link_args=["-fopenmp"],
        language="c++",
    )
]

for e in ext_modules:
    e.pyrex_directives = {"boundscheck": False}

setup(
    name='Coral_library',
    ext_modules=cythonize(ext_modules),
)

0 个答案:

没有答案