SGScript/C++ binding compiler

Table of Contents


SGS/CPP-BC description

This is a compiler that will generate most of the binding code from a bit of markup and additional build configuration. Statistically, the gain is approximately 80% less code to write to connect your C++ code to SGScript.

The compiler can be found at "ext/cppbc/cppbc.sgs".

Arguments:

This is a basic example of how things are done with SGS/CPP-BC:

struct UIFrame
{
	typedef sgsHandle< UIFrame > Handle;
	
	SGS_OBJECT;
	
	UIFrame();
	
	SGS_METHOD void event( UIEvent* e );
	SGS_METHOD void render();
	
	SGS_METHOD void doMouseMove( float x, float y );
	SGS_METHOD void doMouseButton( int btn, bool down );
	SGS_METHOD void doKeyPress( int key, bool down );
	
	SGS_IFUNC(GCMARK) int sgs_gcmark( SGS_CTX, sgs_VarObj* obj, int );
	
	SGS_PROPERTY float x;
	SGS_PROPERTY float y;
	SGS_PROPERTY float width;
	SGS_PROPERTY float height;
    SGS_PROPERTY sgsString name;
	SGS_PROPERTY sgsHandle< UIControl > root;
	
	float prevMouseX;
	float prevMouseY;
};

The SGS_OBJECT tag marks the structs/classes that need to have the binding code. SGS_METHOD would then mark methods that require exporting and SGS_PROPERTY generates property exports. For read-only/write-only properties, all you'd need to add is "READ" or "WRITE" after the tag.

sgsVariable and sgsHandle are classes that are used to store SGScript objects. Handles are for storing exported object pointers and variables are for everything. Handles make it easier to use the included objects, thus they are preferred to plain variable containers.

GCMARK handlers are more like the raw API but all that needs to be done in the function is calling gcmark() on each variable or handle. Due to the possibility of having many unknown kinds of containers of variables, it is unlikely that this function could ever be automatically generated, except for the most primitive of cases.


Common usage patterns

declare a variable and bind it

SGS_PROPERTY float x;

bind an inherited variable

SGS_PROPERTY SGS_ALIAS( float x );

bind & declare variable with post-write callback

SGS_PROPERTY_FUNC( READ WRITE WRITE_CALLBACK myWriteCallback ) float x;

bind a fake variable (based on get/set functions)

SGS_PROPERTY_FUNC( READ getX WRITE setX ) SGS_ALIAS( float x );

bind & declare a variable with two different names

SGS_PROPERTY_FUNC( READ WRITE VARNAME sgsName ) float x;

bind an inherited/previously defined variable

SGS_PROPERTY_FUNC( READ WRITE VARNAME sgsName ) SGS_ALIAS( float x );

bind a related, potentially unsafe variable

SGS_PROPERTY_FUNC( READ WRITE VALIDATE parent SOURCE parent->name ) SGS_ALIAS( sgsString parentName );

declare a method and bind it

SGS_METHOD float calc( float x );

declare a differently named method

SGS_METHOD_NAMED( func ) void sgsFunc( int i );

declare a coroutine-aware method

// ctx is passed automatically, does not affect argument count/order
SGS_METHOD void coroAware( sgs_Context* coroCtx, float arg0 );
// SGS_CTX works too, but may trigger a warning about variable shadowing

declare a vararg method with variable return value count

SGS_METHOD SGS_MULTRET complexFunc();

handle class stub

typedef sgsHandle< struct sgsObj > sgsObjHandle;
struct sgsObj
{
    SGS_OBJECT;
    
    static sgsObjHandle HandleFromPtr( Obj* ); // resolve the link through object's user data pointer or some similar method
    
    sgsObj( Obj* obj ) : m_obj( obj ){}
    ~sgsObj(){ cleanup(); }
    void cleanup() // this is pulled out of constructor in case it might be called by a parent object to invalidate the handle on destruction of the owning system
    {
        if( m_obj )
        {
            // *** free m_obj ***
            m_obj = NULL;
        }
    }
    Obj* m_obj;
    
    // declare additional properties and methods with SGS_PROPERTY(_FUNC) and SGS_METHOD, respectively
    // most properties/methods will most likely have to include a NULL test for m_obj, like this:
    int _getProp(){ return m_obj ? m_obj->GetProp() : 0; }
    void _setProp( int v ){ if( m_obj ) m_obj->SetProp( v ); }
    SGS_PROPERTY_FUNC( READ _getProp WRITE _setProp ) SGS_ALIAS( int prop );
};

data struct stub

struct sgsData : Data
{
    SGS_OBJECT_LITE;
    
    sgsData(){}
    sgsData( const Data& t ) : Data( t ){}
    
    // properties with direct access (non-private)
    SGS_PROPERTY SGS_ALIAS( item1 );
    
    // data struct properties (original type: SubData, wrapped type: sgsSubData)
    sgsSubData _getSubData(){ return subData; }
    void _setSubData( const sgsSubData& sd ){ subData = sd; }
    SGS_PROPERTY_FUNC( READ _getSubData WRITE _setSubData ) SGS_ALIAS( sgsSubData subData );
    
    // properties with method access
    int _getProp(){ return GetProp(); }
    void _setProp( int v ){ SetProp( v ); }
    SGS_PROPERTY_FUNC( READ _getProp WRITE _setProp ) SGS_ALIAS( int prop );
    
    // aliases (second names) for all properties:
    SGS_PROPERTY_FUNC( READ WRITE VARNAME item1alt ) SGS_ALIAS( bool item1 );
    SGS_PROPERTY_FUNC( READ _getSubData WRITE _setSubData VARNAME subDataAlt ) SGS_ALIAS( sgsSubData subData );
    SGS_PROPERTY_FUNC( READ _getProp WRITE _setProp VARNAME propAlt ) SGS_ALIAS( int prop );
};
SGS_DEFAULT_LITE_OBJECT_INTERFACE( sgsData ); // this line can be replaced with a modified combo of sgs_PushVar/sgs_GetVar declarations

Tags

SGS_OBJECT

SGS_OBJECT_LITE

SGS_OBJECT_INHERIT

Marks the objects/structures for parsing.

SGS_OBJECT_LITE does not add helper variables (sgs_VarObj* m_sgsObject; sgs_Context* C) to the class

SGS_OBJECT_INHERIT specifies class or classes to inherit definitions from

SGS_NO_EXPORT

SGS_NO_DESTRUCT

Object binding modifiers.

SGS_METHOD

Marks the methods that should be made available to the scripting engine.

Syntax: SGS_METHOD <type> <name>(<arguments>)

Alt. syntax (bind without declaration): SGS_METHOD SGS_ALIAS( <type> <name>(<arguments>) );

SGS_METHOD_NAMED

Marks the renamed methods that should be made available to the scripting engine.

Syntax: SGS_METHOD_NAMED( <sgsname> ) <type> <realname>(<arguments>)

See SGS_METHOD for more info.

SGS_STATICMETHOD

Marks the static methods that should be made available to the scripting engine.

Syntax: SGS_STATICMETHOD <type> <name>(<arguments>)

Alt. syntax (bind without declaration): SGS_STATICMETHOD SGS_ALIAS( <type> <name>(<arguments>) );

SGS_STATICMETHOD_NAMED

Marks the renamed methods that should be made available to the scripting engine.

Syntax: SGS_STATICMETHOD_NAMED( <sgsname> ) <type> <realname>(<arguments>)

See SGS_STATICMETHOD for more info.

SGS_PROPERTY

Marks the properties that should be made available to the scripting engine. Currently supports only one property at a time.

Syntax: SGS_PROPERTY [READ|WRITE] <type> <name>;

Alt. syntax (bind without declaration): SGS_PROPERTY [READ|WRITE] SGS_ALIAS( <type> <name> );

Modifiers:

SGS_PROPERTY_FUNC

Marks the properties that should be made available to the scripting engine. Has additional options for reading, writing and callbacks.

Syntax: SGS_PROPERTY_FUNC( <tag-args> ) <type> <name>;

Alt. syntax (bind without declaration): SGS_PROPERTY_FUNC( <tag-args> ) SGS_ALIAS( <type> <name> );

Tag arguments: a space separated list of none or more of the following constructs

SGS_IFUNC

Marks the method as a native object interface function that would override any generated one.

Syntax: SGS_IFUNC( <ifunc-type> ) <type> <name>( sgs_Context*, sgs_VarObj*, int );

"ifunc-type" must be one of object interface function defines (destruct, getindex, expr etc.).

SGS_GCREF

Marks objects to be marked for garbage collection.

Syntax: SGS_GCREF( <var1> <var2> ... )

SGS_DUMP

Marks member variables as available for dumping.

Syntax: SGS_DUMP( <var1> <var2> ... )

All readable properties are dumped by default, this is used to specify variables that are not already specified as readable properties.

To prevent certain properties from being dumped, see SGS_NODUMP

SGS_NODUMP

Marks readable properties as unavailable for dumping.

Syntax: SGS_NODUMP( <var1> <var2> ... )

All readable properties are dumped by default, this is used to disable that for certain variables.

SGS_BACKING_STORE

Marks a variable to be used as backing store (read from and write to it if a property/index-related action doesn't match any of this object's properties).

Syntax SGS_BACKING_STORE( (READ|WRITE) <var> )

* var should be sgsVariable. * It is not automatically initialized - to enable the system, it should be initialized to an object with free write capabilities (like dict/map)


Data type handling

template< class T > void sgs_PushVar( SGS_CTX, const T& );

Pushes the specified variable on the stack, automatically converting it to the most appropriate SGScript type.

template< class T > struct sgs_GetVar { T operator () ( SGS_CTX, int item ); };

template< class T > struct sgs_GetVarObj { T* operator () ( SGS_CTX, int item ); };

Takes the specified stack item and converts it to the required type.


Helper classes & functions

Classes

Functions


sgsScope [class]

class sgsScope

This is the class used to minimally save/restore stack state (its size).

If stack is popped too far, it is not restorable.

Variables

Constructors

Methods


sgsMaybe [class]

template< class T > class sgsMaybe

This is the class used for handling nullable values.

Variables

Constructors

Methods


sgsArrayIterator [class]

template< class OwningClass > class sgsArrayIterator

This is an array access iterator class for the owning class that supports array indexing and size retrieval. The owning class needs to have these specific access points:

Variables

Constructors

Methods


sgsHandle [class]

template< class T > class sgsHandle

This is the class used for handling SGS_OBJECT classes.

Variables

Constructors

Methods

Operators


sgsString [class]

class sgsString

This is the string interface and handling class.

Variables

Constructors

Methods

Operators


sgsVariable [class]

class sgsVariable

This is the class used for handling all SGScript variables.

Variables

Constructors

Methods

Operators


sgs_Create(Lite)Class [function]

template< class T > void sgs_CreateClass( sgs_Context* C, sgs_Variable* out, T* inst )

template< class T > void sgs_CreateLiteClass( sgs_Context* C, sgs_Variable* out, T* inst )

Push a new instance of the class on stack.

This function should not be used with existing instances, as it would make more than one SGScript object responsible for the same data. Use sgs_CreateVar or sgs_Create(Lite)ClassFrom with existing instances.


sgs_Create(Lite)ClassIPA [function]

template< class T > T* sgs_CreateClassIPA( sgs_Context* C, sgs_Variable* out )

template< class T > T* sgs_CreateLiteClassIPA( sgs_Context* C, sgs_Variable* out )

Allocate a new class instance in-place.


sgs_Create(Lite)ClassFrom [function]

template< class T > T* sgs_CreateClassFrom( sgs_Context* C, sgs_Variable* out, T* inst )

template< class T > T* sgs_CreateLiteClassFrom( sgs_Context* C, sgs_Variable* out, const T* inst )

Create a new instance by copying inst.


sgs_InitCreatedClass [function]

template< class T> T* sgs_InitCreatedClass( T* inst, sgs_Context* C )

Set context / object pointers to class.


SGS_CREATE(LITE)CLASS [function alias]

SGS_CREATECLASS( sgs_Context* C, sgs_Variable* out, class_name, ctor_args )

SGS_CREATELITECLASS( sgs_Context* C, sgs_Variable* out, class_name, ctor_args )

Create a new instance of the specified class, using the specified arguments for constructor.

Usage example:

SGS_CREATECLASS( C, NULL, myClass, ( param1, 5.0f ) );

sgs_GetClassInterface [function]

template< class T > sgsVariable sgs_GetClassInterface( SGS_CTX )

Get or create the class interface object.


sgsEnv [function]

sgsVariable sgsEnv( SGS_CTX )

Retrieve the global environment.

Wrapper of sgs_GetEnv C API function.


sgsRegistry [function]

sgsVariable sgsRegistry( SGS_CTX )

Retrieve the registry.

Wrapper of sgs_Registry C API function with argument SGS_REG_ROOT.


sgsSymbols [function]

sgsVariable sgsSymbols( SGS_CTX )

Retrieve the symbols section of registry.

Wrapper of sgs_Registry C API function with argument SGS_REG_SYM.