[Top][All Lists]
[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)