Native object interfaces
sgs_ObjInterface object_iface[1] =
{{
"object_name", // type name
NULL, NULL, // destruct, gcmark
NULL, NULL, // getindex, setindex
NULL, NULL, NULL, NULL, // convert, serialize, dump, getnext
NULL, NULL // call, expr
}};- This is the minimal object interface definition. It defines the name and implements no callbacks.
- The slightly unusual syntax is actually a definition of an interface array with one element.
- This effectively creates a pointer to interface, which is the only way the interface is requested by any API function.
- Interface must be accessible until there's at least one object using it. It can usually be defined as a global/static variable.
sgs_CreateObject( C, NULL, malloc( sizeof( mystruct ) ), object_iface ); sgs_CreateObjectIPA( C, NULL, sizeof( mystruct ), object_iface ); // preferred method
- There are two ways to create objects. Pointer to external data / in-place allocation.
- First way simply means that a data pointer is set to whatever value you want.
- Second way sets the data pointer to memory space followed by internal data, for which the internal data allocation is extended by the specified number of bytes.
- The in-place allocated block does not need to be freed explicity.
- This generally requires one less allocation to be performed.
It is very important that all memory operations on in-place allocated blocks do not, at any time, operate beyond the boundaries of those blocks. Be especially wary of putting arrays at the beginning of a structure since accidentally applying negative indices to such arrays could create issues that are extremely hard to debug.
int object_destruct( SGS_CTX, sgs_VarObj* obj )
{
free( obj->data );
return SGS_SUCCESS;
}- This is a very basic object destruction callback. It simply assumes that the data pointer was malloc'ed and frees it.
- All callbacks return
intand have the same first two arguments (sgs_Context*andsgs_VarObj*). - In all callbacks, negative return values are error codes and non-negative (>= 0) imply success.
int object_getindex( SGS_CTX, sgs_VarObj* obj )
{
char* str;
if( sgs_ParseString( C, 0, &str, NULL ) )
{
if( strcmp( str, "data_pointer" ) == 0 ) return sgs_PushPtr( C, obj->data );
if( strcmp( str, "do_something" ) == 0 ) return sgs_PushCFunc( C, object_do_something );
if( strcmp( str, "do_smth_else" ) == 0 ) return sgs_PushCFunc( C, object_do_smth_else );
}
return SGS_ENOTFND; // return that the specified key was not found in object
}
// a slightly cleaner but less hands-on, the macro-based version:
int object_getindex( SGS_ARGS_GETINDEXFUNC )
{
SGS_BEGIN_INDEXFUNC
SGS_CASE( "data_pointer" ) return sgs_PushPtr( C, obj->data );
SGS_CASE( "do_something" ) return sgs_PushCFunc( C, object_do_something );
SGS_CASE( "do_smth_else" ) return sgs_PushCFunc( C, object_do_smth_else );
SGS_END_INDEXFUNC
}- This is a very basic index/property reading callback.
- On request for key
data_pointer, it returns pointer to allocated memory. - On requests for the other two keys, it returns the associated methods.
- On request for key
- Both presented versions are practically interchangeable.
- This error code (SGS_ENOTFND), coming from this callback, has a specific behavior: it may trigger a 'property/index not found' warning.
- It is NOT recommended to return SGS_SUCCESS and send the warning manually because return code is passed back to API functions.
