我用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),
)