# Re: C++ in STk

From: Andrew Dorrell <andrewd_at_ee.uts.edu.au>
Date: Wed, 16 Aug 95 10:34:33 EST

> I need to add some third party C++ code to STk *now*. I am not after a
> difinitive solution which addresses all the philosophical issues.... but
> would greatly appreciate knowing if and how other people have done this.

Thanks for the responses, here is a summary:

------------------------------------------------------------
>From fox_at_GRAPHICS.CS.NYU.EDU Sat Aug 12 22:27:05 1995

I use C++ pretty much the way I would use C:

#include "stk.h"
#include "sys/time.h"

typedef PRIMITIVE (*PF)(...);

static PRIMITIVE
stk_gettimeofday()
{
struct timeval tv;
gettimeofday(&tv, 0);
return STk_cons(STk_makeinteger(tv.tv_sec), STk_makeinteger(tv.tv_usec));
}

class ZVector {
public:
ZVector(double x, double y);
ZVector(const ZVector &p);
double x() const;
double y() const;
#if 0
INLINE friend ZVector operator+(const ZVector &a, const ZVector &b);
INLINE friend ZPoint operator+(const ZVector &a, const ZPoint &b);
INLINE friend ZPoint operator+(const ZPoint &a, const ZVector &b);
INLINE friend ZVector operator-(const ZVector &a);
INLINE friend ZPoint operator-(const ZPoint &a, const ZVector &b);
INLINE friend ZVector operator-(const ZVector &a, const ZVector &b);
INLINE friend ZVector operator*(double k, const ZVector &a);
INLINE friend ZVector operator*(const ZVector &a, double k);
INLINE friend ZVector operator/(const ZVector &a, double k);
INLINE friend double dot(const ZVector &a, const ZVector &b);
INLINE friend double det(const ZVector &a, const ZVector &b);

void operator*=(double k);

ZVector cw90() const;
ZVector ccw90() const;
double lenlen() const;
double length() const;
double slope() const;
bool operator==(const ZVector &v) const;
#endif
private:
double x_;
double y_;
};

ZVector::ZVector(double x, double y) : x_(x), y_(y) {}
ZVector::ZVector(const ZVector &p) : x_(p.x_), y_(p.y_) {}

double ZVector::x() const {return x_;}
double ZVector::y() const {return y_;}

class ZVector;
#define TRVECTOR(x) ((ZVector*)(EXTDATA(x)))
#define TRVECTORP(x) (TYPEP(x, tc_trvector))
#define NTRVECTORP(x) (NTYPEP(x, tc_trvector))
extern int tc_trvector;
extern SCM make_vector(const ZVector &);

int tc_trvector;

void
mark_tr_vector(SCM)
{
}

void
free_tr_vector(SCM vector)
{
delete TRVECTOR(vector);
}

static void
display_tr_vector(SCM vector, SCM port, int /*mode*/)
{
ZVector *p = TRVECTOR(vector);
sprintf(STk_tkbuffer, "[vector %.2f %.2f]", p->x(), p->y());
Puts(STk_tkbuffer, FILEPTR(port));
}

static STk_extended_scheme_type tr_vector_type = {
"trvector", /* name */
0, /* is_procp */
mark_tr_vector, /* gc_mark_fct */
free_tr_vector, /* gc_sweep_fct */
NULL, /* apply_fct */
display_tr_vector /* display_fct */
};

SCM
make_vector(const ZVector &vector)
{
SCM pinfo;
NEWCELL(pinfo, tc_trvector);
TRVECTOR(pinfo) = new ZVector(vector);
return pinfo;
}

static PRIMITIVE
tr_make_vector(SCM x, SCM y)
{
ZVector v(FLONM(x), FLONM(y));
return make_vector(v);
}

static PRIMITIVE
tr_vector_x(SCM v)
{
return STk_makenumber(TRVECTOR(v)->x());
}

static PRIMITIVE
tr_vector_y(SCM v)
{
return STk_makenumber(TRVECTOR(v)->y());
}

extern "C" {

void
STk_user_init(void)
{

}

void STk_user_cleanup()
{
}

};

------------------------------------------------------------
>From hickst_at_nemesis.tucson.saic.com Sun Aug 13 04:06:20 1995

We've done some extensions to STk involving functions from the LibG++
Library using the String data type. Basically, we had to write a small
wrapper for each function which connects to STk. The wrapper adds an
argument which we called the class handle (void pointer to an object).
The STk primitive function then calls the wrapper using the class handle.
The wrapper, of course, call the C++ function.

Here's a concrete example for the LibG++ function String.freq which
counts the number of occurances of a substring within a String:
(see the LibG++ info pages for (a tiny bit) more info. (The LibG++
info pages really lack crucial information. :)).

The STk primitive looks like:

static PRIMITIVE freq(SCM string, SCM substring)
{
int res;

res = String_freq_char( (class_handle) new_String(CHARS(string)),
CHARS(substring) );
return(STk_makeinteger( (long) res));
}

This calls the wrapper String_freq_char. (Note that we need a different
wrapper for each combination of possible argument types - a drawback
of this method). The wrapper looks like:

int String_freq_char(class_handle h, char *ss) {
return( ((String *) h)->freq(ss));
}

The class_handle is just a void *.

Of course, I'm glossing over some of the details, such as include
files and forward declaractions. I may also have some of the details
garbled since it was Sarah Officer (of our organization) who really
worked the details of this out. Anyway, hope that helps,
-tom

p.s. I don't know whether my mailer is gonna reply to you
or stk-request. If you, feel free to repost this.

------------------------------------------------------------
>From dbo_at_arbortext.com Mon Aug 14 23:37:20 1995

I incorporated stk into a linking loader (I didn't use the TK part, it
turned out). I changed the way the main loop worked a bit (C++ calls
something that calls stk that calls back into my C++ environment).
I'm 6 months out of the project, but I can certainly state that it can
be done and might be able to dredge up some details if that would
help.

-Doug

```--
------------------------------------------------------------------------------
Mr Andrew Dorrell
School of Electrical Engineering                 *
University of Technology, Sydney                     *
PO Box 123                                     *