Abstract
This article will explain how to create a wrapper for a .NET DLL and import it in MetaTrader 4. I used Visual Studio 2005 and wrote the example .NET DLL in C# and the wrapper in C++. The wrapper is again a DLL, which implements the Stdcall calling convention (MetaTrader 4 supports only this convention but you can produce a DLL with any calling convention as long as .NET supports it). The .NET DLL can be easily written in any other .NET language. The technique described below can be used to export .NET DLLs to be used by any unmanaged applications.
Motivation
When I decided to create an expert advisor for MetaTrader to test a trading strategy, I was frustrated because of many unsuccessful attempts to find out how to create DLLs and import them in the expert advisor. I am coming from a Java background and a year and a half of programming in C#. I have a slight knowledge of C++ and feel like I am crippled when I have to write something in it. Because of that, my first decision was to implement the trading strategy in C#. I spent days trying to figure out how, but my nerves couldn’t stand it, so I gave it all up and switched to Visual C++ 6.0. When I realized how quickly I am in writing C++ code, I began having second thoughts and started trying in .NET again. After days of trial and error, I came up with the following step-by-step guide.
Step-by-Step Guide for Creating a Sample DLL
I. Creating the C# DLL
- Create a new C# class library project called CSharpAssembly in a new solution named DotNetDllForMetaTrader4.
- Add the following C# class file to the project:
- Change the CSharpAssembly project -> Properties -> Build -> Output path field to “..debug“. You do this to dump all the output to one folder.
This step should be completed after adding CppStdcallInerfaceWrapper project to the solution because this will automatically change the solution platform from Any CPU to Mixed Platforms.
CSharpClass.cs:
using System;
using System.Collections.Generic;
using System.Text;namespace CSharpAssembly
{
public class CSharpClass
{
public static byte[] Hello(byte[] name)
{
string s = “, hello from .NET!”;
byte[] helloPart = Encoding.ASCII.GetBytes(s);
byte[] whole =
new byte[name.Length + helloPart.Length];
int i = 0;
foreach (byte b in name)
{
whole[i++] = b;
}
foreach (byte b in helloPart)
{
whole[i++] = b;
}
return whole;
}
}
}
II. Creating the C++ Wrapper, Implementing the Stdcall Calling Convention
- Add to the solution a new C++ Win32 project called CppStdcallInerfaceWrapper with application type DLL.
- Change the CppStdcallInerfaceWrapper.cpp file content to:
#include “stdafx.h”#ifdef _MANAGED
#pragma managed(push, off)
#endif#ifdef _MANAGED
#pragma managed(pop)
#endif#using “CSharpAssembly.dll”
using namespace CSharpAssembly;__declspec(dllexport) char* __stdcall Hello(char* name)
{
int i = 0;
while (*name != ‘