DLL Strategies and Packages

DLLs can be used either to write strategies in other languages than C, or to extend Zorro's C language with external packages. Zorro supports 3 types of script files in the Strategy folder: C code (.c), compiled C code (.x), and DLLs (.dll). These file types automatically appear in the Script scrollbox. Strategy DLLs can be written in any language that supports dynamic link libraries, such as C++, C#, Java, Pascal, or Delphi. The recommended language is C++ due to its speed and simplicity of use. A developer kit for Visual C++ is included.

The Visual Studio™ Community Edition is a powerful development suite that can be freely downloaded from Microsoft™. Writing a strategy in C++ has several advantages. All the tools of Visual Studio can be used, such as the debugger and profiler. External function libraries, such as Boost, can be directly integrated without the need to write a wrapper DLL. VC++ has a good code optimizer and produces code that runs about 20% faster than compiled lite-C. The only disadvantage is that you need to install and set up a large software package, and the DLL code is not automatically compiled at start, which requires an additional step in the development and test process.

The syntax of a strategy in C++ is the same as in lite-C. Functions and system variables can be used in (almost) the same way. Here's the C++ DLL version of Workshop 4:

#include "zorro.h"

DLLFUNC void run()
{
  vars Price = series(price(0));
  vars Trend = series(LowPass(Price,500));
  
  Stop = 4*ATR(100);
  
  vars MMI_Raw = series(MMI(Price,300));
  vars MMI_Smooth = series(LowPass(MMI_Raw,500));
  
  if(falling(MMI_Smooth)) {
    if(valley(Trend))
      enterLong();
    else if(peak(Trend))
      enterShort();
  }
  
  set(LOGFILE);
  PlotWidth = 800;
  PlotHeight1 = 300;
}
    

Setting up VC++

The dialogs are slightly different for any VC++ version, but here's the general DLL setup for a Zorro strategy.

For convenience, a developer kit with a strategy template (MyStrategy) for VC++ 2005 and for VC++ 2017 is included in the Zorro distribution, so you can use it to start right away. It contains the strategies from the tutorial workshops. They are basically identical to their lite-C equivalents.

A more sophisticated framework for creating Zorro strategies with VC++ has been developed by a user and is available on https://github.com/xezon/zorro-dll.

When converting lite-C code to C++, please mind the following code 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 strong>0; a normal C++ compiler does not. So take care to properly initialize all variables when necessary (of course this is 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.

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 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 not yet split into a .h and .c part. It can be directly included in a single-source DLL project. Some other lite-C libraries in the include folder - for instance, contract.c, 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 - just follow the rules above.
 

Using other languages

You can write strategy DLLs in any language that supports 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, lite-C for C/C++ programmers

► latest version online