Definition of the links between Scol language and DLL functions

This article shows the possibility to add new functions to Scol language using the integration of plugins written in C language.

Creation of a simple function "HelloWorld"

We will create our first C function which we will be able to call from Scol language.
This function will allow to display a log message ("Hello World") in the Scol console.
The first thing to do right here is to write the C function. It's important to take a look at the function signature, because it takes a machine object as a parameter and returns an integer (this integer should be 0 on success and something else on failure -- the scol machine will stop on failure).

It's also important to notice MMechostr function from the Scol API. This method takes as parameters the log level (MSKFOO, MSKRUNTIME, MSKWARNING, MSKTRACE or MSKDEBUG) and the message to log.

Finally, we have to notice MMset function which purpose is to set a value for the first element of Scol stack (in our case, an integer which value is 0), this one corresponding to the return value of the Scol function, accordingly to the expected Scol prototype (fun [ ] I, a function without any parameter and returning an integer).

 /*! @ingroup group1
  * \brief _HelloWorld : Log a "Hello World" message in the console
  *
  * <b>Prototype:</b> fun [] I
  *
  * \return I : 0 in all cases.
  **/
 int _HelloWorld(mmachine m)
 {
     // Show the message
     MMechostr(MSKRUNTIME, "Hello World!");

     // Scol return value.
     MMset(m,0,0);

     return 0;
 }

Binding between C and Scol

To be able to call the function HelloWorld directly from Scol language, we have to register it. The function from the Scol API enabling it is PKhardpak.

 /*!
  * \brief Load the template functions
  *
  * \param mmachine : scol machine structure
  *
  * \return int : 0 if succes, error code otherwise
  **/
 int LoadTemplate(mmachine m)
 {
     int k;

     // Load package
     k = PKhardpak(m, "TemplateEngine", NbTplPKG, TplName, TplFunc, TplNArg, TplType);
     return k;
 }

The parameters of the function are the following :
  • NbTplPKG : the number of functions we have to export to Scol (the different arrays described below must have as many values as this number)
  • TplName : an array containing the name of the functions as they will be called in a Scol source code
  • TplFunc : an array of pointers to C functions, corresponding to the bindings of Scol functions to their equivalent in C language
  • TplNArg : an array of integers representing the number of arguments expected for each function
  • TplType : an array of strings containing the Scol prototypes for each function

WARNING : If several functions are being exported, we have to make sure that for all the arrays, the functions are in the same order.

Now, we can inject the following source code just before calling PKhardpak. A good habit is to use the same name for the Scol function and for the C function because is simplifies the edition of the documentation and the revision of the source code.

 //! Nb of Scol functions or types
 #define NbTplPKG    1

 /*!
  * Scol function names
  **/
 char* TplName[NbTplPKG] =
 {
     "_HelloWorld" 
 };

 /*!
  * Pointers to C functions that manipulate the VM for each scol function previously defined
  **/
 int (*TplFunc[NbTplPKG])(mmachine m)=
 {
     _HelloWorld
 };

 /*!
  * Nb of arguments of each scol function
  **/
 int TplNArg[NbTplPKG]=
 {
     0
 };

 /*!
  * Prototypes of the scol functions
  **/
 char* TplType[NbTplPKG]=
 {
     "fun [] I"          // _HelloWorld
 };

To finish the binding of the C function, all we need to do is to call the function named LoadTemplate when the plugin is being initialized, that is to say in SCOLloadTemplate function. The content of this one should now be the following :

 /*! 
  * \brief Starting point of the DLL
  **/
 extern "C" __declspec (dllexport) 
 int SCOLloadTemplate(mmachine m, cbmachine w)
 {
    SCOLinitplugin(w);
    // Get Scol window handle (for message callback)
    HScol = (HWND)SCgetExtra("hscol");

    // Display debug message
    MMechostr(MSKDEBUG,"Loading Template DLL ...\n");    
    return LoadTemplate(m);
 }

After that, it's now possible to compile the project and move the DLL file into the plugins directory of the Scol Voyager installation folder, which is usually C:\Program Files (x86)\Scol Voyager.

Use of the new function in Scol language

We will now create a new Scol source code, in which we will call our function previously created.
Let's create a new file called template.pkg in the Scol Voyager user partition, which is usually located in My Documents\Scol Voyager\Partition_LocalUsr. The file will only contain a main function calling our HelloWorld method :

 /*! \brief Sample main function that log a "Hello World" message.
  *
  *  <b>Prototype:</b> fun [] I
  *
  *  \return I : 0
  **/
 fun main()=
   _HelloWorld;;

Let's create another file in our user partition, named HelloWorld.scol. This program will load the package template.pkg that we have just created, and run its main function :

 _load "template.pkg" 
 main

Now, we can run the program HelloWorld.scol and notice that the log message we've defined in the C function is displayed in Scol console.