FoxPro and .NET Interop
wwDotNetBridge and FIX Protocol
Gravatar is a globally recognized avatar based on your email address. wwDotNetBridge and FIX Protocol
  Kathy
  All
  Jan 25, 2018 @ 10:50am

Hello,
I'm looking for a solution for using FIX protocol (Financial Information eXchange) and sending FIX messages via Foxpro.

I've been trying to use "Onix" FIX Engine; "FIXForge.NET.FIX.Engine" and their *FIXMLConverter *but I've not been successful to load the assembly/ies in Fox:
ERROR: "Could not load file or assembly '...\fixforge.net.fix.engine-net-4.7_x64.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format."

Not sure if it's one of those complex APIs or where my mistake is.
But has anyone had any experience with FIX protocol and Onix or other products out there or would anyone have any suggestion what would be the best way of sending FIX messages?

Thank you in advance,
Kathy

Gravatar is a globally recognized avatar based on your email address. re: wwDotNetBridge and FIX Protocol
  Rick Strahl
  Kathy
  Jan 25, 2018 @ 01:03pm

Looks like that assembly is compiled explicitly for 64 bit, which won't work for FoxPro. wwDotnetBridge will only be able to load assemblies compiled for x86 or Any cpu - x64 specific assemblies will likely fail. Haven't checked for that but I would assume that's the issue.

But you should also check and make sure that any dependencies that are used by the DLL are also available either in the GAC or in the same folder as the base assembly.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: wwDotNetBridge and FIX Protocol
  Kathy
  Rick Strahl
  Jan 26, 2018 @ 10:12am

Thank you so much Rick.
You were right as always. I downloaded their x86 version and it looks like working.
I've just started studying the feasibility of using wwDotNetBridge and I would appreciate your idea on this approach for I feel like I'm already lost.

Given Onix FIX Engine API Reference and the Buyside.cs in C# code down below (one of the examples they've suggested to start from), would you think if I'm able to create instances and invoke methods directly from VFP or else what would you suggest?
I'm asking because I'm not sure if Onix objects could be/how should be passed as params from VFP.
For instance, I was able to create instance for EngineSettings but I don't know why I can't create instance for the actual Engine:

DO wwDotNetBridge
loBridge = GetwwDotNetBridge()
loBridge.LoadAssembly("FIXForge.NET.FIX.Engine-net-4.7_x86.dll")
loFoxEngineSetting = loBridge.createinstance("FIXForge.NET.FIX.EngineSettings")
? loFoxEngineSetting   && (Object)
loFoxEngine = loBridge.createinstance("FIXForge.NET.FIX.Engine")
? loFoxEngine   && .NULL.
loFoxEngine = loBridge.createinstance("FIXForge.NET.FIX.Engine", loFoxEngineSetting)
? loFoxEngine   && .NULL.

While EngineSetting Class is like: EngineSettings Class
And Engine classe is like: Engine Class

And here is the Buyside.cs Examle:

using System;
using System.Reflection;
using FIXForge.NET.FIX;
using FIXForge.NET.FIX.FIX44;
using Helpers;
using System.Globalization;

namespace BuySide
{
    /// <summary>
    /// Establishes the FIX session as Initiator.
    /// </summary>
    internal class Initiator
    {
        private static void OnInboundApplicationMsg(Object sender, InboundApplicationMsgEventArgs e)
        {
            Console.WriteLine("Incoming application-level message:\n" + e.Msg);
            // Processing of the application-level incoming message ... 
        }

        private static void Run()
        {
            try
            {
                EngineSettings settings = new EngineSettings();

                Engine.Init(settings);

                Session sn = new Session(Settings.Get("SenderCompID"),
                                         Settings.Get("TargetCompID"),
                                         Settings.GetVersion());

                sn.InboundApplicationMsgEvent += new InboundApplicationMsgEventHandler(OnInboundApplicationMsg);
                sn.StateChangeEvent += new StateChangeEventHandler(OnStateChange);

                sn.ErrorEvent += new ErrorEventHandler(OnError);
                sn.WarningEvent += new WarningEventHandler(OnWarning);

				sn.LogonAsInitiator(Settings.Get("Counterparty Host"), Settings.GetInteger("Counterparty Port"));

                Console.WriteLine("Press any key to send an order.");
                Console.ReadKey();

                Message order = CreateOrderMessage();

                sn.Send(order);

                Console.WriteLine("The order (" + order + ") was sent");

                Console.WriteLine("Press any key to disconnect the session and terminate the application.");
                Console.ReadKey();

                sn.Logout("The session is disconnected by BuySide");
                sn.Dispose();

                Engine.Instance.Shutdown();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: " + ex);
            }
        }

        private static Message CreateOrderMessage()
        {
            Message order = new Message("D", Settings.GetVersion());
            order.Set(Tags.HandlInst, "1");
            order.Set(Tags.ClOrdID, "Unique identifier for Order");
            order.Set(Tags.Symbol, "IBM");
            order.Set(Tags.Side, "1");
            order.Set(Tags.OrderQty, 1000);
            order.Set(Tags.OrdType, "1");
			order.Set(Tags.TransactTime, DateTime.UtcNow.ToString("yyyyMMdd-HH:mm:ss", CultureInfo.InvariantCulture));

            order.Validate();
            return order;
        }

        private static void OnStateChange(Object sender, StateChangeEventArgs e)
        {
            Console.WriteLine("New session state: " + e.NewState);
        }

        private static void OnError(Object sender, ErrorEventArgs e)
        {
            Console.WriteLine("Session Error: " + e.ToString());
        }

        private static void OnWarning(Object sender, WarningEventArgs e)
        {
            Console.WriteLine("Session Warning: " + e.ToString());
        }   

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        private static void Main()
        {
            Run();

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

Gravatar is a globally recognized avatar based on your email address. re: wwDotNetBridge and FIX Protocol
  Rick Strahl
  Kathy
  Jan 26, 2018 @ 01:40pm

If you need to capture all those events - you can't really do that from Foxpro directly. You either need to create explicit event interfaces that COM Interop can handle (which means you have to register the DLL via .NET COM which sucks), or you have to create a .NET wrapper that handles the events and forwards them to FoxPro.

I'd recommend creating a small .NET class library that makes the calls and handles the events, and forwards the Events to a FoxPro object you pass in and call back to when the events fire in .NET (similar to the way the SIgnalR eventing works).

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: wwDotNetBridge and FIX Protocol
  Kathy
  Rick Strahl
  Jan 28, 2018 @ 01:01pm

I'll try to do so.
That was a great help.
Thank you so much.
Kathy

© 1996-2024