13.1 C-scripts
13.1.1 Introduction
If 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 programs 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 from 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 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
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 main menu,
you can perform all above
operations. When you want create a new C-script, right-clicking the Select script window and selecting New
C-script, two multiple templates are available. New templates can be added
coping them to ...\VEGA ZZ\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. Remember to place the script in the Scripts directory (or in its subdirectories). If you want to use template scripts, you can follow these steps:
Open the script selection window (File
Run script).
Explore the directory tree in order to find the preferred place in which to put the script.
Click a directory by the right mouse
button and select New
C script
Template name
(e.g. Standard). New.c file is created.
Rename it, clicking on it by the right mouse button and selecting Rename (e.g. my_script.c).
Edit it by the built-in mini editor, using the context menu and selecting Edit.
The standard C-script code is the following:
/******************************************* **** VEGA ZZ C Script **** **** Standard template **** **** (c) 2005-2013, 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. This function receives the address of the VGP_VEGAINFO structure defined in 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 as in the REBOL scripts and in the batch files, but they must be called using the 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 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 you can't edited it. The use of a VLL is recommended if you have a complex and very large C-scripts that requires 2 or more seconds to start it. To build a VLL you must follow these steps:
Open the VEGA ZZ console (Start
VEGA ZZ
VEGA Console).
Change the current directory to the folder containing the C-script file.
In the console type:
tcc -shared [VEGA_PATH]\tcc\lib\vgcrt2.voj my_script.c -o my_script.vll
where [VEGA_PATH] is the VEGA ZZ installation path, my_script.c
is the file name of the C-script and my_script.vll is the file
name of the output VLL.
To run the VLL, you must copy it to VEGA ZZ\Scripts directory tree. When you run VEGA ZZ,
it's automatically recognized by PowerNet plug-in
and using the script selection tool (File
Run script) is
possible to run it.
13.1.4 The super APIs
The super APIs are real VEGA ZZ functions remapped into the plug-in layer. They are declared in vgplugin.h that is palced in VEGA ZZ\Tcc\include directory and in 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 the requested
pixel format (PixeFormat ) 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 to 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 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 polling of ISRUNNING system
variables, because it uses the kernel events and doesn't loose the CPU
performances.