This is the mail archive of the guile@cygnus.com mailing list for the guile project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Jim Blandy <jimb@red-bean.com> writes: > One of Guile's primary goals is to interoperate smoothly with C and > C++ code. This is more important than performance, for example. So > this property will not go away. Speaking of interoperating with C++, I have a design question about wrapping C++ objects. I've found it really easy to wrap C++ objects with guile (see the template file I include below which I've used to make it especially easy), but I'm concerned about the grunt work in rewrapping subclasses. In particular, suppose I have a class Foo that I've already got wrapped nicely in guile so I have primitives (make-foo), (foo? FOO), and the SMOB functions all taken care of. Now I want to change some of the dynamic behaviour of class Foo by public inheritance and override: i.e., class Bar: public Foo { ... }. My concern is that I now need to re-wrap the derived class to maintain type-safety. One possible solution is to keep the base class's SMOB identifier in the derived class. Then I'd just need to add new (make-bar) and (bar? BAR) primitives, where the latter would do a (foo? BAR) and use C++'s RTTI to see if a downcast is safe. Alternatively, I could avoid using C++'s virtual function mechanism at all, and have C-style callbacks and hooks in the C++ class instead of using the language-level features. Does anybody have any experience, wisdom, or thoughts on this matter? Thanks, Greg Here's my C++->guile wraper template file -- comments are welcome and appreciate -- I use this with an auto-insert mode with Emacs. (Sorry for the length of this). //// $Id: new-type-skeleton.cc,v 1.3 1998/07/19 22:01:22 gjb Exp $ //// Skeleton to use for creating a new type for GUILE //// (C) 1998, By Greg J. Badros -- 18 July 1998 // SCMTYPE: %[SCMTYPE (e.g., cl_variable -- a C identifier)? %] // SCM object name: %[SCM object name (e.g., cl-variable -- a Scheme id)? %] // Wrapped type name: %[Wrapped Type Name (e.g., ClVariable)? %] // Hungarian Tag: %[Hungarian tag name (e.g, clv)? %] // By %U // %d #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <guile/gh.h> #include <assert.h> #include "scwm.h" #define %F_IMPLEMENTATION #include "%b.h" #ifdef __cplusplus extern "C" { #endif #define NEW(x) ((x *) safemalloc(sizeof(x))) #define NEWC(c,x) ((x *) safemalloc((c)*sizeof(x))) #define FREE(x) free(x) inline SCM SCM_BOOL_FromF(bool f) { return (f? SCM_BOOL_T: SCM_BOOL_F); } inline bool FUnsetSCM(SCM scm) { return (scm == SCM_UNDEFINED || scm == SCM_BOOL_F); } //// %3 wrapper #undef SCMTYPEID #define SCMTYPEID scm_tc16_%1 long SCMTYPEID; inline bool FIs%3Scm(SCM scm) { return SCM_NIMP(scm) && SCM_CAR(scm) == (SCM) SCMTYPEID; } inline %3 *P%4FromScm(SCM scm) { return (%3 *)(SCM_CDR(scm)); } SCM mark_%1(SCM scm) { SCM_SETGC8MARK(scm); return SCM_BOOL_F; } size_t free_%1(SCM scm) { %3 *p%4 = P%4FromScm(scm); delete p%4; return 0; } int print_%1(SCM scm, SCM port, scm_print_state *pstate) { strstream ss; %3 *p%4 = P%4FromScm(scm); ss << "#<%2" << *p%4 << ">" << ends; scm_puts(ss.str(), port); return 1; } SCWM_PROC (%1_p, "%2?", 1, 0, 0, (SCM scm)) #define FUNC_NAME s_%1_p { return SCM_BOOL_FromF(FIs%3Scm(scm)); } #undef FUNC_NAME SCWM_PROC (make_%1, "make-%2", 0, 0, 0, ()) #define FUNC_NAME s_make_%1 { int iarg = 1; %@ #if 0 // FIXME if (!FUnsetSCM(scm)) { if ( ) { scm_wrong_type_arg(FUNC_NAME, iarg++, scm); } else { sz = gh_scm2newstr(scm,NULL); p = PFromScm(scm); } } #endif %3 *p%4 = new %3(); SCM answer; SCM_DEFER_INTS; SCM_NEWCELL(answer); SCM_SETCAR(answer, (SCM) SCMTYPEID); SCM_SETCDR(answer, (SCM) p%4); SCM_ALLOW_INTS; return answer; } #undef FUNC_NAME #if 0 // PRIMITIVE FUNCTION TEMPLATE SCWM_PROC (, , 0, 0, 0, ()) #define FUNC_NAME s_ { return SCM_UNDEFINED; } #undef FUNC_NAME #endif MAKE_SMOBFUNS(%1); void init_%b() { REGISTER_SCWMSMOBFUNS(%1); #ifndef SCM_MAGIC_SNARFER #include "%b.x" #endif } #ifdef __cplusplus } // extern "C" #endif