-
-
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
argsat 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