Strategy development with Visual Studio™

Zorro supports three types of strategy files in the Strategy folder: C code (.c), lite-C executables (.x), and DLLs (.dll). These 3 file types automatically appear in the Script scrollbox. The free Zorro version can run all strategy types, but only create strategies in .c code. You need Zorro S for compiling .c strategies to .x executables or for developing .dll strategies. Any language that can generate a Win32 DLL can be used, such as C#, Java, Pascal, Delphi, Basic, and of course C++.

For developing strategies in lite-C you need no further tools; the process is described in the tutorial. For developing strategy DLLs in other languages you'll need an external development system. We recommend Visual Studio™ Community Edition. It is a powerful development suite that can be freely downloaded from Microsoft™. Writing a strategy as a VC++ DLL has several advantages over lite-C. All tools of Visual Studio can be used, especially the debugger and profiler. External function libraries, such as Boost, can be directly integrated without the need to write a wrapper. VC++ has an excellent code optimizer and produces code that runs about 20% faster than lite-C. The disadvantages are that the project must be set up as decribed below before you can start coding, and the DLL must be manually compiled after every code change, which requires an additional step in the development process.

DLLs can be used not only for for developing strategies, but also for extending Zorro's C language with external packages. The code syntax in VC++ is the same as in lite-C, and almost all functions and system variables can be used in the same way. But additionally you have all object oriented language features of C++ at your disposal.

Setting up VC++

The dialogs and setup procedures shown below are slightly different for any VC++ version. Here's it for the latest (Oct 2018) version of the Visual C++ 2017 Community Edition:

The file MyStrategy.cpp in the Source folder contains VC++ versions of Workshops 6..8, the RTest script, and the DeepLearn script. Which one to compile can be selected with a #define at the begin. Check it out for learning the differences of writing a strategy in VC++ instead of lite-C. All known code differences are listed below. If you encounter any other incompatility with a function or variable, please report on the user forum or to Zorro support. An alternative framework for creating Zorro strategies with VC++ has been developed by a user and is available on https://github.com/xezon/zorro-dll.

Migrating a lite-C script to VC++

Lite-C contains 'abbreviations' to make code shorter and less complex. Most of them, but not all, work also with 'real' C++. When converting a lite-C strategy to C++, please mind the following subtle differences (see also lite-C for C/C++ programmers):

No variable initialization

The lite-C compiler initializes all global and local variables and arrays to 0; a normal C++ compiler does not. This means they have random content at start. So take care to properly initialize all variables when necessary (normally also recommended in lite-C code!):
var MyArray[10];  // lite-C; automatically initialized to zero
var MyArray[10] = { 0,0,0,0,0,0,0,0,0,0 }; // C++

Early comparison abort

In lite-C, the order of expressions in a comparison plays no role. In C/C++, comparisons with && or || are order sensitive. The comparison is aborted when a && is encountered and the expression so far evaluated to false, or when a || is encountered and the expression evaluated to true. This can cause a different behavior when the comparison contains function calls:
if(test(x) && test(y)) .. // lite-C always calls test(x) and test(y)
if(test(x) && test(y)) .. // C++ calls test(y) dependent on what's returned by test(x)

Exported and void functions

If functions do not return something, define them with void. A function defined with function must return an int. If functions are exported by the DLL - such as run, main, objective, etc - define them also with the DLLFUNC macro:
function run() { ... } // lite-C
DLLFUNC void run() { ... } // C++

No parameter skipping

In lite-C, function parameters can often be omitted when they are 0. For this purpose, the lite-C compiler offers a variable that contains the number of parameters. This variable is not available in C++, so default parameters must be explicitely defined. The zorro.h include file has such definitions for most functions with multiple parameters, but not for single-parameter functions.
var Close = priceClose();  // lite-C
var Close = priceClose(0); // C++

Different string type

In lite-C, strings can be compared with string constants using the normal comparison operators, such as ==, !=, or switch...case. In the C++ DLL headers, a string is typedef'd as a char* pointer, and comparison with a constant would always result in false. Either use C++ types like CString or basic_string for string handling (but make sure to call lite-C functions always with C-style, null-terminated strings), or use the str... functions from the C library.
if(Algo == "TRND") ... // lite-C
if(0 == strcmp(Algo,"TRND")) ... // C++

Different bool type

In lite-C, bool has a size of 4 bytes, in C++ it's 1 byte. The lite-C bool type is equivalent to the Win32 BOOL type. For avoiding confusion, you might prefer to use int instead of bool / BOOL.

No watch() and printf() statements

Zorro's single-step debugger can still be used with a DLL, but the watch statement can not. Also, printf() is now a C library function that prints to the standard output stream and not to the Zorro window and log file. Use print(TO_WINDOW,...) instead.
printf("\nHello World!") // lite-C
print(TO_WINDOW,"\nHello World!") // C++

Using DLL functions

In lite-C, the API macro imports functions from a DLL library. In C/C++, use the LoadLibrary and GetProcAddress standard functions for that:
int __stdcall MyDLLFunction(double a,double b);
API(MyDLL,MyDLLFunction) // lite-C
int (__stdcall *MyDLLFunction)(double a,double b);
HMODULE DllHandle = LoadLibrary("MyDLL");  // C/C++
if(DllHandle) {
   *(FARPROC*)&MyDLLFunction = GetProcAddress(DllHandle,"MyDLLFunction");
   ...
}
...
if(DllHandle) FreeLibrary(DllHandle);

Lite-C Libraries

The r.h bridge library has been adapted to C++, but contains function bodies, so it can be included in a single-source DLL project, but not in multiple sources. Some other lite-C libraries in the include folder - for instance, profile.c - have not yet been adapted to C++. Adaption of all lite-C libraries is planned for future Zorro updates, but if you need them earlier, go ahead and do it yourself - by following the rules above. If you find something C++ incompatible with an existing library, or encounter difficulties with the adaption, please post on the user forum or contact Support.
 

Using other languages

You can write strategy DLLs in any language that supports 32-bit dynamic link libraries. In that case you must adapt the headers to the used language, and also adapt the ZorroDLL.cpp. Aside from the DLL entry point that is unused, it contains a zorro() function that is called upon strategy start, and receives a pointer to the GLOBALS struct. The GLOBALS struct is defined in trading.h. It is a singleton with all predefined variables and functions. Its Functions pointer leads to a list of 32-bit addresses of the functions in the same order as listed in functions.h. The functions must be called with __cdecl calling convention.

When importing the GLOBALS struct, set up the compiler so that it does not pad structs with dummy elements for aligning the struct members. If available, set the struct alignment to 4 bytes or below. This is needed to ensure that the structs have identical size in your DLL and in Zorro.  

See also:

API, llite-C for C/C++ programmers, migrating from other platforms

► latest version online