Jump to content
Tom Next - Daytrading Community

Recommended Posts

Posted

MC8.8

 

Ich bin dabei meine Algorithmen in eine C#-DLL auszulagern und habe mir entsprechend eine Interop-DLL in C++ geschrieben, die quasi als Wrapper für die C#-DLL agiert. In MC kann ich {self} als Referenz via IEasyLanguageObject übergeben und auch in C++ verwerten, nur scheitert es an der Weitergabe an C#.

 

Die wichtigsten Punkte dazu folgend im Code. Lediglich die Übergabe von IEasyLanguageObject an C# ist so noch verkehrt. Möglicherweise ist die Lösung relativ einfach. Der MC-Support lieferte keine wirklich hilfreichen Informationen. Es wurde sogar die grundsätzliche Möglichkeit der objektorientierten Nutzung in den DLLs verneint. Ich habe dann auf das MC-Forum verwiesen, wo diesbezueglich die ersten Fragen bereits 2007 beantwortet und mit Support unterstüzt wurden. Wichtig ist die CLR-Unterstützung in der Interop-DLL. Das ist bei den Projekteigenschaften mit /clr konfiguriert.

 

// ----- C++ Interop-DLL

#include "stdafx.h"
#include "TSLib_Interop.h"
#include <comdef.h>

#import "C:\Program Files\TS Support\MultiCharts64\PLKit.dll" no_namespace

double __clrcall TestR(IEasyLanguageObject* pELObj, double _2) {
  return TS::Class1::TestR(pELObj, _2);
}

// ------ C# DLL
using PLKit;

public class Class1
{
    public static double TestR(ref IEasyLanguageObject elRef, double len)
    {
        return 2;
    }
}
Posted

Mittlerweile hat sich einiges getan. Um in C# die Schnittstelle IEasyLanguageObject zu erreichen muss man diese via QueryInterface in Erfahrung bringen. Bis auf die auskommentierte C#-Methode Calc ist die Kommunikation so praktizierbar. Die restlichen Schritte in Calc konnte ich so nicht klären. Es liessen sich auch Mittel umsetzen in der C++-Schicht bestimmte Bar-Werte auslesen und diese dann auf einfache Weise zu übertragen. Das wäre aber keine elegante Art und Weise. Ein Zugriff auf den Indikator-Kontext auf C#-Ebene ist aber mehr als wichtig, da die C#-Lib umfangreicher wird und auch zur Weiterleitung bestimmter Informationen an eine C#-GUI genutzt werden soll, quasi eine bidirektionale Verbindung von EL C#-GUI mit einem Service als Dispatcher. Der offene Knackpunkt war noch das Weiterleiten der Referenz nach C#.

 

Ein paar Gedanken weiter und ich habe mir MC.Net gezogen, ein bisschen eingelesen und meine Lib eingebunden, debugged, etc. Was mir neu war ist die Möglichkeit der License-Conversion für 199$, das Migrieren des EL-Codes ist einfacher als ich vermutet hatte und die ganze Infrastruktur, die ich mir aufbauen minimiert sich enorm.

 

Der Vollständigkeit wegen habe ich den Code komplettiert, falls also jemand aus EL heraus auf C++ oder C# zugreifen möchte:

 

// ----- Powerlanguage - Code
...
EXTERNAL: "TSLib_Interop.dll", string, "StringExample", string ;
EXTERNAL: "TSLib_Interop.dll", string, "Calc", IEasyLanguageObject, string, int ;
...
resultCalc = Calc( self, "value9", BarNumber);
Plot1(value9, "Calc", Blue);
commentary("ResultCalc: " + resultCalc + newline + "Sponsored by: " + StringExample("-Next"));


// ----- C++ TSLib_Interop.def
// This file declares the functions to be exported from this C++-Interop-DLL
// MC can call all functions exported here

LIBRARY    "TSLib_Interop"
EXPORTS
    Calc
    StringExample
    
// ----- C++ Interop-DLL
#include "stdafx.h"
#include "TSLib_Interop.h"
#include <comdef.h>

#import "C:\Program Files\TS Support\MultiCharts64\PLKit.dll" no_namespace

// ---  Two helper methods when dealing with <string> in C#-Method signature -----------

System::String^ bstr2string(const _bstr_t& _str){
    if (!_str.length())
        return System::String::Empty;
    return System::Runtime::InteropServices::Marshal::PtrToStringBSTR((System::IntPtr)(BSTR)_str);
}

const _bstr_t string2bstr(System::String^const _str){
    if (System::String::IsNullOrEmpty(_str))
        return "";
    _bstr_t _result;
    _result.Attach( (BSTR)(void*)System::Runtime::InteropServices::Marshal::StringToBSTR(_str) );
    return _result;
}

LPCSTR __stdcall Calc( IEasyLanguageObject* pEL, LPCSTR varName, int barnum )
{
   static _bstr_t s_result;

   // Example of accessing IEasyLanguageObject from within C++
   IEasyLanguageVariable *pVar = pEL->Variables[ varName ] ;
   if ( pVar ) pVar->AsDouble[0] = (double) barnum;

   // Calling C#, the ref is handled by using IntPtr
   s_result = string2bstr(TS::Class1::Calc((System::IntPtr)pEL, barnum));
   return s_result;
}

LPCSTR __stdcall StringExample(LPCSTR _input_str){
    static _bstr_t s_result;
    s_result = string2bstr(TS::Class1::StringExample(bstr2string(_input_str)));
    return s_result;
}

// ------ C# DLL
using PLKit;
using System;
using System.Runtime.InteropServices;

namespace TS
{
 public class Class1
 {

  public static string StringExample(string _1){
           return "Tom-" + _1;
  }

   public static string Calc(IntPtr elRef, double barnum)
   {
        // Bis hierher funktionieren die Aufrufe. Lediglich das Extrahieren der
        // Schnittstelle IEasyLanguageObject in C# fehlt. COM ist wirklich nicht meine Welt
        // aber so in etwa könnte es aussehen. Ich habe zwei Varianten aufgeführt, um an
        // die Schnittstelle zu gelangen. Welche davon die eigentliche ist
        // und wie das im Detail aussehen wuerde, die Frage bleibt im Raum, ist mir aber mittlerweile
        // unwichtig geworden ;)
      
        //    IEasyLanguageObject mcObj;
        //    Guid myGuid;
        //    string infoTxt = ":";

        //  Variante 1
        //    IntPtr ptr = Marshal.GetIUnknownForObject(elRef);
        //    result = Marshal.QueryInterface(ptr, ref iid, out finalIntPtr);

        //  Variante 2
        //    ptr = Marshal.GetComInterfaceForObject(elRef, typeof(IEasyLanguageObject));
        //    ... Marshal.ReadIntPtr(ptr);
        //    mcRef = (IEasyLanguageObject)Convert.ChangeType(ptr2, typeof(IEasyLanguageObject));


        //        Marshal.Release(ptr);
        //        Marshal.Release(...);

        //    return ...;
  }  
 }
}
  • Upvote 2

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...