Integration
Integration of TIScript is pretty straightforward. Let's take a look on it step by step. I will use C++ here for the sake of conciseness. C API is also available - just take a look on tiscript.h and comments inside.
Step 1. Creating the engine
|
side note:
std_stream implementation |
|
/* console io */
class std_stream: public tiscript::stream
{
virtual int get()
{ return fgetc( stdin ); }
virtual bool put(int v)
{ return fputc( v, stdout ) != EOF; }
}; |
/* include TIScript C++ API header. */ #include "tiscript.hpp"
/* Create instance of simple stream which will be used by script for its stdio, stdin, stderr */ std_stream cio;
/* Create instance of engine */ tiscript::engine tis(&cio);
At this point we have working instance of the engine in variable tis.
Step 2. Defining native classes
Native classe are classes implemented in C++ to be called from script. Native class definition is an instance of struct TIS_class_def.
/* MessageBox class - standard message box object */
TIS_class_def MessageBoxClass =
{
"MessageBox", // name of the class as it seen in script
MessageBox_methods, // list of methods
MessageBox_properties, // list of properties
MessageBox_destructor // destructor function
};
As you may see above, to define class you need to provide:
- list of method definitions - array of pairs: name/pointer to C++ functions - implementation of the method. Function with the name "this" will serve a role of constructor.
- list of property definitions - array of pairs: name/pointer to C++ functions - implementation of the property
- and C++ function - implementation of destructor. Script engine will call it during garabage collection.
Implementation of native method may look like as:
static VOID CALLBACK MessageBox_show(
HSCRIPT hse, // instance of the engine
void** p_data_slot, // instance data slot (initialized in ctor)
tiscript::value* argv, int argc, // vector of parameters of the method
tiscript::value* retval) // return value of the method
{
MessageBox_instance* pinst = (MessageBox_instance*)*p_data_slot;
if( pinst )
::MessageBoxW(NULL, pinst->message, pinst->caption , MB_OK | MB_ICONEXCLAMATION);
else // error, this is memeber function so it has to be invoked as
// this.show() or mb.show() but not as MessageBox.show();
tiscript::engine(hse).throw_error(L"member function!");
}
/* add our native class to script name space */
tis.add(&MessageBoxClass);
At this point we have initialized scripting engine with our class registered. Next is ...
Step 3. Running scripts
/* creating input stream for reading our script code */
tiscript::file_in_stream in( "c:/test.js" );
if(!in.is_valid())
{
printf( "cannot open %s\n", "c:/test.js" );
return -1;
}
/* load and execute script from the in stream. */
if(!tis.load( &in ))
return -2;
/* done */
Step 4. (optional) Calling script functions
Script execution starts immediately on load but you may want to call scripting functions from your C++ code. Never been easier, see:
/* defining array of parameters for script function */
tiscript::value argv[2] = { tiscript::value(1), // int parameter tiscript::value(L"hello") // string parameter };
/* assume that there is MyScriptFunction defined in script, let's call it then: */
tiscript::value r = tis.call(L"MyScriptFunction", argv, 2 /* argc */ );
/* in r we have result returned by MyScriptFunction, report it */
printf( "got from script:%S\n", r.get(L"?") );
Done. We have implemented all typical steps of script engine integration into C++ application.
Full source code of tis.exe - console application using TIScript is in /samples/console/tis.cpp of TIScript SDK.
|