13.1 C-scripts

 

13.1.1 Introduction

If the REBOL and batch file script engines aren't enough fast for you, you can use the C-scripts. They aren't based on a script engines because they are real C program that are compiled on-the-fly and converted in machine code. Thanks to the powerful Tiny C compiler, this step is so fast  that the user thinks to use scripts executed by an interpreter instead of source codes built by a compiler.  The C-scripts are executed inside the VEGA ZZ environment allowing to access to the same resources used by the master software. This approach allows to obtain extreme performances, but it have some risks related to the master program (VEGA ZZ) stability. For this reason, the C-scripts are executed inside an exception-trapping box that protects the VEGA ZZ main core to illegal memory accesses.
The C compiler supports the ANSI C, the ISO C99 standard and many GNU C extensions including inline assembly. For more information, see the Tiny C reference documentation.

 

13.1.2 Machine code generation

VEGA ZZ calls the Tiny C compiler to build the C source code in a dynamic link library and if an error occurs, the compiling procedure is stopped showing a message in the console. The resulting link library, called VEGA Link Library (VLL), is loaded, linked to the main VEGA process and at this step only, is executed calling the entry point using a separate thread. The main process waits the end of the execution but if the C-script performs an illegal operation, it's halted and an error message is shown. When the script is halted or it's normally terminated, the main process releases all resources. VEGA ZZ can run more then one C-script in the same time in the same environment.

 

13.1.3 Script management

The PowerNet plug-in has the job to manage the C-scripts, allowing to create, to delete, to edit, to rename and to run them as the batch and REBOL files. Selecting File -> Run script in the main menu, it's possible to perform all above operations. Please note when you want create a new C-script, clicking with the right mouse button on the Select script window and selecting New -> C-script, two templates are available: OpenGL for scripts that require the OpenGL output and Standard for all other scripts. New templates can be added coping them in the Scripts\_Templates directory.

 

13.1.4 How to create a C-script

The C-script creation is very easy: you can use the tools built-in in VEGA ZZ or an external text editor. Please remember to place the script in the Scripts directory (or in its subdirectories) because VEGA requires it for its management. If you want use the template scripts, you can follow these steps:

The standard C-script code is the following:

/*******************************************
****          VEGA ZZ C Script          ****
****         Standard  template         ****
**** (c) 2005-2007, Alessandro Pedretti ****
*******************************************/
#define VGVLL
#include <vega.h>
int VllMain(VGP_VEGAINFO *VegaInfo)
{
  /**** Put here your code ***/
  return 0;
}

A C script or a VLL must always include the vega.h header defining the VGVLL symbol. The header contains the prototypes of the functions callable inside the script. The C-script entry point is defined by the VllMain() function and without it the script can't be linked. The VllMain() function should return a non-zero value if an error occurs, otherwise zero if no error is found. To the this function is passed the address of the VGP_VEGAINFO structure defined in the vgplugin.h header:

typedef struct {
  VG_UWORD      Version;            /* VEGA version                             */
  VG_UWORD      Release;            /* VEGA release                             */
  VG_ULONG      *GlobErr;           /* Pointer to global error variable         */
  char          *ErrStr;            /* Pointer to error string                  */
  ATOMO         **BegAtm;           /* Pointer to the pointer of the atom list  */
  ATOMO         **LastAtm;          /* Pointer to the pointer to the last atom  */
  VG_ULONG      *TotalAtm;          /* Pointer to the number of atoms variable  */
  void          **SrfList;          /* Pointer to the pointer of the surface    */
                                    /* list defined by HD_LIST in hyperdrive.h  */
  char          *Result;            /* Pointer to the result string             */
  void          *AppHandle;         /* Application handle                       */
  void          *Res1;              /* Reserved pointer (don't use it !)        */
  void          *Res2;              /* Reserved pointer (don't use it !)        */
  HDC           hDC;                /* Device context                           */
  HGLRC         hRC;                /* Rendering context                        */
  HMENU         hMenu;              /* Handle of the main menu                  */
  HMENU         hPopUpMenu;         /* Handle of the popup menu                 */
  HWND          hWnd;               /* Handle of the main window                */
  char          IniFile[MAX_PATH];  /* Plugin .ini file with full path          */
  char          PrgPath[MAX_PATH];  /* Program path \ terminated                */
  /**** Super API ****/
  void          (*VegaCmd)(const char *);       /* Send a command               */
  void          (*Free)(void *);                /* Free the memory              */
  void *        (*Malloc)(unsigned int);        /* Alloc the memory             */
  VG_ULONG      (*ChoosePixelFormat)(void *Dc, int *PixelFormat, int Multisample, int Stereo);
                                                /* Choose the pixel format      */
  void *        (*AW_InitAlphaWin)(HWND);       /* Initialize the alpha blend   */
  void          (*AW_FadeOut)(HWND);            /* Fade out the window          */
  void          (*WaitCalc)(void);              /* Wait the calculation end     */
} VGP_VEGAINFO;

The Super API section could be expanded in the next releases and it allows to access directly to the VEGA ZZ functions. The C-script must read only this structure (write operations aren't allowed).

The C scripts are linked to the startup code (see Tcc\src\Vgcrt2 and Tcc\Lib directories) including the functions to control the extended commands. They can used ad in the REBOL scripts and in the batch files, but they must be called using a C wrapper:

 

int VegaCmd(const char *Com)
Send an extended command to VEGA ZZ main process and wait the execution end. The function returns the error code (0 if no error occurs) and the command output, if available,  is copied in the Result character pointer of the VGP_VEGAINFO structure.

Example:

char	CurPath[256];
VegaCmd("Get CurDir");                // Send the Get command to VEGA ZZ
strcpy(CurPath, VegaInfo -> Result);  // Copy the result in the user defined variable
 

int VegaCmdEx(const char *Com, ...)
This is the extended version of the VegaCmd() function. It accepts the format specifiers as the the printf() standard function combining a series of arguments.

Example:

VegaCmdEx("GraphAdd %d %f", Item, Value);

 

int VegaGetRes(char *Buf, const int Size)
Copy the results of a previous extended command into a character variable. This is a more secure method to obtain the results of a command when the size of the output is unknown. The input parameters are the character variable (Buf) accepting the result and its size (Size). The output is the length of the result. If the Buf size it too short, the output is truncated.

Example:

char		Result[128];
unsigned int	Atoms;
VegaCmd("Get TotAtm");		// Send the Get command to VEGA ZZ 
VegaGetRes(Result, 128);	// Obtain the result
Atoms = atoi(Result);		// Convert it from character to integer

 

A C-script can read and write directly the atoms: please take care because no check are done if wrong data are inserted in the atom list. This is an example:

#include <stdio.h>
#define VGVLL
#include <vega.h>
/**** Write the X, Y, Z coordinates of each atom ****/
int VllMain(VGP_VEGAINFO *VegaInfo)
{
  ATOMO     *Atm;
  FILE      *FH;
  /**** Check if a molecule is loaded ****/
  if (!*(VegaInfo -> BegAtm)) return 0;
  /**** Show a message in the console ****/
  VegaCmd("Text \"* Saving the XYZ coordinates\" 1");
  /**** Open the output file ****/
  if ((FH = fopen("C:\\xyz.txt", "w")) == NULL) return 0;
  /**** Atom loop ****/
  for(Atm = *(VegaInfo -> BegAtm); Atm; Atm = Atm -> Ptr) {
    fprintf(FH, "%f %f %f\n", Atm -> x, Atm -> y, Atm -> z);
  } /* End of for (Atm) */
  /**** Close the file handle ****/
  fclose(FH);
  return 0;
}

 

13.1.4 How to build a VEGA Link Library

The VEGA Link Library (VLL) is a C-script compiled by Tiny C. It's in the middle between a script and a plug-in: it's already in binary format and the compiling and linking phases aren't required to run it. By this way, the VLL is started much faster than a C-script but it can't edited in the VEGA ZZ environment. The use of a VLL is recommended if you have a complex and very large C-script that requires 2 or more seconds to start it. To build a VLL you must follow these steps:

 

13.1.4 The super APIs

The super APIs are real VEGA ZZ functions remapped into the plug-in layer. They are declared in the vgplugin.h in the VEGA ZZ\Tcc\include directory and in the plugins.h file of the plug-in SDK. They can be called using the address of the VGP_VEGAINFO structure (e.g. VegaInfo -> WaitCalc()).

void AW_InitAlphaWin(HWND hWnd)
Initialize the alpha channel use for the specified window handle (hWnd). This is an interface to the AwLib library linked to VEGA ZZ that allows the creation of transparent windows with fade-in and fade-out effects. This function doesn't have any effect if the glass windows are disabled (see Preferences dialog window).

void AW_FadeOut(HWND hWnd)
Force the fade-out effect of the specified window (hWnd). This effect doesn't work if the glass windows aren't enabled in the Preferences control panel. This function should be called before closing the window. Please remember to initialize the window calling AW_InitAlphaWin with the appropriate window handle.

VG_ULONG ChoosePixelFormat(void *Dc, int *PixelFormat, int Multisample, int Stereo)
This function replace the standard ChoosePixelFormat() provided by Windows APIs to choose the pixel format for the OpenGL rendering context. The required arguments are the device context (Dc); the pointer of the pixel format variable (PixelFormat); the ARB multisample anti-aliasing value (Multisample) that could be 0 (no anti-aliasing), 2 (2x), 4 (4x), 6 (6x), etc; the hardware stereo mode (Stereo), that could be 0 (disabled) or 1 (enabled). Not all graphic cards implement the stereo hardware and so it's possible that it can work. The the anti-alias mode currently enabled in VEGA ZZ is available getting the value of the MSAA system variable (see GET command).
The function returns zero if it fails, and in PixeFormat the requested pixel format that will be used to create the OpenGL rendering context.

void Free(void *Mem)
Free a memory segment (Mem), previously allocated by Malloc().

void *Malloc(unsigned int Size)
Allocate an uninitialized memory segment of specified size (Size). If you want allocate memory blocks (e.g. atoms, surfaces, etc) that will be managed directly by VEGA ZZ, you must use this function only and not the equivalent malloc() function provided by the standard C library, because it's incompatible with the memory manager embedded in VEGA ZZ.

void VegaCmd(const char *Com)
It's the same function used in the C-scripts. For more details, see above.

void WaitCalc(void)
Wait the end of a calculation (e.g. AMMP, Mopac, etc). It's strongly recommended the use of this function instead of the periodical check of the ISRUNNING system variables, because it uses the kernel events and don't loose the CPU performances.