• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 843
  • Last Modified:

Tradestation and Dll

I want to use C# to Get the Global Variables from the third party program Tradestation and process the data.
Declaration inTS is :

external:  "GlobalVariable.dll", int, "GV_GetInteger", int ;
external:  "GlobalVariable.dll", int, "GV_SetInteger", int, int ;
this GlobalVar.Dll is written in C++ ,but far behind my experience - so the question is if this is possible at all?  (the GlobalVar. is only working in realtime)
0
JojoR
Asked:
JojoR
  • 14
  • 11
1 Solution
 
Meir RivkinFull stack Software EngineerCommented:
try this:

[DllImport(@"c:\<full-path>\GlobalVariable.dll")]
   private static int GV_GetInteger(int a);

[DllImport(@"c:\<full-path>\GlobalVariable.dll")]
   private static int GV_SetInteger(int a, int b);

Open in new window

0
 
Meir RivkinFull stack Software EngineerCommented:
now, once u set the full path of the dll, you can simply call the function from your managed code:

class Program
{
  [DllImport(@"c:\<full-path>\GlobalVariable.dll")]
   private static int GV_GetInteger(int a);

[DllImport(@"c:\<full-path>\GlobalVariable.dll")]
   private static int GV_SetInteger(int a, int b);

   static void Main(string[] args)
   {
       Console.WriteLine(GV_GetInteger(3));
       Console.WriteLine(GV_SetInteger(3,4));
   }
}

Open in new window

0
 
JojoRAuthor Commented:
thank you for answering.I'm not very good in programming so I miss the first part -
Try this ......
Do I have to build a extra class first of this part?

If I open a new console project only with your code class programm , then some references might missing , but I cannot add a reference to the GlobalVariable .
If I add using  System.Runtime.InteropServices; then error "ConsoleApplication.1.Program.GV_GetInteger(int)" is not declared abstract, extern or partial
and has to daclare text (my translation)
what do I miss?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Meir RivkinFull stack Software EngineerCommented:
add extern keyword:

class Program
{
  [DllImport(@"c:\<full-path>\GlobalVariable.dll")]
   private static extern int GV_GetInteger(int a);

[DllImport(@"c:\<full-path>\GlobalVariable.dll")]
   private static extern int GV_SetInteger(int a, int b);

   static void Main(string[] args)
   {
       Console.WriteLine(GV_GetInteger(3));
       Console.WriteLine(GV_SetInteger(3,4));
   }
}

Open in new window

0
 
Meir RivkinFull stack Software EngineerCommented:
you need to add the reference System.Runtime.InteropServices.
0
 
JojoRAuthor Commented:
I've added using System.Runtime.InteropServices;now compiles without errors ,but then get:
Bad image format exeption HRESULT: 0x8007000B
make shure assembly is valid and path is correct
0
 
Meir RivkinFull stack Software EngineerCommented:
try this:

class Program
{
  [DllImport(@"c:\<full-path>\GlobalVariable.dll",CallingConvention=CallingConvention.Cdecl)]
   private static extern int GV_GetInteger(int a);

[DllImport(@"c:\<full-path>\GlobalVariable.dll",CallingConvention=CallingConvention.Cdecl)]
   private static extern int GV_SetInteger(int a, int b);

   static void Main(string[] args)
   {
       Console.WriteLine(GV_GetInteger(3));
       Console.WriteLine(GV_SetInteger(3,4));
   }
}

Open in new window

0
 
Meir RivkinFull stack Software EngineerCommented:
an alternative is using win32api loadlibrary to dynamically load your dll:
    class Program
    {
        [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
        static extern int LoadLibrary(
            [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);

        [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
        static extern IntPtr GetProcAddress(int hModule,
            [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

        [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
        static extern bool FreeLibrary(int hModule);

        //declare delegates to convert pointer functions
        delegate int D_GV_GetInteger(int b);
        delegate int D_GV_SetInteger(int a, int b);

        static void Main(string[] args)
        {
            //load dll
            int hModule = LoadLibrary(@"c:\dlls\GlobalVariable.dll");
            if (hModule == 0) return;
            IntPtr intPtrGetInteger = GetProcAddress(hModule, "GV_GetInteger");
            IntPtr intPtrSetInteger = GetProcAddress(hModule, "GV_SetInteger");

            D_GV_GetInteger GV_GetInteger = (D_GV_GetInteger)Marshal.GetDelegateForFunctionPointer(intPtrGetInteger, typeof(D_GV_GetInteger));
            Console.WriteLine(GV_GetInteger(3));

            D_GV_SetInteger GV_SetInteger = (D_GV_SetInteger)Marshal.GetDelegateForFunctionPointer(intPtrSetInteger, typeof(D_GV_SetInteger));
            Console.WriteLine(GV_SetInteger(3, 4));
        }
    }

Open in new window

0
 
JojoRAuthor Commented:
Hello
First thank you for your efforts and assistance - we are getting closer.
Your first suggestion using calling convention leads to the same result as before:Bad image format exeption.Your second seemes to be better - no exeption thrown,compiling.
But then strange is that I added Console.ReadLine() after ConsoleWriteLine and it disappeares anyway - so I can not prove ,if there is a correct result .
0
 
Meir RivkinFull stack Software EngineerCommented:
Can u debug your code and see if the function returns something?
0
 
JojoRAuthor Commented:
sorry my fault I forget to set the proper path to the dll , to fast. it works so far:
I get 3 for  the location( adress or whatever don't no how to describe exactly) the global var stores the values, but not the value itself.
I attach a description
Global-Variable-2.3.doc
0
 
Meir RivkinFull stack Software EngineerCommented:
did you manage to call the functions of your dll successfully?
are you saying you are not satisfy with the function result?
i don't understand what's the doc u attached go to do with the question.
0
 
JojoRAuthor Commented:
Sorry for confusing - I try to clear.The GV_Set has two parameters ,GV_Get only one.As far I understand ,the first par.stands for the location (pointer?), where the value (any variable) is stored (the second par).
If I call GV_Get(3) ,I receive the value(4) which is stored(in location 3) by a calculation made in Tradestation already - fetch it and process for further calcs in C#. ( then maybe sending it back or display in another form or sth.like this)
What I get now on the console is  " 3 " , so works perfect this far - but I need the values (4) ofcourse - which should deliver the ongoing realtime values running.
0
 
Meir RivkinFull stack Software EngineerCommented:
what i meant by in my question is, whether the problem you are facing is technical or logical/business problem by the nature of the function.

it seems that the function doesn't do what it suppose to do, right?
if that is the matter than i can't really help you without having the code of the dll.

secondly, your initial question was how can you load the assembly and call the get/set functions from C# code, which i answered.
0
 
JojoRAuthor Commented:
I appreciate your efforts, ofcourse. Due to my limitations I try my best to explain , where the problem is. I attach the code.
Have problems with allowed extensions.renamed def to txt.I hope these two files are right.
GV23Code.cpp
GV23Def.txt
0
 
Meir RivkinFull stack Software EngineerCommented:
sorry, i don't understand what is not working for you.
0
 
JojoRAuthor Commented:
In Tradestation I make calculations in one chart -> store result in GV_Set global var->  I can get (inside TS in another chart i.e.) these results - if I call GV_Get ,process the variables values further,display them etc.
What I wanted to achieve is to get these results(variables) which I set in Tradestation to ->
external application C# to process the data incoming in realtime.
what is working now is to get the location number where the Global Variable stores these results - but I need the values which are stored in this location, not only the location itself.

I hope this is clear now.
0
 
Meir RivkinFull stack Software EngineerCommented:
ok, i understand.
before i get into solving your problem, can i ask why the global variables used in memory rather than from a file?

the reason i ask is that it's very unorthodox and not best practice to have one application access variables stored in a memory in another application with direct API.
if both application runs on the same environment or even on different machines but with access to each one, it's better to have the Tradestation which set those global variables, dump them to a file where your C# app can read them.

in this case, you can have the C# app get notification (triggered) whenever those variables are changed (via file watcher for instance).

this is better approach cause u don't tight your C# app with the dll's memory space.
let me know what you think of this approach, if it's make sense to you or if it's feasible to implement in your environment.
0
 
JojoRAuthor Commented:
interesting idea , but I do not know if processing is fast enough this way.Sometimes ther are several values within a second.But if this would be practicable, no problem
0
 
Meir RivkinFull stack Software EngineerCommented:
how often the variables are being set?
the reading would be fast enough i imagine.

another question, who/how the C# app is being imitated?
is it running constantly and need to read these variables on specific intervals?
0
 
JojoRAuthor Commented:
between 1  to ~ 20(max) within one second

yes constantly to catch these incoming values as tight as possible - interval has to be checked
maybe 10 ms are fast enough
0
 
Meir RivkinFull stack Software EngineerCommented:
what those variables are used for by the C# app?
how are they being processed?
0
 
JojoRAuthor Commented:
this is not yet developed .Generally it's about " Tradespeed " , time intervals between the single trades that occurr in trading and how these changes and accumulations interfere the price movement - more generally just price and time
0
 
Meir RivkinFull stack Software EngineerCommented:
so we share the same "business", i work in forex company so i understand where you come from.

since time is a major factor here, i'd have your managed C++ dll invoke .net delegate from C# library.
basically it's a reverse mechanism of what you were initially wanted to implement.
so instead of having C# app which constantly reads the variables, you will have your managed C++ dll call directly your C# dll.

the best and easiest example i found on the internet is posted here:
Reverse P/Invoke

its fairly easy to implement, if you encounter any problems let me know and i'll guide you through.

cheers
0
 
JojoRAuthor Commented:
oops and I thought there would be an easy solution - so theoretically I need my C# dll with all calculations in it first and ready to go -
and then put  this Reverse mechanism into the existing .cpp GlobalVar code to call this     and call this then from Tradestation ? I will try to understand the concept .
Thanks again for everything you did so far
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 14
  • 11
Tackle projects and never again get stuck behind a technical roadblock.
Join Now