-
-
Save bsommardahl/8605208 to your computer and use it in GitHub Desktop.
public interface IRtdClient | |
{ | |
object GetValue(params object[] args); | |
} | |
public class RtdClient : IRtdClient | |
{ | |
readonly string _rtdProgId; | |
static IRtdServer _rtdServer; | |
public RtdClient(string rtdProgId) | |
{ | |
_rtdProgId = rtdProgId; | |
} | |
public object GetValue(params object[] args) | |
{ | |
const int topicCount = 1; | |
var rnd = new Random(); | |
var topicId = rnd.Next(int.MaxValue); | |
var rtdServer = GetRtdServer(); | |
rtdServer.ConnectData(topicId, args, true); | |
object val = null; | |
while (val == null) | |
{ | |
var alive = rtdServer.Heartbeat(); | |
if (alive != 1) | |
GetRtdServer(); | |
else | |
{ | |
var refresh = rtdServer.RefreshData(topicCount); | |
if (refresh.Length <= 0) continue; | |
if (refresh[0, 0].ToString() == topicId.ToString()) | |
{ | |
val = refresh[1, 0]; | |
} | |
} | |
} | |
rtdServer.DisconnectData(topicId); | |
return val; | |
} | |
IRtdServer GetRtdServer() | |
{ | |
if(_rtdServer==null) | |
{ | |
Type rtd = Type.GetTypeFromProgID(_rtdProgId); | |
_rtdServer = (IRtdServer)Activator.CreateInstance(rtd); | |
} | |
return _rtdServer; | |
} | |
} | |
[ComImport, | |
TypeLibType((short)0x1040), | |
Guid("EC0E6191-DB51-11D3-8F3E-00C04F3651B8")] | |
public interface IRtdServer | |
{ | |
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10)] | |
int ServerStart([In, MarshalAs(UnmanagedType.Interface)] IRTDUpdateEvent callback); | |
[return: MarshalAs(UnmanagedType.Struct)] | |
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)] | |
object ConnectData([In] int topicId, [In, MarshalAs(UnmanagedType.SafeArray, | |
SafeArraySubType = VarEnum.VT_VARIANT)] ref object[] parameters, [In, Out] ref bool newValue); | |
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] | |
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)] | |
object[,] RefreshData([In, Out] ref int topicCount); | |
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(13)] | |
void DisconnectData([In] int topicId); | |
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(14)] | |
int Heartbeat(); | |
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(15)] | |
void ServerTerminate(); | |
} | |
[ComImport, | |
TypeLibType((short) 0x1040), | |
Guid("A43788C1-D91B-11D3-8F39-00C04F3651B8")] | |
public interface IRTDUpdateEvent | |
{ | |
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10), | |
PreserveSig] | |
void UpdateNotify(); | |
[DispId(11)] | |
int HeartbeatInterval { [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)] | |
get; [param: In] | |
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)] | |
set; } | |
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)] | |
void Disconnect(); | |
} |
This looks like the best I can find on the web about code to do this. But for some reason I cannot pass the topics
args
at all.Having this on MS-Excel:
=RTD("rtdtrading.rtdserver",, "WINZ20_F_0", "HOR")
This formula works on Excel and pulls fresh data.I then tried to instantiate the object with:
var handler = new RtdClient("rtdtrading.rtdserver");
So far, so good. But then, when I try to
var valList = handler.GetValue(new object[] { "WINZ20_G_0", "HOR" });
I get a big Catastrophic failure (0x8000FFFF (E_UNEXPECTED)) from
IRtdServer.ConnectData(Int32 topicId, Object[]& parameters, Boolean& newValue)
, line 24 in the code above.If I try to use
new string[] { "WINZ20_G_0", "HOR" });
, then the error changes to Specified array was not of the expected type, happening a bit deeper, but I believe still beforeConnectData()
is actually run, as the call stack suggestes:at System.StubHelpers.MngdSafeArrayMarshaler.ConvertSpaceToNative(IntPtr pMarshalState, Object& pManagedHome, IntPtr pNativeHome) at ProfitRTDAnalyzer.Program.IRtdServer.ConnectData(Int32 topicId, Object[]& parameters, Boolean& newValue)
Hi @avengerx, to solve this problem, I do the follwing:
Create a a new class to implement UpdateEvent:
public class UpdateEvent : IRTDUpdateEvent
{
public long Count { get; set; }
public int HeartbeatInterval { get; set; }
public UpdateEvent()
{
// Do not call the RTD Heartbeat()
// method.
HeartbeatInterval = -1;
}
public void Disconnect()
{
// Do nothing.
}
public void UpdateNotify()
{
Count++;
}
and then, replace it into GetRtdServer function
IRtdServer GetRtdServer()
{
if (_rtdServer == null)
{
Type rtd = Type.GetTypeFromProgID(_rtdProgId);
_rtdServer = (IRtdServer)Activator.CreateInstance(rtd);
// Create the updateEvent.
UpdateEvent updateEvent = new UpdateEvent();
_rtdServer.ServerStart(updateEvent);
}
return _rtdServer;
}
Now it's working for me.
@julianozucatti I can give my dirty sandbox application
where I tried to make RTD Client for "TWS RTD Server API".
What is good here, you can see the sources of this API and what is going
with your requests.
@Neznakomec
I could demonstrate what your RTD client looks like, I'm facing the same problem with the exception of calling
IRtdServer.ConnectData(Int32