Well, at first, I didn't want to bother people with the details. But now, it seems that it is needed.
The definition of the class and the implementation are below. Here is a git repo on which one can find the whole project : git://github.com/ggutierrez/cprelmaster.git (the class is defined in rel/grelation.hh)
In my experience with SWIG and CFFI, I've never had that kind of problem. At some point, the implementation is using a library named cudd (http://vlsi.colorado.edu/~fabio/CUDD/). Maybe the problem comes from there, I really don't know.
Thank you you for any help, it is highly appreciated.
Sascha
class GRelation { private: friend class GRelationIter; typedef boost::shared_ptrVarImpl::RelationImpl Impl; Impl pimpl_; ///> Relation storage /// Avoid default construction GRelation(void); /// Constructor taking an implementation explicit GRelation(Impl impl); public: /// \name Constructors, destructors and assignement //@{ /// Constructor for an empty relation of arity \a a explicit GRelation(int a); /// Copy constructor GRelation(const GRelation& r); /// Assignment GRelation& operator=(GRelation& right); void become(const GRelation& other);
/// Destructor ~GRelation(void); /// Constructs the relation \f$R=\mathcal{U}_{a}\f$ static GRelation create_full(int a); //@} /// \name Modification operations //@{ /** * \brief Adds tuple \a t to the relation. If \f$ t \in this \f$ the relation * remains unchanged. */ void add(const Tuple& t); /** * \brief Adds the tuples contained in \a s to the relation. */ void add(const std::vector<Tuple>& s); /** * \brief Union of relations: \f$ this = this \cup r \f$. */ void unionAssign(const GRelation& r); /** * \brief Difference of relations: \f$ this = this \setminus r \f$. */ void differenceAssign(const GRelation& r); //@} /// \name Set operations //@{ /// Computes \f$ this \setminus r \f$ GRelation difference(const GRelation& r) const; /// Computes \f$ this \cap r \f$ GRelation intersect(const GRelation& r) const; /// Computes \f$ this \cup r \f$ GRelation Union(const GRelation& r) const; /// Computes \f$ \overline{this}\f$ GRelation complement(void) const; //@} /// \name Column permutation //@{ /** * \brief Computes the permutation of \a this according to \a desc. * * \warning The permutation descriptor has to be valid for the relation. If it * is not then a InvalidPermDescriptor exception is thrown. */ GRelation permute(const std::vector<std::pair<int,int>>& desc) const; /** * \brief Computes the permutation of \a this according to \a desc. * * \warning The permutation descriptor has to be valid for the relation. If it * is not then a InvalidPermDescriptor exception is thrown. */ GRelation permute(const PermDescriptor& desc) const; /** * \brief Computes the relation resulting by shifting all the columns in \a r * \a n possitions to the right. * * The first \a n columns of \a r does not appear in the final relation. */ GRelation shiftRight(int n) const; //@} /// \name Cross product //@{ /** * \brief Computes \f$ \mathcal{U}_n \times this\f$. */ GRelation timesULeft(int n) const; /** * \brief Computes \f$ this \times \mathcal{U}_n \f$. */ GRelation timesURight(int n) const; /** * \brief Computes \f$ this \times r \f$ */ GRelation times(const GRelation& r) const; //@} /// \name Relational algebra operations //@{ /** * \brief Returns: \f$ \mathit{this};\bowtie_{j}; r \f$. * * This is, the result of joining the two relations on the \a j right most * columns of \a this and the \a j left most columns of \a r. */ GRelation join(int j,const GRelation& r) const; /** * \brief Returns: \f$ \mathit{this}_{\smile_{f}}r \f$. * * \todo documentation */ GRelation follow(int f,const GRelation& r) const; /** * \brief Returns: \f$ \Pi_{p} this \f$. * * This is, the projection of \a this on the \a p rightmost columns. * * \warning Throws an exception InvalidProjection if \a p is not a valid column * in the relation. */ GRelation project(int p) const; //@} /// \name Quantification //@{ /** * \brief Returns the relation resulting from existencially quantifying on * column \a c * * \param c a column: \f$ 0 \leq c < \text{arity}(\text{this})\f$ */ GRelation exists(int c) const; /** * \brief Returns the relation resulting from uniquely quantifying on column * \a c * * \param c a column: \f$ 0 \leq c < \text{arity}(\text{this})\f$ */ GRelation unique(int c) const; /** * \brief Returns the relation resulting from uniquely quantifying on all the * columns in \a c. * * \param c a vector of columns: \f$ \forall_{i \in * {0,\ldots,\text{size}(c)-1}}: 0 \leq c[i] < * \text{arity}(\text{this})\f$ */ GRelation unique(const std::vector<int>& c) const; /** * \brief Returns the relation resulting from universaly quantifying on column * \a c * * \param c a column: \f$ 0 \leq c < \text{arity}(\text{this})\f$ */ GRelation forall(int c) const; //@}
/** * \brief Computes the relation resulting by shifting all the columns in \a r * \a n possitions to the left. * * The new columns in the resulting relation are existentially quantified. */ //GRelation shiftLeft(int n) const; /// Returns the relation \f$ this \times r \f$ //@} /// \name Test operations //@{ /// Tests \f$ this \subseteq r \f$ bool subsetEq(const GRelation& r) const; /// Tests \f$ this \supset r \f$ bool superset(const GRelation& r) const; /// Tests \f$ this \cap r = \emptyset \f$ bool disjoint(const GRelation& r) const; /// Tests whether this represents the same relation as \a r bool eq(const GRelation& r) const; /// Tests whther the relation is empty bool empty(void) const; /// Tests whther the relation represents the universe bool universe(void) const; //@} /// \name Relation information //@{ /// Returns the arity (i.e. number of columns) of the relation int arity(void) const; /// Returns the cardinality (i.e. number of tuples) of the relation double cardinality(void) const; //@} /// \name Constant relations //@{ /// Creates the binary relation \f$ R = {(x,y) : x = y } \f$ //static GRelation equalXY(void); //@} /// \name Content access //@{ /** * \brief Returns one tuple represented by the relation. * * The only guarantee on the returned tuple is that it belongs to * the relation. */ Tuple pickOneTuple(void) const; //@} /// \name Output //{@ void print(std::ostream& os) const; //@} };
GRelation::GRelation(Impl impl) : pimpl_(impl) {}
GRelation::GRelation(int a) : pimpl_(Impl(new RelationImpl(a))) {}
GRelation::GRelation(const GRelation &r) : pimpl_(new RelationImpl(*(r.pimpl_))) { }
GRelation& GRelation::operator =(GRelation& right) { pimpl_.swap(right.pimpl_); return *this; }
void GRelation::become(const GRelation& other) { pimpl_ = Impl(new RelationImpl(*(other.pimpl_))); }
GRelation::~GRelation(void) {}
GRelation GRelation::create_full(int a) { RelationImpl full = RelationImpl::create_full(a); return GRelation( Impl(new RelationImpl(full)) ); }
/* * Modification */ void GRelation::add(const Tuple &t) { pimpl_->add(t); }
void GRelation::add(const std::vector<Tuple>& s) { std::for_each(s.begin(), s.end(), [=](const Tuple& t) { pimpl_->add(t); }); }
void GRelation::unionAssign(const GRelation &r) { pimpl_->add(*(r.pimpl_)); }
void GRelation::differenceAssign(const GRelation &r) { pimpl_->remove(*(r.pimpl_)); }
/* * Set operations */ GRelation GRelation::difference(const GRelation &r) const { return GRelation( Impl(new RelationImpl(VarImpl::difference(*pimpl_,*(r.pimpl_)))) ); }
GRelation GRelation::intersect(const GRelation &r) const { return GRelation( Impl(new RelationImpl(VarImpl::intersect(*pimpl_,*(r.pimpl_)))) ); }
GRelation GRelation::Union(const GRelation &r) const { return GRelation( Impl(new RelationImpl(VarImpl::Union(*pimpl_,*(r.pimpl_)))) ); }
GRelation GRelation::complement(void) const { return GRelation( Impl(new RelationImpl(VarImpl::complement(*pimpl_))) ); }
/* * Column permutation */ GRelation GRelation::permute(const std::vector<std::pair<int,int>>& desc) const { return GRelation( Impl(new RelationImpl(pimpl_->permute(desc))) ); }
GRelation GRelation::permute(const PermDescriptor& desc) const { typedef boost::error_info<struct tag_perm_descriptor,std::string> perm_descriptor;
if (!desc.valid(arity())) throw InvalidPermDescriptor() << errno_code(errno) << perm_descriptor("Invalid permutation description used at: GRelation::permute");
return permute(desc.getPerm()); }
GRelation GRelation::shiftRight(int n) const { return GRelation( Impl(new RelationImpl(pimpl_->shiftRight(n))) ); }
/* * Cross product */ GRelation GRelation::timesULeft(int n) const { return GRelation(Impl(new RelationImpl(pimpl_->timesULeft(n)))); }
GRelation GRelation::timesURight(int n) const { return GRelation(Impl(new RelationImpl(pimpl_->timesURight(n)))); }
GRelation GRelation::times(const GRelation& r) const { return join(0,r); }
/* * Relational algebra */ GRelation GRelation::join(int j,const GRelation& r) const { typedef boost::error_info<struct tag_invalid_join,std::string> invalid_join;
if (arity() < j || r.arity() < j) throw InvalidJoin() << errno_code(errno) << invalid_join("There are not enough columns for the join");
return GRelation( Impl(new RelationImpl(pimpl_->join(j, *(r.pimpl_)))) ); }
GRelation GRelation::follow(int f,const GRelation& right) const { /// \todo handle arity errors with exceptions
// if (arity() < j || r.arity() < j) // throw InvalidJoin() // << errno_code(errno) // << invalid_join("There are not enough columns for the join");
return GRelation( Impl(new RelationImpl(pimpl_->follow(f, *(right.pimpl_)))) ); }
GRelation GRelation::project(int p) const { typedef boost::error_info<struct tag_projection,std::string> projection;
if(p <= 0 || p > arity()) { throw InvalidProjection() << errno_code(errno) << projection("Invalid columns to project on"); } return GRelation( Impl(new RelationImpl(pimpl_->project(p))) ); }
/* * Quantification */ GRelation GRelation::exists(int c) const { return GRelation( Impl(new RelationImpl(pimpl_->exists(c))) ); }
GRelation GRelation::unique(int c) const { return GRelation( Impl(new RelationImpl(pimpl_->unique(c))) ); }
GRelation GRelation::unique(const std::vector<int>& c) const { return GRelation( Impl(new RelationImpl(pimpl_->unique(c))) ); }
GRelation GRelation::forall(int c) const { return GRelation( Impl(new RelationImpl(pimpl_->forall(c))) ); }
/* * Test operations */ bool GRelation::subsetEq(const GRelation& r) const { return VarImpl::subsetEq(*pimpl_,*r.pimpl_); }
bool GRelation::superset(const GRelation& r) const { return VarImpl::superset(*pimpl_,*r.pimpl_); }
bool GRelation::disjoint(const GRelation& r) const { return VarImpl::disjoint(*pimpl_,*r.pimpl_); }
bool GRelation::eq(const GRelation& r) const { return *pimpl_ == *(r.pimpl_); }
bool GRelation::empty(void) const { return pimpl_->empty(); }
bool GRelation::universe(void) const { return pimpl_->universe(); }
/* * Relation information */ int GRelation::arity(void) const { return pimpl_->arity(); }
double GRelation::cardinality(void) const { return pimpl_->cardinality(); }
/* * Content access */ Tuple GRelation::pickOneTuple(void) const { /// \todo throw an exception assert(!empty() && "Relation is empty, nothing to return"); return pimpl_->pickOneTuple(); }
/* * Relation output */ void GRelation::print(std::ostream& os) const { pimpl_->print(os); }
std::ostream& operator<< (std::ostream& os, const GRelation& r) { r.print(os); return os; }
Le 25 nov. 2011 à 18:25, Frank Goenninger a écrit :
Am 25.11.2011 um 17:08 schrieb Sascha Van Cauwelaert:
I tried what you did and it works. The problem is that the project I try to interface is much more complicated than this (and I cannot modify it) but still it helps.
I will try to do the same thing with the real class GRelation. But for this, I need to use another C compiler than the standard one (I have to use the last version of gcc) and to modify the passed options (not only add some).
Ok. This all leads to the question: What is the class GRelation really looking like? What is it that makes is so complicated? What is the "project" you are referring to? I jfgi and found those entries for GRelation:
http://waffles.sourceforge.net/
http://www.ibm.com/developerworks/linux/tutorials/l-glib/section9.html
http://www.google.de/url?sa=t&rct=j&q=grelation&source=web&c...
Something else?
Frank