Sascha Van Cauwelaert | 21 Nov 10:28 2011
Picon

Interface problem in LispWorks but not in SBCL

Hello everybody,

I am using SWIG to generate CFFI code to be used into LispWorks 6. The interface is between C++ and Common
Lisp. Then, I try to call that function from LispWorks :

std::string  test() {
	freopen ("/tmp/mystdout.txt","w",stdout);
	freopen ("/tmp/mystderr.txt","w",stderr);
	std::cout << "Redirected stdout." << std::endl;
	std::cerr << "Redirected stderr." << std::endl;
	
	GRelation testgr(3);

	std::cout << "test ! " << std::endl;
	std::cerr << "test cerr! " << std::endl;
	std::cout << testgr.arity() << std::endl;
	std::cerr << testgr.arity() << std::endl;	
	std::cout << "test after! " << std::endl;
	std::cerr << "test cerr after! " << std::endl;
	std::stringstream os;
	os << testgr << std::endl ;
	return os.str();
}

As you can see, I just create one object and print lots of stuff, including an object attribute. Everything I
print before trying to print the attribute prints ok in the redirected outputs. The attribute is not
printed and nothing else afterwards. I also get the following error when I add testgr to the stringstream
os :

lispworks-personal-6-0-1-macos-universal(52881,0xb0314000) malloc: *** error for object
(Continue reading)

Martin Simmons | 22 Nov 21:16 2011

Re: Interface problem in LispWorks but not in SBCL

>>>>> On Mon, 21 Nov 2011 10:28:56 +0100, Sascha Van Cauwelaert said:
> 
> Hello everybody,
> 
> I am using SWIG to generate CFFI code to be used into LispWorks 6. The
> interface is between C++ and Common Lisp. Then, I try to call that function
> from LispWorks :
> 
> std::string  test() {
> 	freopen ("/tmp/mystdout.txt","w",stdout);
> 	freopen ("/tmp/mystderr.txt","w",stderr);
> 	std::cout << "Redirected stdout." << std::endl;
> 	std::cerr << "Redirected stderr." << std::endl;
> 	
> 	GRelation testgr(3);
> 
> 	std::cout << "test ! " << std::endl;
> 	std::cerr << "test cerr! " << std::endl;
> 	std::cout << testgr.arity() << std::endl;
> 	std::cerr << testgr.arity() << std::endl;	
> 	std::cout << "test after! " << std::endl;
> 	std::cerr << "test cerr after! " << std::endl;
> 	std::stringstream os;
> 	os << testgr << std::endl ;
> 	return os.str();
> }
> 
> As you can see, I just create one object and print lots of stuff, including
> an object attribute. Everything I print before trying to print the attribute
> prints ok in the redirected outputs. The attribute is not printed and
(Continue reading)

Sascha Van Cauwelaert | 23 Nov 16:20 2011
Picon

Re: Interface problem in LispWorks but not in SBCL

Thank you for your answer.

Actually, I have an additional clue, which make me think that it is not related with garbage collection. If,
in Lispworks,  I use a wrapped function on the pointer to the C object (e.g. to get the arity), it works fine ! 

It seems that I just can't call a function which print some information about the object in a C++ function,
wrapped to be used in LispWorks ... If I do it, I get the error :

lispworks-personal-6-0-1-macos-universal(49641,0xb0314000) malloc: *** error for object
0x17bfc0f8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

I don't get how it can work in SBCL and not in LispWorks, and I have no clue because I don't know the internal
implementation of LispWorks.

I would really appreciate a little bit of your help.

Regards,

Sascha Van Cauwelaert

Le 22 nov. 2011 à 21:16, Martin Simmons a écrit :

>>>>>> On Mon, 21 Nov 2011 10:28:56 +0100, Sascha Van Cauwelaert said:
>> 
>> Hello everybody,
>> 
>> I am using SWIG to generate CFFI code to be used into LispWorks 6. The
>> interface is between C++ and Common Lisp. Then, I try to call that function
>> from LispWorks :
(Continue reading)

Martin Simmons | 24 Nov 20:55 2011

Re: Interface problem in LispWorks but not in SBCL

I've tried to replicate what you are doing, by adding the following hacks to
your function in a file called gtest.cpp:

#include <iostream>
#include <sstream>
#include <string>

class GRelation {
private:
  int _arity;
public:
  int arity() { return _arity; };
  GRelation(int arity) { _arity = arity; };
};

std::ostream& operator<<(std::ostream& out, GRelation &g)
{
  out << "<GRelation" << g.arity() << ">";
  return out;
};

I then passed it through SWIG 1.3.31:

swig -cffi -c++ -module gtestswig gtest.cpp
cat gtest.cpp gtest_wrap.cxx > gtest_code_and_wrap.cpp

Beware that I've not read much C++ or SWIG documentation, so the above might
be somewhat bogus!

Following that, it ran without errors with CFFI 0.10.6 on Mac OS X 10.6.8 like
(Continue reading)

Sascha Van Cauwelaert | 25 Nov 17:08 2011
Picon

Re: Interface problem in LispWorks but not in SBCL

Thank you very much for your answer, again.

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). 
I read documentation about defsystem but I didn't find how to do it ? Could you please tell me where I could
find that information ?

Best regards,

Sascha Van Cauwelaert

Le 24 nov. 2011 à 20:55, Martin Simmons a écrit :

> I've tried to replicate what you are doing, by adding the following hacks to
> your function in a file called gtest.cpp:
> 
> #include <iostream>
> #include <sstream>
> #include <string>
> 
> class GRelation {
> private:
>  int _arity;
> public:
>  int arity() { return _arity; };
>  GRelation(int arity) { _arity = arity; };
(Continue reading)

Frank Goenninger | 25 Nov 18:25 2011

Re: Interface problem in LispWorks but not in SBCL

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&cd=6&ved=0CD4QFjAF&url=http%3A%2F%2Fwww-hera-b.desy.de%2Fsubgroup%2Fsoftware%2Fclue%2FBEE-0-98%2Fgrelation%2Fmanual.ps.gz&ei=fs7PTs6EMNCEhQex6NTmDQ&usg=AFQjCNGTikFM_ttnj1PqfaEQHm9H0Ey_Ow&sig2=q_nFQ9Jxnc5OB8A_b0sjMw

Something else?

  Frank
Sascha Van Cauwelaert | 26 Nov 14:56 2011
Picon

Re: Interface problem in LispWorks but not in SBCL

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_ptr<VarImpl::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
    // <at> {
    /// 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);
    // <at> }
    /// \name Modification operations
    // <at> {
    /**
     * \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);
    // <at> }
    /// \name Set operations
    // <at> {
    /// 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;
    // <at> }
    /// \name Column permutation
    // <at> {
    /**
     * \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;
    // <at> }
    /// \name Cross product
    // <at> {
    /**
     * \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;
    // <at> }
    /// \name Relational algebra operations
    // <at> {
    /**
     * \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;
    // <at> }
    /// \name Quantification
    // <at> {
    /**
     * \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;
    // <at> }

    /**
     * \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$
    // <at> }
    /// \name Test operations
    // <at> {
    /// 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;
    // <at> }
    /// \name Relation information
    // <at> {
    /// 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;
    // <at> }
    /// \name Constant relations
    // <at> {
    /// Creates the binary relation \f$ R = \{(x,y) : x = y \} \f$
    //static GRelation equalXY(void);
    // <at> }
    /// \name Content access
    // <at> {
    /**
     * \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;
    // <at> } 
    /// \name Output
    //{ <at>
    void print(std::ostream& os) const;
    // <at> }
  };


  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&cd=6&ved=0CD4QFjAF&url=http%3A%2F%2Fwww-hera-b.desy.de%2Fsubgroup%2Fsoftware%2Fclue%2FBEE-0-98%2Fgrelation%2Fmanual.ps.gz&ei=fs7PTs6EMNCEhQex6NTmDQ&usg=AFQjCNGTikFM_ttnj1PqfaEQHm9H0Ey_Ow&sig2=q_nFQ9Jxnc5OB8A_b0sjMw

Something else?

 Frank

_______________________________________________
cffi-devel mailing list
cffi-devel <at> common-lisp.net
http://lists.common-lisp.net/cgi-bin/mailman/listinfo/cffi-devel

Gmane