Data Definition

SC is based on types defined in the host application , even built in types are created in this way. It has a very flexible mechanism based on macros and templates to do that.

Below there are described only some common cases, see the macros list for specific information (macros). Most of the code snippets are taken from the examples provided with the SDK.


Namespaces

A namespace is used to organize data. All non member data is contained by some namespace. You can export variables, functions and types to a namespace (also other namespaces). It will be visible in all namespaces below. Scripts are also created in some namespace. There exists one root namespace (global namespace). Everything defined in this namespace is visible in all scripts.



//function exported to script
void SCSTDCALL Print(Int i)
{
   printf("%d\n", i);
};

void main()
{
   ...
   InitalizeSC();
   ...
   //g_SCEnv is an object achieved with SCInit call
   ISCType *gns = g_SCEnv->GetGlobalNamespace(); //get global namespace    
      
   //register s1ns namespace in the global namespace
   ISCType *scriptNS = SC_NAMESPACE(gns, "s1ns");
   if(!scriptNS)
      return SCTestError("script namespace initialization error", -1);
   ...
}

Simple types

Types may be defined in any namespace. There are provided some basic types (see built in types docs - built in types). You can also define your own:


void main()
{
   ...
   InitalizeSC();
   ...
   //g_SCEnv is object achieved with SCInit call
   ISCType *gns = g_SCEnv->GetGlobalNamespace(); 
   ISCType *TByte = SC_SIMPLE_TYPE(gns, Byte);
   if(TByte == NULL)
      return SCTestError("type export error", -1);
   ...
}

Simple types may have defined operators.

Classes

Classes are surely the most common data exported to SC. You can export public attributes, methods, constructors, operators, keep class relations. The example below shows how to export a base class (see also ex_classeexport example) "Soldier" and its attribute, a method and a parametrized constructor. Note the form of InitSoldier function. The first argument must be a reference to the object, the rest must be the same like in the constructor. The return type must be a reference to the object. Use SC_CONSTRUCTOR_BODY macro to genereate the body.

A default constructor, copy constructor, destructor and assignent operator for non constant arguments are exported when the class is declared, so don't define it again - an error occur


class Soldier
{
public:
	Int health;
	
	Soldier(Int h)
	{
		health = h;		
	}

	Soldier()
	{
		health = 100;		
	}
	
	virtual void Hit(Int damage)
	{
		health -= damage;		
	}

	virtual ~Soldier()
	{		
	}
};

Soldier& SCSTDCALL InitSoldier(Soldier &s, Int h)
{
	SC_CONSTRUCTOR_BODY(Soldier, s, (h) );
}

void main()
{
   ...
   InitalizeSC();
   ...
   //g_SCEnv is object achieved with SCInit call
   ISCType *gns = g_SCEnv->GetGlobalNamespace(); 
   ISCType *tSoldier = SC_BASE_CLASS(gns, Soldier);
   if(!SC_ATTRIBUTE(tSoldier, Soldier, Int, health) ||				
      !SC_CONSTRUCTOR(tSoldier, Soldier, InitSoldier, (Soldier *s, Int h)) || 		
      !SC_METHOD(tSoldier, Soldier, void, Hit, (Int damage)))
      return SCTestError("type export error", -1);
   ...
}

Functions

An exported function may be global or the method of some class, but must be STDCALL (or THISCALL). C++ functions are callable in SC in the same way like in C++ code and vice versa. You can export a function with the following code:



//function exported to script
void SCSTDCALL Print(Int i)
{
   printf("%d\n", i);
};

void main()
{
   ...
   InitalizeSC();
   ...
   //g_SCEnv is object achieved with SCInit call
   ISCType *gns = g_SCEnv->GetGlobalNamespace(); 
   if(!SC_FUNCTION(gns, void, Print, (Int v)))
      return SCTestError("Print registering error", -1);
   ...
}

Variables

You can export variables to some namespace. The variable must have constant address while using in SC. Such a variable is visible in all scripts that the namespace is superior to.

   ...
   //g_SCEnv is object achieved with SCInit call
   Int extInt = 10;
   ISCType *gns = g_SCEnv->GetGlobalNamespace();
   
   ISCSymbol *extIntSym = SC_VARIABLE(gns, Int, extInt);    

Function Pointers

SC allow to define function pointers , Though they are not the same as C++ function pointers, their behaviour is similar. Having a SC function pointer you can call any function that match the type of the pointer. To use some function pointer in SC or on C++ side you must define the type first.

The first step is to define C++ type by typedef keyword.


typedef void (SCSTDCALL* TFuncVoidInt)(Int x);

Next you must register the function pointer type by using SC_FUNC_PTR_TYPE macro. After that you can use this type is SC code.


	ISCType *tTFuncVoidInt = SC_FUNC_PTR_TYPE(globalNS, void, TFuncVoidInt, (Int x));
	if(!tTFuncVoidInt)
		  return SCTestError("tTFuncVoidInt export error", -1);

Then you can define a variable in C++ code to hold the SC function pointer. It is treated as a typical variable both on C++ and SC side.


void TestFunc(Int x)
{

}

  ...

  TSCFuncPtr<TFuncVoidInt> funcPtrVoidInt;	
  funcPtrVoidInt = TestFunc;
  funcPtrVoidInt(10); //calls TestFunc
  ...
  funcPtrVoidInt = SC_NULL; //sets pointer to NULL

On SC side you can use TFuncVoidInt type like in the example below.


void SCTestFunc(Int x)
{

}

   ...

   TFuncVoidInt   funcPtrVoidInt;	
   scFuncPtrVoidInt = SCTestFunc;
   scFuncPtrVoidInt(10); //calls SCTestFunc
   ...
   scFuncPtrVoidInt = NULL; //sets pointer to NULL

You can also call functions defined in SC code from C++ code by SC function pointers. There are two ways to do that. You can simply export variable and in the script assign to the pointer some function like in the example above. The other way is to use SC_GET_FUNC_PTR macro. It returns a function defined in the script. The call executes the function from the script.

   TSCFuncPtr scFunc = SC_GET_FUNC_PTR(script, TFuncVoidInt, "SCTestFunc");  
   scFunc(10); //calls 	SCTestFunc

Aliases

Aliases may be defined as global. They will be visible in any script (PCStr is a built in example). You can do that with RegisterGlobalAlias function:

   ...
   if(!g_SCEnv->RegisterGlobalAlias("PCStr", "const Char*"))
      return SCTestError("alias export error", -1);
   ...