Working With the API

Parent Previous Next

Working With the API.

The API functionality is categorized as:


Identity Information.

This functionality provides information about the DLL:



// Pascal:

function CompilerVersion() : int32;


// C/C++:

int CompilerVersion_cdecl();



This function is not really related to the other functions - it simply returns a 32 bit integer value for the required version of the compiler. It can be a good idea to check the value once the DLL is loaded before invoking the other functions, because the built-in execution engine of the DLL can only execute bytecode that was generated by a compiler with the same version number. Otherwise errors or unexpected behavior may occur.


Multi-Threading.

This functionality is used to setup, how the DLL handles multiple threads accessing the API functions simultaneously:



// Pascal:

function MultiThreadMode(mode : int32) : TBoolInt;


// C/C++:

TBoolInt MultiThreadMode_cdecl(int mode);



The parameter mode can define these three scenarios:

Mode

DLL MultiThread Setup

-1

Not thread-safe, but execution may be slightly faster. Only for single thread activity.
If multiple threads are using the API functions, the DLL may crash at random.

0

Thread-safe execution where multiple threads may invoke the API functions simultaneously.
Provides the fastest parallel execution with the fewest restrictions.

1

Gatekeeper restricted access to one API function at a time. Multiple threads may invoke the API functions, but only one thread at a time is allowed to enter and execute an API function from start to finish without being interrupted by the other waiting threads.


The default startup scenario of the DLL is mode=0 for fully multi-threaded unrestricted access to all API functions.


When using mode=1 the DLL can become a bottleneck performance wise, but it may provide an easy solution in case shared resources are used.


You'll find more tips and warnings in Using Multiple Threads.


PLEASE NOTICE:

This functionality should only be used before multiple threads are created and started. If the mode is changed, while the DLL is being used by other threads, unexpected behavior may occur including lockups or crashes, which may require the host process to be restarted.


Error Handling.

These functions are used to handle error situations in order to present an error message of the last registered error:



// Pascal:

function LastErrorGetStringLength(codePage : int32; var len : int32) : TBoolInt;

function LastErrorGetString(codePage, len : int32; textbytes : PByte) : TBoolInt;


// C/C++:

TBoolInt LastErrorGetStringLength_cdecl(int codePage, int& len);

TBoolInt LastErrorGetString_cdecl(int codePage, int len, unsigned char* textbytes);



To get the error message, the host application must do this:

1.

Get the length of the error message. The length (the number of bytes) depends on the codepage preferred by the host. Use LastErrorGetStringLength to get a len value based on the specified codepage.

2.

Create a byte-array with the required number of allocated bytes.

3.

Pass the byte-array to get the bytes for the string. Use LastErrorGetString with the codepage, len and a pointer to the byte-array. The VM DLL will then copy the bytes to the passed byte-array.

4.

Finally the host can encode the updated bytes into a string.


Please note: Do not invoke any other functions, as they may clear or overwrite the last error.


VM Management.

These functions are used to create, execute, garbage collect and free VMs. You can also provide a callback function for a VM.



// Pascal:

function VMCreate(codePage, len : int32; asmByteCode : PByte; var vm : int32) : TBoolInt;

function VMFree(vm : int32) : TBoolInt;

function VMSetCallback(vm : int32; callBack : TCallBack) : TBoolInt;

function VMGC(vm : int32; gcMainClass : TBoolInt) : TBoolInt;

function VMExecute(vm, x, y, z : int32; var returnValue : int32) : TBoolInt;


// C/C++:

TBoolInt VMCreate_cdecl(int codePage, int len, unsigned char* asmByteCode, int& vm);

TBoolInt VMFree_cdecl(int vm);

TBoolInt VMSetCallback_cdecl(int vm, int (*callBack)(int,int,int));

TBoolInt VMGC_cdecl(int vm, TBoolInt gcMainClass);

TBoolInt VMExecute_cdecl(int vm, int x, int y, int z, int& returnValue);



These API functions provide a functionality which are very closely related to the internal library functions

@VMCreate, @VMFree, @CallBack, @VMGC, @VMExecute.


You are strongly encouraged to familiarize yourself with these functions and also read about The Life and Death of a VM.


Please note:


Managing Cells.

These API functions are used to work with the cells of an instantiated VM:



// Pascal:

function VMClearCells(vm : int32) : TBoolInt;

function VMCellIsInteger(vm, row, col : int32; var returnValue : TBoolInt) : TBoolInt;

function VMCellIsBytes(vm, row, col : int32; var returnValue : TBoolInt) : TBoolInt;

function VMCellIsString(vm, row, col : int32; var returnValue : TBoolInt) : TBoolInt;

function VMCellGetInteger(vm, row, col : int32; var returnValue : int32) : TBoolInt;

function VMCellGetBytesLength(vm, row, col : int32; var len : int32) : TBoolInt;

function VMCellGetBytes(vm, row, col, len : int32; bytes : PByte) : TBoolInt;

function VMCellGetStringLength(vm, row, col, codePage : int32; var len : int32) : TBoolInt;

function VMCellGetString(vm, row, col, codePage, len : int32; textbytes : PByte) : TBoolInt;

function VMCellSetInteger(vm, row, col, value : int32) : TBoolInt;

function VMCellSetBytes(vm, row, col, len : int32; bytes : PByte) : TBoolInt;

function VMCellSetString(vm, row, col, codePage, len : int32; textbytes : PByte) : TBoolInt;


// C/C++:

TBoolInt VMClearCells_cdecl(int vm);

TBoolInt VMCellIsInteger_cdecl(int vm, int row, int col, TBoolInt& returnValue);

TBoolInt VMCellIsBytes_cdecl(int vm, int row, int col, TBoolInt& returnValue);

TBoolInt VMCellIsString_cdecl(int vm, int row, int col, TBoolInt& returnValue);

TBoolInt VMCellGetInteger_cdecl(int vm, int row, int col, int& returnValue);

TBoolInt VMCellGetBytesLength_cdecl(int vm, int row, int col, int& len);

TBoolInt VMCellGetBytes_cdecl(int vm, int row, int col, int len, unsigned char* bytes);

TBoolInt VMCellGetStringLength_cdecl(int vm, int row, int col, int codePage, int& len);

TBoolInt VMCellGetString_cdecl(int vm, int row, int col, int codePage, int len, unsigned char* textbytes);

TBoolInt VMCellSetInteger_cdecl(int vm, int row, int col, int value);

TBoolInt VMCellSetBytes_cdecl(int vm, int row, int col, int len, unsigned char* bytes);

TBoolInt VMCellSetString_cdecl(int vm, int row, int col, int codePage, int len, unsigned char* textbytes);



They provide functionality which are analog to the internal library functions

@VMClearCells,

@VMCellIsInteger, @VMCellIsBytes, @VMCellIsString,

@VMCellGetInteger, @VMCellGetBytes, @CellGetString,

@VMCellSetInteger, @VMCellSetBytes, @VMCellSetString.


Using the API functions or the internal library functions both require the same precautions - taking care not to request values from cells that are not storing the requested value type, or else exceptions are thrown.