Menu

C API

Kalle

Howto: Integrate V1 Script with C/C++ API into own projects

You can integrate the V1 interpreter language with a simple C/C++ API into own applications.

Therefore download the newest development package from v1-script.net with precompiled v1.dll for Windows or libv1.so for Linux (libc >= 2.2 required) and VC++, GCC examples.

Here are 16 examples how to work with the C API. Take a look at v1.h to see all API functions.

Example 1: Hello World

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Evaluate V1 code  
  const char* code = "print ('Hello World');"; 
  v1Eval (ctx, code, strlen (code));

  v1DeleteContext (ctx);
  v1Shutdown ();  
  return 0;
}

Example 2: Calculate a value

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();
  V1Data ret = v1CreateData ();  

  // Evaluate V1 code and return a calculated value  
  const char* code = "10+22*8;";   
  v1Eval (ctx, code, strlen (code), ret);
  printf ("Return: %g\r\n", v1Number(ret));

  v1DeleteData (ret);  
  v1DeleteContext (ctx);
  v1Shutdown ();
  return 0;
}

Example 3: Execute a V1 script file

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();

  // Execute a V1 filename
  v1Execute (ctx, "example.v1", argc, argv); 

  v1Shutdown ();
  return 0;
}

Example 4: Fetch a parser error

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Evaluate V1 code with parser error  
  const char* code = "print X ('Hello World');"; 
  int retCode = v1Eval (ctx, code, strlen (code));
  if (v1Aborted (ctx))
    printf ("Aborted with: %s\r\n", (const char*) v1LastError (ctx));

  v1DeleteContext (ctx);
  v1Shutdown ();
  return 0;
}

Example 5: Exit with exit code

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Exit with exit code  
  const char* code = "exit(99);"; 
  exitCode = v1Eval (ctx, code, strlen (code));
  if (v1Exited (ctx))
    printf ("Exit Code: %i\r\n", (int) exitCode);

  v1DeleteContext (ctx);
  v1Shutdown ();
  return 0;
}

Example 6: Set own error function

#include <stdio.h>
#include "v1.h"

int myErrorFunc (const char* filename, int line, const char* text) 
{
  printf ("%s\r\n", text);
  return 0;
}

int main (int argc, char **argv) 
{  
  v1Startup ();

  // Set own error function, otherwise errors will be printed to stdout/stderr
  v1SetErrorFunction (myErrorFunc);

  v1Shutdown ();
  return 0;
}

Example 7: Working with own functions

#include <stdio.h>
#include "v1.h"


int myFunction (V1ArgList args, V1Data ret, V1Context ctx) 
{
  // Check if first parameter is set and at least a string value (also number, bool, null possible)
  if (v1Argument1NoString (args))
    return V1_RET_PARAM1|V1_RET_NUM_REQUIRED;

  // Parameter 2 is required and must be an array 
  if (v1ArgumentCount(args)<2 || v1Argument2Type (args)<V1_DATATYPE_ARRAY)
    return V1_RET_PARAM2|V1_RET_ARRAY_REQUIRED;

  // Parameter 3 is optional and must be a number value (also number, bool, null possible) 
  if (v1ArgumentCount(args)>2 && v1Argument3Type (args)>V1_DATATYPE_STR)
    return V1_RET_PARAM3|V1_RET_NUM_REQUIRED;

  // Get the arguments      
  printf ("myFunction() is called with %i arguments.\r\n", v1ArgumentCount(args));

  V1Data arg1 = v1Argument(args,0);
  printf ("First argument: %s\r\n", v1String (arg1));

  printf ("Second argument:\r\n");
  V1Data arg2 = v1Argument(args,1);
  V1Data value; const char* key;
  v1ArrayIterate (arg2);
  while (value=v1ArrayNext (arg2, &key)) {
    printf ("%s => %s\r\n", (const char*) key, (const char*) v1String (value));
  }

  if (v1ArgumentCount(args)>2) {
    V1Data arg3 = v1Argument(args,2);
    printf ("Third argument: %g\r\n", v1Number (arg3));
  }

  /*
  // Raise a warning
  v1WarnInterprete (ctx, "Raise a warning");
  */

  /*
  // Abort, you can check if interpreter is aborted by v1IsAborted (ctx)
  v1AbortInterprete (ctx, "Now abort");
  return V1_RET_ABORT;
  */

  // Set return value as string
  v1SetString (ret, "My return value");
  return 0;
}


int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Register own function and call it
  v1RegisterFunction (ctx, "myFunction", myFunction);
  const char* code = "print (myFunction ('Param 1', ['Param 2'=>'Value']));";
  v1Eval (ctx, code, strlen (code));

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Example 8: Set constants

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Set simple constants
  v1SetConstant (ctx, "MY_CONSTANT", 0, "MY STRING"); // String "MY STRING"
  v1SetConstant (ctx, "MY_CONSTANT2", 99, NULL); // Number 99

  const char* code = 
    "print (MY_CONSTANT);"\
    "print (MY_CONSTANT2);";
  v1Eval (ctx, code, strlen (code));  

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Example 9: Read and change a global variable written by V1

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Read a global variable written by V1
  const char* code = "a = time ();";
  v1Eval (ctx, code, strlen (code));
  V1Data a = v1Symbol (ctx, "a", V1_SYMBOLS_GLOBAL); // 0 = constants, 1 = global vars
  if (a) {
    printf ("a = %.13g\r\n", (double) v1Number (a));

    // Change the variable
    v1SetNumber (a, 99);
    code = "print('a is now ', a);";
    v1Eval (ctx, code, strlen (code));
  }

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Example 10: Manipulate a global array written by V1

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Manipulate a global array written by V1
  const char* code = "b = array ('key1'=>'Value 1', 'key2'=>99, 'key3'=>true); print_r (b);";
  v1Eval (ctx, code, strlen (code));

  V1Data b = v1Symbol (ctx, "b", V1_SYMBOLS_GLOBAL); // 0 = constants, 1 = global vars
  if (b) {
    // Unset key2
    v1UnsetArrayKey (b, "key2");
    printf ("b has now %u elements\r\n", v1ArraySize (b));

    // Iterate the array
    V1Data value; const char* key;
    v1ArrayIterate (b);
    while (value=v1ArrayNext (b, &key)) {
        printf ("%s => %s\r\n", (const char*) key, (const char*) v1String (value));
    }

    // Set a value in array safe:
    // Note! v1ArrayPut...() will insert/replace the complete array key/value pair
    // To change only the value of a key, first get the value with v1ArrayValue().
    // So the references to this value will be not destroyed!
    V1Data v = v1ArrayValue (b, "key1");
    if (v) {
        v1SetNumber (v, 100);
    }
    code = "print ('key1 was changed by application.'); print_r (b);";
    v1Eval (ctx, code, strlen (code));
  }

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Example 11: Call a V1 user function

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Define a V1 user function
  code = "function myUserFunc (arg1,arg2) { print ('myUserFunc() called from application with arg1=', arg1, ' and arg2=', arg2); return 'OK'; }";
  v1Eval (ctx, code, strlen (code));

  // Call the V1 function with arguments 
  V1ArgList argList = v1CreateArgList ();
  V1Data ret = v1CreateData ();
  V1Data arg1 = v1CreateData ();
  v1SetString (arg1, "Value for Argument 1");
  V1Data arg2 = v1CreateData ();
  v1SetNumber (arg2, 99);
  v1SetArgument (argList, 0, arg1);
  v1SetArgument (argList, 1, arg2);
  if (!v1CallUserFunction (ctx, "myUserFunc", argList, ret)) {
    printf ("Return value: %s\r\n", (const char*) v1String (ret));
  }
  else {
    printf ("%s\r\n", (const char*) v1LastError (ctx));
  }
  v1DeleteData (arg1); // v1DeleteData() must be called for a corresponding v1CreateData()
  v1DeleteData (arg2);
  v1DeleteData (ret);
  v1DeleteArgList (argList); // v1DeleteArgList() must be called for a corresponding v1CreateArgList()

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Example 12: Read a V1 file handle

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Create a file handle with V1 and work with it
  code = "fh = fopen ('testfile.txt', 'w+');";
  v1Eval (ctx, code, strlen (code));
  V1Data fh = v1Symbol (ctx, "fh", V1_SYMBOLS_GLOBAL); // 0 = constants, 1 = global vars

  if (fh && v1HandleType (fh)==V1_HANDLETYPE_FILE) {
    // Cast to FILE* HANDLE
    FILE* pFile = (FILE*) v1Handle (fh);
    if (pFile) {
      // Write 
      const char* buf = "Written by application";
      unsigned int size = strlen (buf);
      if (fwrite (buf, sizeof(char), size, pFile) < size) {
        printf ("Problems to write file.\r\n");
      }
    }
  }

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Example 13: Create a file and assign the file handle to a V1 variable

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Create a WIN32 file and assign file handle to V1 variable (on Linux you can assign a FILE* pointer)
  wchar_t wFilename[MAX_PATH+1];
  DWORD size = MultiByteToWideChar(CP_UTF8, 0, "testfile2.txt", -1, wFilename, MAX_PATH);
  wFilename[size]=0;

  HANDLE hFile;
  if (INVALID_HANDLE_VALUE == (hFile = CreateFileW (wFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS, NULL))) {
    printf ("Cannot create file.");
  }
  else {
    V1Data symbol = v1CreateSymbol (ctx, "fh2", V1_SYMBOLS_CONSTANT); // 0=constants, 1=global vars, 2=first running function ...
    v1SetHandle (ctx, symbol, V1_HANDLETYPE_FILE, (V1Handle) hFile); // only V1_HANDLETYPE_FILE, V1_HANDLETYPE_SOCKET allowed

    code = "fwrite (fh2, 'Written by V1'); fclose (fh2);";
    v1Eval (ctx, code, strlen (code));
    // Note! File handles will be closed also automatically in v1DeleteContext()
  } 

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Example 14: Iterate all variables of current symbol table

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Set some variables
  code = "a=1;b=2;c=['key'=>'value'];";
  v1Eval (ctx, code, strlen (code));  

  // Iterate all variables of current symbol table
  V1Data value; const char* name;
  v1SymbolIterate (ctx, v1CurrentSymbolTable (ctx));
  printf ("Max. %u symbol tables available, current symbol table is %u.\r\n", (unsigned int) v1SymbolTableCount (ctx), (unsigned int) v1CurrentSymbolTable (ctx));
  while (value=v1SymbolNext (ctx, v1CurrentSymbolTable (ctx), &name)) {
    printf ("%s => Type %i (string=\"%s\")\r\n", (const char*) name, (int) v1Type (value), (const char*) v1String (value));
  }

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Example 15: Remove a function

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Remove a function
  code = "function userFunc (x) { return sqrt(x); }; print (userFunc(16));";
  v1Eval (ctx, code, strlen (code));
  if (v1FunctionRegistered (ctx, "userFunc")) {
    v1RemoveFunction (ctx, "userFunc");
    // Redefinition will cause no error, because function was removed
    v1Eval (ctx, code, strlen (code));
  }

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Example 16: Create a constant array

#include <stdio.h>
#include "v1.h"

int main (int argc, char **argv) 
{  
  v1Startup ();
  V1Context ctx = v1CreateContext ();

  // Create a constant array
  V1Data symbol = v1CreateSymbol (ctx, "mySymbol", V1_SYMBOLS_CONSTANT); // 0=constants, 1=global vars, 2=first running function ...
  v1PutArrayString (symbol, "key1", "Value 1");
  v1PutArrayString (symbol, "key2", "Value 2");
  v1PutArrayBool (symbol, "key3", true);
  V1Data subArray = v1PutArrayArray (symbol, "subArray");   
  v1PutArrayString (subArray, "key1", "Value 1");
  v1PutArrayString (subArray, "key2", "Value 2");
  v1PutArrayBool (subArray, "key3", true);  
  V1Data subArray2 = v1PutArrayArray (symbol, "subArray2"); 
  // Push will create a vector (keys are set automatically 0,1,2 ...)
  v1PushArrayString (subArray2, "Value 1");
  v1PushArrayNumber (subArray2, 42.12);
  v1PushArrayBool (subArray2, true);

  code = "print_r (mySymbol);"; 
  v1Eval (ctx, code, strlen (code));

  // Try to overwrite constant array will cause error
  code = "mySymbol['key1']['key3']=42;"; 
  v1Eval (ctx, code, strlen (code));
  printf ("%s\r\n", (const char*) v1LastError (ctx));

  v1DeleteContext (ctx);  
  v1Shutdown ();
  return 0;
}

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.