A Tech Log

October 6, 2008

Mono and Tibco RV

Filed under: Development — adallow @ 11:46 am
Tags:

The below is taken from: http://weblogs.asp.net/mdavey/pages/79456.aspx I came across it a few years ago and found it useful based on what i was doing at the time, I just found it again in my browser favourites so thought i would post it for the sake of completeness….

Tibco RV is often used in investment banks to send market data. Its therefore going to be a requirement for any front-office trading application running on Linux and Mono to subscribe to Tibco RV subjects. What follows is a simple example of the code required to do this – effectively a Mono language binding for Tibco RV. This code was written on RedHat 9.0, with Mono 0.30, and Tibco 7.2.

First we need a C++ library (.so) which uses the Tibco RV C++ API to setup a simple subscription. Callback’s from C++ to C# (unmanaged to managed) are handled by C++ function pointers and normal C# delegates. The C++ “Start” function below will be called by C#, passing a C# delegate, which the C++ will callback on when a message is received on the Tibco RV subject.

#include
#include
#include
#include
#include

#include “tibrv/tibrvcpp.h”

/*********************************************************************/
/* Transport parameters */
/*********************************************************************/

char* serviceStr = NULL;
char* networkStr = NULL;
char* daemonStr = “tcp::7500”;

typedef void (*stringFunction)(char*);

stringFunction stringFunctionPtr;
/*********************************************************************/
/* Message callback class */
/*********************************************************************/
class MsgCallback : public TibrvMsgCallback
{
public:

void onMsg(TibrvListener* listener, TibrvMsg& msg)
{
const char* sendSubject = NULL;
const char* replySubject = NULL;
const char* msgString = NULL;

// Get the subject name to which this message was sent
msg.getSendSubject(sendSubject);

// If there was a reply subject, get it
msg.getReplySubject(replySubject);

// Convert the incoming message to a string
msg.convertToString(msgString);

if (replySubject != NULL)
printf(“subject=%s, reply=%s, message=%s\n”, sendSubject, replySubject, msgString);
else
printf(“subject=%s, message=%s\n”, sendSubject, msgString);

printf(“About to do callback to C#\n”);
(*stringFunctionPtr)((char*)msgString);
fflush(stdout);
}
};

extern “C” void Start(stringFunction f)
{
stringFunctionPtr = f;
TibrvStatus status;

// open Tibrv
status = Tibrv::open();
if (status != TIBRV_OK)
{
fprintf(stderr,”Error: could not open TIB/RV, status=%d, text=%s\n”, (int)status,status.getText());
exit(-1);
}

// Create network transport
TibrvNetTransport transport;
status = transport.create(serviceStr,networkStr,daemonStr);
if (status != TIBRV_OK)
{
fprintf(stderr,”Error: could not create transport, status=%d, text=%s\n”, (int)status,status.getText());
Tibrv::close();
exit(-1);
}
transport.setDescription(“SomeSubject”);

TibrvListener* listener = new TibrvListener();
status=listener->create(Tibrv::defaultQueue(),new MsgCallback(),&transport,”SomeSubject”);
if (status != TIBRV_OK)
{
fprintf(stderr,”Error: could not create listener on %s, status=%d, text=%s\n”, “SomeSubject”,(int)status,status.getText());
Tibrv::close();
exit(-1);
}
printf(“Listening on: %s\n”,”SomeSubject”);
fflush(stdout);

// dispatch Tibrv events
while((status=Tibrv::defaultQueue()->dispatch()) == TIBRV_OK);

// if everything is Ok we’ll never get here
fprintf(stderr,”Error: dispatch failed, status=%d, text=%s\n”, (int)status,status.getText());
Tibrv::close();
exit(-1);
}

We use the DllImport .NET attribute to tell C# where the C++ “Start” method should be located. The TibCallback delegate must match the C++ function pointer stringFunction from an argument perspective.

using System;
using System.Threading;
using System.Runtime.InteropServices;

namespace Test
{
public delegate void TibCallback(string s);

public class Class1
{
[DllImport(“”, CharSet=CharSet.Ansi)]
public static extern void Start(Delegate d);

private Thread tibThread;

static void Main(string[] args)
{
new Class1().Run();
}

public void Run()
{
tibThread = new Thread(new ThreadStart(StartTib));
tibThread.IsBackground = true;
tibThread.Name = “TibThread”;
tibThread.Start();
Console.ReadLine();
}

private void StartTib()
{
Start(new TibCallback(this.TibMsg));
}

public void TibMsg(string s) {
Console.WriteLine(“TibMsg called”);
Console.WriteLine(s);
}
}
}

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: