chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] Exporting class definitions to C++?


From: Thomas Christian Chust
Subject: Re: [Chicken-users] Exporting class definitions to C++?
Date: Mon, 29 Jan 2007 10:02:55 +0100
User-agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1.2pre) Gecko/20070111 SeaMonkey/1.1

Elliot Cuzzillo wrote:

> Is there a way to define a class in Scheme and have it export a C++
> class definition (which might inherit from existing C++ classes), so
> that C++ classes can instantiate and inherit from it?
> [...]

Hello,

I'm reposting this message because I got a strange error reply from one
of the mailservers on the way and I think it didn't make it to the list...

as far as I know there is no such automatism available with the EasyFFI
egg of CHICKEN. But I recall that SWIG provided a mechanism for that
purpose through so called "director classes" -- I just don't know
whether it was available in SWIG's CHICKEN frontend.

Anyway, if there is no automatic way to achieve this, you can always
write a class in C++ which wraps a Scheme object and delegates all
virtual method calls from the C++ side to Scheme method calls, which is
exactly what a SWIG director class does. I have attached a "simple"
example of this technique.

Maybe it would be worth the effort to automate this whole mess and add
it to EasyFFI in the form of a few convenient macros...

cu,
Thomas


;;; How to help class inheritance hierarchies to cross
;;; the C++ <-> Scheme boundary.
;;;
;;; Compile using csc -X easyffi -c++ foo.scm

(require-extension tinyclos)

;; First we have the completely native C++ stuff:

#>
#include <iostream>
using namespace std;

class Foo {
 protected:
  int x;

 public:
  virtual ~Foo() {
  }
  int getX() {
    return x;
  }
  virtual int frobnicate(int y) = 0;
} ;

void frobnicateAFoo(Foo *foo, int y) {
  cout << foo->frobnicate(y) << endl;
}
<#

;; Then the wrapper declarations:

#>?
___abstract class Foo {
 protected:
  int x;

 public:
  virtual ~Foo();
  int getX();
  virtual int frobnicate(int y);
} ;

___safe void frobnicateAFoo(Foo *foo, int y);
<#

(define-method (destroy (foo <Foo>))
  ((foreign-lambda* void ((c-pointer foo))
     "delete (Foo *)foo;")
   (slot-ref foo 'this)))

;; Then we add some glue code:

#>
extern "C" int SCHEME_FooWrapper_frobnicate(C_word foo, int y);

class FooWrapper : public Foo {
 protected:
  void *sor;

 public:
  FooWrapper(C_word _so) {
    x = 42;
    sor = CHICKEN_new_gc_root();
    CHICKEN_gc_root_set(sor, _so);
  }
  virtual ~FooWrapper() {
    CHICKEN_delete_gc_root(sor);
  }
  virtual int frobnicate(int y) {
    return SCHEME_FooWrapper_frobnicate(CHICKEN_gc_root_ref(sor), y);
  }
} ;
<#

(define-external (SCHEME_FooWrapper_frobnicate (scheme-object foo) (int y)) int
  (frobnicate foo y))

;; And finally we can easily inherit from the first C++ class above:

(define-class <MyFoo> (<Foo>)
  (z))

(define-method (initialize (foo <MyFoo>) initargs)
  (slot-set! foo 'this
    ((foreign-lambda* c-pointer ((scheme-object foo))
       "return(new FooWrapper(foo));")
     foo))
  (initialize-slots foo initargs))

(define-method (frobnicate (foo <MyFoo>) y)
  (+ (* (getX foo) y) (slot-ref foo 'z)))

;; Let's see whether the native C++ call does the right thing:

(define a-foo (make <MyFoo> 'z 23))
(frobnicateAFoo a-foo 2)
(destroy a-foo)


reply via email to

[Prev in Thread] Current Thread [Next in Thread]