How to convert C/C++ code to lite-C

Lite-C supports a syntax subset of the C/C++ language. In most cases - when no particular C++ features, like STL, are used - a C/C++ programm can be easily converted to lite-C. Examples for this are the DirectX samples that come with the lite-C installation; they are just slightly modified versions of the original samples from the DirectX 9 SDK. For converting a C/C++ program to lite-C, the following modifications are required:

Trinary operators

Lite-C does not support the comparison ? expression : expression; syntax, so an if statement must be used:
x = (x<0 ? -1 : 1); // C/C++
if (x<0) x=-1; else x=1;  // lite-C 

Struct and array initialization

In C/C++ arrays structs can be initialized by giving a list of member values, like VECTOR myvector = { 0,0,0 };. This is only supported for global structs and arrays in lite-C. Local structs can not be initialized, and local initialized arrays automatically become static. Lite-C initializes all global arrays and structs automatically to zero; local arrays and structs are normally not initialized and thus contain random content. Thus, use the zero() macro (defined in acknex.h) for initalizing local structs to zero, and vec_zero() for initializing vectors consisting of 3 vars:
VECTOR speed;
...

vec_zero(speed);	// initializes the VECTOR "speed" to x=0,y=0,z=0

For migration and testing, lite-C can automatically initialize also all local variables to zero with the PRAGMA_ZERO definition. If you add

#define PRAGMA_ZERO   // initialize variables

at the beginning of your script, all uninitialized local variables and structs are set to zero. This slows down function calls a little, so it's preferable not to to use PRAGMA_ZERO in your final version.

Enums

Enums can be replaced by defines:
enum RGB { RED=1; BLUE=2; GREEN=3 }; // C/C++

#define RED 1 // lite-C #define BLUE 2 #define GREEN 3

Unions

Union members of the same type can be substituted by a #define, and union members of different type can be treated as a different members of the struct. Example:
typedef struct S_UNION { 
   int data1;
   union { int data2; float data3; };
   union { int data4; int data5; };
} S_UNION; // C/C++

typedef struct S_UNION { int data1; int data2; float data3; int data4; } S_UNION; // lite-C #define data5 data4

If the struct size must not change, or if for some reason the program requires different variable types to occupy the same place in the struct, a special conversion function can be used to convert the type of a variable without converting the content:

typedef struct S_UNION { 
   int data1;
   union { int data2; float data3; };

} S_UNION; // C/C++
...
S_UNION s_union;
s_union.data3 = 3.14;

typedef struct S_UNION { int data1; int data2; } S_UNION; // lite-C #define data3 data2 ... int union_int_float(float x) { return *((int*)&x); } ... S_UNION s_union; s_union.data3 = union_int_float(3.14);

Function pointers

In C/C++, function pointers are declared like this: int (*foo)(int a, int b);. In lite-C there's no difference between function prototypes and function pointers: int foo(int a, int b);. See details under pointers.

Signed or unsigned variables

In lite-C, floating point, long and int variables are generally signed, and pointers, char and short are generally unsigned, according to the normal way they are used. The include\litec.h file contains definitions for all usual unsigned variables like DWORD or WORD that are used in Windows functions. So using unsigned variables normally does not cause any problems. However you need to take care when variables exceed their range. For instance, subtracting 1 from (DWORD)0 results in -1 under lite-C, but in 0xFFFFFFFF in standard C/C++, and would produce different behavior in comparisons.

Adding C library functions

Lite-C contains only a subset of all functions from the standard C/C++ libraries, but you can add any function that you need as described under Using the Windows API. Here's a brief instruction of how to add a API function to lite-C:

If you need certain structs or variable types that are not yet contained in include\windows.h or in the other standard include files, just add them from their original file either into your script. If you think that a certain function, struct, or variable type is often needed, suggest its inclusion into api.def on the Gamestudio future forum rather than modifying api.def yourself. Self-modified files are overwritten by lite-C updates.

Adding DirectX API functions

DirectX and other Windows SDKs use the Component Object Model (COM) as described in the API chapter. For convenience, the Windows interface definitions (like DECLARE_INTERFACE_ and STDMETHOD_) are already contained in the lite-C include\d3d9.h file, and the basic classes are already defined within. So it'is easy to add further interface classes when they are needed. Just copy the class definition from the original d3d9.h or other DirectX header file into it's lite-C counterpart, and add the inherited methods (if any) from the parent class.

Compiling a lite-C script with other C++ compilers

As long as you don't use any special lite-C syntax, like global struct initialization or pointer autodetection, you can normally compile a lite-C legacy mode script with any other C++ compiler. Here's an example how to compile the mandelbrot_legacy.c file with Visual Studio 2003:

See also:

Pointers, Structs, Functions, Windows API