Tuesday, April 3, 2012

Code to Export C# DLL to Metatrader

Note: updated build 600+ code can be found at Code to Export C# DLL to Metatrader Build 600+.

I worked up a simple sample C# DLL that is properly exported for use with Metatrader. I made use of the template that can be downloaded from C# Project Template for Unmanaged Exports.

C# Code for "testUMD.dll" below using R. Giesecke's template:
Code:
using System;
using System.Text;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace testUnmanagedDLL
{
   class Test
   {
 
        [DllExport("AddInteger", CallingConvention = CallingConvention.StdCall)]
        public static int AddInteger(int Value1, int Value2) {
            MessageBox.Show("Add Integers: " + Value1.ToString() + " " + Value2.ToString());
            return (Value1 + Value2);
        }

        [DllExport("AddDouble", CallingConvention = CallingConvention.StdCall)]
        public static double AddDouble(double Value1, double Value2) {
            MessageBox.Show("AddDouble: " + Value1.ToString() + " " + Value2.ToString());
            double Value3 = Value1 + Value2;
            return (Value3);
        }

        [DllExport("AddDoubleString", CallingConvention = CallingConvention.StdCall)]
        public static string AddDoubleString(double  Value1, double Value2) {
            MessageBox.Show("AddDoubleString: " + Value1.ToString() + " " + Value2.ToString());
            double Value3 = Value1 + Value2;
            return (Value3.ToString() );
        }

        [DllExport("returnString", CallingConvention = CallingConvention.StdCall)]
        public static string returnString(string Input) {
            MessageBox.Show("Received: " + Input);
            return ("SEND to MT4");
        }

        // many thanks to anonymous for the code sample below!
        [DllExport("ReturnDouble2", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
        static double ReturnDouble2() {
            return 4.5;
        }

   }


MT4 Script 'testDLL' code below: File testUMD.dll added to experts/libraries folder
Code:
#import "testUMD.dll"
   int AddInteger(int Value1, int Value2);
   double AddDouble(double Value1, double Value2);
   string AddDoubleString(double Value1, double Value2);
   string returnString(string Input);
   double ReturnDouble2(); 
#import
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//----
   Print("AddInteger: " + AddInteger(250, 750));
   double a = AddDouble(250,750);
   Print("AddDouble: " + NormalizeDouble(a,4));

   double d = StrToDouble(AddDoubleString(250, 750));
   Print("AddDoubleString: " + NormalizeDouble(d,4));
   string temp = "Send to DLL";
   string recv = returnString(temp);
   Print(recv);
   double dd = ReturnDouble2();
   Print("Returning Double from C#: " + NormalizeDouble(dd, 4));
//----
   return(0);
  }

Cursory Summary: Integer passing = success, double passing MT4 to C# = success, double passing from C# to MT4 = fail, string passing = success. I haven't experimented with arrays. Sample code written with VS 10 .NET 4.0.

If anyone knows how to successfully get doubles to pass from C# to MT4 without conversion to a string, please leave a comment!

------------
Edit: thanks for the feedback from anonymous! The code has been updated to reflect passing a double from C# to Metatrader.

By the way, you must use the 32 bit version of the DLL. The 64 bit version and the "Any CPU" version both failed with error #127 in Metatrader. This is understandable considering MT4 is a 32 bit program. 

As per g3ro's suggestion I have made available for download both the testUnamanagedDLL Visual Studio solution and the testDLL MT4 script. Download testUnmanagedDLL VS solution

Monday, April 2, 2012

Export C# DLL to Metatrader

I've recently learned several methods for exporting a C# DLL for use outside .NET and specifically to Metatrader. The first method was alluded to in the article:
Write CSharp (C#) DLL for Metatrader.

This is a template created to make things simpler.

C# Project Template for Unmanaged Exports

The template method works but you have to delete the default function and use a slightly different syntax. (see next post).

I've seen two other articles that I haven't yet had time to fully explore but that I've heard work for simplifying the export of a C# DLL.

Simple Method of DLL Export without C++/CLI

How to Automate Exporting .NET Function to Unmanaged Programs

This second article looks not too difficult and I've heard good feedback on its implementation.

Tuesday, October 18, 2011

Misc VB6 to C# Commands

Quick reference VB6 to C#

Q: How do you replicate VB6's Debug.Print in C#?
A: In C#, Add using System.Diagnostics; to the top of the project. Then it is possible to use:

   Debug.Print("debug text");
   Debug.Write("writes without adding the newline character");
   Debug.WriteLine("writes with adding the newline character");

All three methods write to the Immediate window in C# just as Debug.Print does in VB6.

----------------------------------------------------------------
Q: How do you replicate the VB6 mid$ function in C#?
   VB6: mid$("ABCDEFG12345", 7, 2)
returns "G1"

   C# Debug.Print("ABCDEFG1234".Substring(6, 2));
returns "G1"
(note how in VB6 strings the first string's (A in the string above) reference is 1, while in C# the first string's reference is 0.)
----------------------------------------------------------------
Q: How do you call a routine in C# or why do I get the error: 

Only assignment, call, increment, decrement, and new object expressions can be used as a statement


VB6: Call myRoutine or
         myRoutine

C#: myRoutine(); // you must add the () at the end of the routine in C#!

Thursday, August 18, 2011

MT4 to R Project

I stumbled upon an interesting interface written to connect Metatrader (MT4) to the R project for statistical computing. If you have an active R installation, you can access R through MT4 via the mt4R.dll. mt4R.dll was created as an interface to wrap the functions of Rterm.exe, a component of the R project that is meant to allow batch mode access to the R terminal. mt4R.dll is a wrapper for Rterm.exe that exposes the R functionality in a well documented and intuitive manner.

Metatrader is a charting package for trading forex. If you like Metatrader, you will like the R for MetaTrader project, where you can download mt4R.dll as well as sample MT4 code to interface MT4 with R. There is a discussion about R for Metatrader on Forex Factory.

I plan to use mt4R.dll to interface VB6 to R, thus saving me from having to implement my own interface. In this effort I have found partial success, though I'm still struggling with a matrix conversion issue of the original interface, and may post more on a VB6 wrapper for mt4R.dll as time goes by.

Tuesday, August 2, 2011

Write C# DLL for Metatrader (CSharp)

Those C# developers who would like to write a DLL in C# for Metatrader instead of in C++ now have a path to that end. There is a very interesting article titled "Exposing C# code to MQL5 using unmanaged exports" that I've just read. I use MT4 (MQL4) instead but the idea is still valid.

Read/skim the article and read section 2.5 onward.
Exposing C# code to MQL5 using unmanaged exports - MQL5 Articles

Read the directions, then download the Template for C# "Unmanaged Export Library" and place the zip file in the right directory (by following the directions on that page):
C# Project Template for Unmanaged Exports

Load Microsoft Visual Studio 2010 (or  Microsoft Visual C# 2010 Express) and select the "Unmanaged Export Library" template. Follow the code samples. Hope this helps somebody!

You can find sample code for creating a C# dll with the Unmanaged Export Library here  including  a download for the visual studio solution and the MT4 sample script.

Monday, August 1, 2011

How To Write a C# 2010 DLL and Call It Within VB6 - CSharp Interoperability

Interoperability in C# is a real PITA. I know because I just spent the entire day chasing down a simple example. Unfortunately the C# documentation out there is so sparse and out of date (in this area the C# language seems to have changed quite a bit pre 2010) on the subject that doing a simple task like linking a C# dll from VB6 seems next to impossible. Maybe the topic is so mind numbingly simple that only pure C# neophytes struggle with something so mundane. But there is hope at the end of this rainbow. This short tutorial will give you the code necessary to write a simple C# 2010 DLL, and link that DLL via COM in VB6.

C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;


namespace testMath
{
    public interface Math
    {
        int Multiply(int x, int y);
        int Add(int x, int y);
    }


    [ClassInterface(ClassInterfaceType.None)]
    public class Calc : Math
    {
        public int Multiply(int x, int y)
        {
            return(x * y);
        }


        public int Add(int x, int y)
        {
            return (x + y);
        }
    }
}
The public interface is what is shown in VB6 when you look at the referenced class's methods and properties. If the interface is excluded, the class shows up as not having any way to access the methods (interface-less).

The only real kicker is the [ClassInterface(ClassInterfaceType.None)] line that eliminates extraneous class interfaces, including the desired Multiply and Add functions from showing up in the interface. You can verify this by making the removing "public" from in front of the interface declaration.

However, because a public interface is declared with Multiply and Add, those interface elements show up in VB6 as if they were the actual functions, and because the class that inherits the ": Math" interface also contains the Multiply and Add functions, VB6 is none the wiser.

On the AssemblyInfo.cs page make sure you see the following line:
[assembly: ComVisible(true)]

If it is set to false, make the change. This can also be done from within the Visual Studio environment under the Project/Properties menu. Choose to "Register for COM interop" on the Build tab, and on the Application tab under Assembly Information, make sure to check that "Make assembly COM-Visible" is checked.

Note: the C# DLL was saved as testClass.dll.


VB6 code:

Option Explicit
Private o As testClass.Calc
Private Sub Form_Load()
    Set o = New testClass.Calc
    Debug.Print "testClass.Calc"
    Debug.Print o.Add(5, 10)
    Debug.Print o.Multiply(5, 5)
    Set o = Nothing
End Sub

Yes the VB6 end of the equation really is that simple. In the VB6 IDE, just add the reference to the .tlb that was created in C# under Project/References (menu) and you're good to go.

C# Books

I'm reading the following two books to learn C#.

Visual C# 2010 Step by Step by John Sharp. I usually don't like the step by step books but actually found this book an easy and clear read right from the beginning. More so than my other selection. The book is divided into sections.

Part I contains chapters 1-6 and introduces C# and Visual Studio 2010.
Part II is chapters 7-14 and is titled "Understanding the C# Language."

I'm just starting chapter 13, "Creating Interfaces and Defining Abstract Classes." The book was fairly clear up through chapter 12. I needed some more in-depth analysis of the C# language, so I started a second book.

Beginning Visual C# 2010 from Wrox press. I've read and liked other Wrox press books before and so I had high expectations for this book. Unfortunately I didn't have a good experience in the early chapters. The book is written in a very loose "conversational" style that drives me crazy. I also thought that the book started covering the wrong material, or the right material in the wrong order. This led me to start reading the "Step by Step" book above.

However, after plowing through 12 1/2 chapters of the "Step by Step" book I needed something more thorough. I came back to the Wrox book and found that if anything, this book is thorough. The chapters are longer and they don't revolve around a particular code sample as the "Step by Step" book does, but overall I found reading these books in this order to be helpful and would suggest this approach.

By working through the examples in the "Step by Step" book and manually typing in the code I was able to learn much about the Visual Studio 2010 IDE, some of the C# features and this was useful for me to be led through the samples. I find that working through a specific problem tends to help me the most, particularly when dealing in abstract concepts. It also helps if the examples are relevant to a  real-world problem, but that's asking quite a lot from books of this sort.

I'm in the middle of chapter 11, "Collections, Comparisons, and Conversions" in the Wrox book. Part I of the Wrox book covers chapters 1-14 and is titled "The C# Language." Part I in the Wrox book covers approximately the same material as in the "Step by Step" book, though with a lot more detail. Case in point, I'm on page 253 and Chapter 13 of "Step by Step" but on page 314 and chapter 11 of "Beginning Visucal C# 2010."

I wouldn't consider either as a great book but both were available at the public library.