#ifndef __TEST_H__
#define __TEST_H__
// small example for the YInG- the YAC Interface Generator.
//
// in order to compile this example library ("plugin"), first create the YAC interface by running
// "tks ../yac/ying test.h"
// which will create the following files:
// ying_test.h
// ying_test.cpp
// ying_MyClass.h
// ying_MyClass.cpp
// .
// .
//
// you may then e.g. load the plugin into the tkscript application host and test the whole thing
// by issueing e.g. "tks test"
//
// ----
// ----
// ---- the YG define is used to set the group name for the current set of classes/functions.
// ---- THe group name is used to prefix the output files, e.g. 'ying_<group>_<class>.cpp'
// ----
// ----
YG("test")
// ----
// ----
// ---- the YC define is used to export the given class. The class definition must appear
// ---- on the same text line.
// ----
// ---- the YAC define is used to forward-declarate some "magic" methods which will be implemented
// ---- by including the 'ying_<group>_<class>.cpp' file (which will be auto-generated by YInG).
// ----
// ----
YC class MyEmptyClass : public YAC_Object {
public:
YAC(MyEmptyClass);
};
// ----
// ---- the YP define is used to export members (properties).
// ---- YInG will generate set/get methods for each member and also create an export-table
// ---- which contains the member offsets relative to the class object base pointer.
// ----
YC class MyVector : public YAC_Object {
public:
YP float x;
YP float y;
YP float z;
YAC(MyVector);
sSI YAC_VCALL yacTensorRank(void) { return YAC_TENSOR_RANK_VECTOR; }
YM sF32 getAbs(void);
};
// ----
// ---- the next example will export the set/get methods in this class
// ---- (look for
// ---- YM //int getA(void);
// ---- YM //void setA(int);
// ---- )
// ----
class BaseClass : public YAC_Object {
public:
sSI a;
sSI b;
sSI getA(void) { return a;}
void setA(sSI _a) { a=_a; }
};
// ----
// ---- the YCI and YCF defines are used to export int and float constants.
// ----
// ---- please notice that YInG automatically creates the rtti-check/prepare code so
// ---- you can also directly export methods which use objects derived from YAC_Object
// ---- (in this example YAC_String and MyClass)
// ----
YC class MyClass : public BaseClass {
public:
YAC(MyClass);
#define XXXA YCI 42
#define XXXB YCI 64
#define XXXPI YCF 3.1415f
YP sSI i;
YP sSI j;
YP sSI k;
YP YAC_String *myString;
// ----
// ---- the YM // syntax is used to export methods that were originally declared
// ---- in a base-class.
// ----
YM //sSI getA(void) { return a;}
YM //void setA(sSI _a) { a=_a; }
MyClass(void) {a=99; myString=0;}
~MyClass()
{
if(myString)
yac_host->yacDelete(myString);
}
YM void manyargs (int _i, float _f, YAC_String *_s, MyClass *_c) { yac_host->printf("manyargs _i=%i _f=%f _s=\"%s\" _c=%p\n", _i,_f,_s->chars,_c); }
YM void test1 (void) { yac_host->printf("test1() called.\n"); }
YM void test2 (int _i) { yac_host->printf("test2(%i) called.\n", _i); }
YM int test3 (void) { return 23; }
YM int test4 (int _i) { return _i*_i; }
YM void test5 (YAC_Object*) { }
YM YAC_Object *test6 (void) { return this; }
YM void test7 (YAC_String*) { }
YM sF32 test8 (YAC_String*) { return 1.23f; }
YM YAC_String *test9 (void) { return 0;};
YM MyClass *test10 (void) { return this; };
YM void calcState(sF32 _deltatime, sSI _binterpolate) { yac_host->printf("deltatime=%f, binterpolate=%i\n", _deltatime, _binterpolate); }
// ----
// ---- if the string "YAC_Value *_r" appears within the declaration of an exported
// ---- method, the interface generator will interpret it as a "variable-return-type" method
// ----
YM void returnNewMyClass(YAC_Value *_r);
sBool YAC_VCALL yacToString(YAC_String *_s)
// ----
// ---- this method is called by the runtime whenever this object must be converted
// ---- to a string, e.g. in a "print" statement.
// ----
{
#ifdef YAC_BIGSTRING
_s->alloc(256);
::sprintf((char*)_s->chars, "(%i,%i,%i)", i,j,k);
_s->fixLength();
return 1;
#endif
return 0;
}
// ---- Declare tensor rank of Object (used by testObjRet*() methods) ----
sSI YAC_VCALL yacTensorRank(void) { return YAC_TENSOR_RANK_SCALAR; }
// ---- getter/setter methods for i,j,k members ----
YM sSI getI (void) { return i; }
YM void setI (sSI _i) { i = _i; }
YM sSI getJ (void) { return j; }
YM void setJ (sSI _j) { j = _j; }
YM sSI getK (void) { return k; }
YM void setK (sSI _k) { k = _k; }
// ---- Initialize "this" with integer value ----
void YAC_VCALL yacValueOfI(sSI _i) { i = _i; }
YM void getString(YAC_Value *_r)
// ----
// ---- this method returns a new string which is meant to be deleted by the tkscript runtime
// ----
// ---- if you define YAC_BIGSTRING before #including <yac.h>, the YAC_String class will
// ---- implement the alloc() and fixLength() methods (along with some others)
// ----
// ---- Please notice that a getFoo() method can be addressed like a ".foo" property, i.e.
// ---- print new MyClass().string; // will call MyClass::getString()
// ----
{
YAC_String *r=YAC_New_String();
yacToString(r);
_r->initString(r, 1 /**deleteme */);
}
YM YAC_String *getMyString(void)
// ----
// ---- this method returns a "read-only" reference to the property "myString".
// ----
// ---- please remember that this class deletes "myString" when
// ---- it is destructed; the tkscript runtime will just reference the returned
// ---- object (which also means that it may only be referenced in scripts until
// ---- the instance of this class which returned myString is destroyed)
// ----
{
return myString;
}
YM void setMyString(YAC_Object *_s)
// ----
// ---- this method sets the property "myString" by assigning the given String.
// ---- the YAC_BCHK() macro is used to test whether YAC_String is a baseclass of _s.
// ----
{
if(YAC_BCHK(_s, YAC_CLID_STRING))
{
if(!YAC_VALID(myString))
{
myString = YAC_New_String();
}
myString->yacOperatorAssign(_s);
}
else
{
::printf("[---] setMyString: parameter _s is not a String.\n");
}
}
YM void setMyStringValue(YAC_Object *_vo)
//
// ---- this method assigns the given YAC_ValueObject (if it holds a YAC_String object)
// ---- to the property "myString".
// ----
// ---- Notice that if the YAC_String value has the "deleteme" flag set, then the
// ---- String object is unlinked from the ValueObject and placed in "myString".
// ----
// ---- script-wise this behaviour can be tested by using the #(<expr>) expression,
// ---- which wraps the <expr> result in a YAC_ValueObject. Example: print #(new String()).string;
// ---- resp. _=new MyClass().setMyStringValue( #(new String()) );
// ----
// ---- You should generally never keep object pointers that are passed from the script-engine to C++
// ---- methods although it may sometimes be useful for speeds sake. At least *never* delete these
// ---- object pointers unless they come from a YAC_Value that has the "deleteme" flag set.
//
{
if(YAC_BCHK(_vo, YAC_CLID_VALUE))
{
YAC_ValueObject *vo=(YAC_ValueObject*)_vo;
if(vo->type>3)
if(YAC_BCHK(vo->value.object_val, YAC_CLID_STRING))
{
if(vo->deleteme)
{
::printf("[...] MyClass::setMyStringValue: unlinking value object..\n");
vo->deleteme=0;
if(YAC_VALID(myString))
{
YAC_DELETE(myString);
}
myString=vo->value.string_val;
}
else
{
if(!myString)
myString=YAC_New_String();
myString->yacOperatorAssign(vo->value.string_val);
}
}
else
{
// ---- other type of YAC_Object
if(vo->value.object_val)
{
if(!myString)
myString=YAC_New_String();
vo->value.object_val->yacToString(myString);
}
}
}
else
setMyString(_vo);
}
//
// Declare some methods that allow to deliver their return values in pre-allocated objects
// e.g. o.testObjRet0() => myRetObj (statement, returns void)
// or o.testObjRet0() <=> myRetObj (expression, returns myRetObj)
// Note: In a script, the methods are named just "testObjRet0", "testObjRet1" !
//
YM void testObjRet0_YAC_RARG(YAC_Object *_ret42); // Returns "42" in "return argument"
YM void testObjRet1_YAC_RARG(sSI _i, YAC_Object *_ret); // Returns _i in "return argument"
//
// These methods are used when the testObjRet*() methods are called without the =>, <=> operator.
// Note: The method signatures must be the same as the testObjRet*_YAC_RARG methods except for the
// last argument which is YAC_Value* instead of YAC_Object* !
//
YM void testObjRet0_YAC_RVAL(YAC_Value *_r); // Returns new Integer object (int. value= 42)
YM void testObjRet1_YAC_RVAL(sSI _i, YAC_Value *_r); // Returns new Integer object (int.value = _i)
//
// Declare a method variant to be used when =>* is used.
// Note: If no dedicated RSELF variant is present, a fallback to RARG is used.
//
YM void testObjRet1_YAC_RSELF(sSI _i); // Returns _i in "self"
};
// ----
// ---- Example for a class that supports pooling
// ----
YC class MyPooledClass : public MyClass {
public:
YAC_POOLED(MyPooledClass, YAC_POOL_PRIORITY_MEDIUM);
};
// ----
// ---- the YF define is used to export global "C" functions
// ----
YF void YAC_CALL Say_Hello(void);
YF void YAC_CALL _Say_Hello2(void);
YF void YAC_CALL printMyVector(MyVector *_v) {
yac_host->printf("printMyVector: (%f, %f, %f)\n", _v->x, _v->y, _v->z);
}
YF sF32 YAC_CALL Fun_ReturnF(sF32 _a, sF32 _b) {
return _a*_a+_b*_b;
}
YF sSI YAC_CALL Fun_ReturnI(sSI _a, sSI _b) {
return _a+_b;
}
YF sSI YAC_CALL Fun_ReturnI_CPP(void) {
sSI r=1;
sUI i;
for(i=0; i<1000000; i++)
{
r=r+Fun_ReturnI(r, r);
r=r+Fun_ReturnI(r, r);
r=r+Fun_ReturnI(r, r);
r=r+Fun_ReturnI(r, r);
r=r+Fun_ReturnI(r, r);
r=r+Fun_ReturnI(r, r);
r=r+Fun_ReturnI(r, r);
r=r+Fun_ReturnI(r, r);
r=r+Fun_ReturnI(r, r);
r=r+Fun_ReturnI(r, r);
}
return r;
}
YF sF32 YAC_CALL Fun_ReturnF_CPP(void) {
sUI i;
float f=1.1f;
for(i=0; i<1000000; i++)
{
f=f+Fun_ReturnF(f, f);
f=f+Fun_ReturnF(f, f);
f=f+Fun_ReturnF(f, f);
f=f+Fun_ReturnF(f, f);
f=f+Fun_ReturnF(f, f);
f=f+Fun_ReturnF(f, f);
f=f+Fun_ReturnF(f, f);
f=f+Fun_ReturnF(f, f);
f=f+Fun_ReturnF(f, f);
f=f+Fun_ReturnF(f, f);
}
return f;
}
// ----
// ---- if the string "YAC_Value *_r" appears within the declaration of an exported
// ---- function, the interface generator will interpret it as a "variable-return-type" function
// ----
YF void YAC_CALL Fun_ReturnNewMyClass(YAC_Value *_r);
YF void YAC_CALL _TestVarRetMangled(YAC_Object *_o, YAC_Value *_r);
/** Raise a segmentation fault on purpose.
*
*
*/
YF void YAC_CALL RaiseSegV(void);
// Raises InvalidPointer error/exception
YF void YAC_CALL Raise_InvalidPointer(void);
//
// Declare some functions that allow to deliver their return values in pre-allocated objects
// e.g. TestObjRet0() => myRetObj (statement, returns void)
// or TestObjRet0() <=> myRetObj (expression, returns myRetObj)
// Note: In a script, the functions are named just "TestObjRet0", "TestObjRet1" !
//
YF void YAC_CALL TestObjRet0_YAC_RARG(YAC_Object *_ret42); // Returns "42" in "return argument"
YF void YAC_CALL TestObjRet1_YAC_RARG(int _i, YAC_Object *_ret); // Returns _i in "return argument"
//
// These functions are used when the TestObjRet*() functions are called without the =>, <=> operator.
// Note: The function signatures must be the same as the TestObjRet*_YAC_RARG functions except for the
// last argument which is YAC_Value* instead of YAC_Object* !
//
YF void YAC_CALL TestObjRet0_YAC_RVAL(YAC_Value *_r); // Returns new Integer object (int. value= 42)
YF void YAC_CALL TestObjRet1_YAC_RVAL(int _i, YAC_Value *_r); // Returns new Integer object (int.value = _i)
#endif // __TEST_H__