如何使用 pythonnet 在 python 侦听器中订阅 .NET 事件?

2024-03-23

我正在尝试创建一个事件侦听器来订阅tick使用 Python 的外汇交易应用程序的(价格)事件。原始应用程序是一个本机 32 位 Windows 应用程序,名为元交易者4。这没有任何 API,所以mtapi https://github.com/vdemydiuk/mtapi/Bridge 是在 .NET 中设计的,允许其他编程语言与其交互。该应用程序定义了一些事件,其中两个是:QuoteUpdate and QuoteUpdated.

所以我想写一个监听器(delegate?) 使用python.net https://github.com/pythonnet/pythonnet订阅此活动。但由于我无法理解 .NET 代码是如何产生这些事件的,也不知道如何正确使用蟒蛇网,我无法让它发挥作用。我也不断遇到错误:

TypeError: 'EventBinding' object is not callable

谷歌搜索不会返回任何有用的东西,除了this https://github.com/pythonnet/pythonnet/blob/master/src/tests/leaktest.py#L3“修复我”评论。

这是我的代码:

import os, sys, clr
sys.path.append(r"C:\Program Files\MtApi")
asm = clr.AddReference('MtApi')
import MtApi as mt

res = 0

def printTick(symbol, ask, bid):
    print('Tick: Symbol: {}  Ask: {:.5f}  Bid: {:.5f}'.format(symbol, ask, bid))

# Setup .NET API bridge connection
mtc = mt.MtApiClient()
res = mtc.BeginConnect('127.0.0.1', 8222);

#--------------------------------------
# Register and use the listener
#--------------------------------------
# This does NOT work!
mtc.QuoteUpdate += printTick

#...

我的代码的意图应该很清楚。

问:如何让我的听众在收到消息时触发QuoteUpdate.NET 事件?


以供参考:

  • C# 中的 .NET 代码(来自MtApiClient.cs https://github.com/vdemydiuk/mtapi/blob/9eedf15e9e5aeda39e60fc76e6deb4dbdc92d289/MtApi/MtApiClient.cs看起来像这样:
...
private void _client_QuoteUpdated(MTApiService.MtQuote quote) { 
    if (quote != null) { 
        QuoteUpdate?.Invoke(this, new MtQuoteEventArgs(new MtQuote(quote))); 
        QuoteUpdated?.Invoke(this, quote.Instrument, quote.Bid, quote.Ask); 
    } 
} 
...
public event MtApiQuoteHandler QuoteUpdated; 
public event EventHandler<MtQuoteEventArgs> QuoteUpdate; 
public event EventHandler<MtQuoteEventArgs> QuoteAdded; 
public event EventHandler<MtQuoteEventArgs> QuoteRemoved; 
  • 还有一个小VB 测试应用程序 https://github.com/vdemydiuk/mtapi/blob/master/TestClients/TestMtApi/TestMtApi/Form1.vb看起来像这样:
Imports MtApi
Public Class Form1
    Private apiClient As MtApiClient
    Public Sub New()
        InitializeComponent()
        apiClient = New MtApiClient
        AddHandler apiClient.QuoteUpdated, AddressOf QuoteUpdatedHandler
    End Sub

    Sub QuoteUpdatedHandler(sender As Object, symbol As String, bid As Double, ask As Double)
        Dim quoteSrt As String
        quoteSrt = symbol + ": Bid = " + bid.ToString() + "; Ask = " + ask.ToString()
        ListBoxQuotesUpdate.Invoke(Sub()
                                       ListBoxQuotesUpdate.Items.Add(quoteSrt)
                                   End Sub)
        Console.WriteLine(quoteSrt)
    End Sub
    Private Sub btnConnect_Click(sender As System.Object, e As System.EventArgs) Handles btnConnect.Click
        apiClient.BeginConnect(8222)
    End Sub
    Private Sub btnDisconnect_Click(sender As System.Object, e As System.EventArgs) Handles btnDisconnect.Click
        apiClient.BeginDisconnect()
    End Sub
End Class

UPDATE

作为参考,我们有以下相关的 DLL 调用,由属性、类型 and __doc__:

attr: QuoteAdded             type: <class 'CLR.EventBinding'>    doc: <n/a>
attr: QuoteRemoved           type: <class 'CLR.EventBinding'>    doc: <n/a>
attr: QuoteUpdate            type: <class 'CLR.EventBinding'>    doc: <n/a>
attr: QuoteUpdated           type: <class 'CLR.EventBinding'>    doc: <n/a>

attr: add_QuoteAdded         type: <class 'CLR.MethodBinding'>   doc: Void add_QuoteAdded(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: add_QuoteRemoved       type: <class 'CLR.MethodBinding'>   doc: Void add_QuoteRemoved(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: add_QuoteUpdate        type: <class 'CLR.MethodBinding'>   doc: Void add_QuoteUpdate(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: add_QuoteUpdated       type: <class 'CLR.MethodBinding'>   doc: Void add_QuoteUpdated(MtApi.MtApiQuoteHandler)

attr: remove_QuoteAdded      type: <class 'CLR.MethodBinding'>   doc: Void remove_QuoteAdded(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: remove_QuoteRemoved    type: <class 'CLR.MethodBinding'>   doc: Void remove_QuoteRemoved(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: remove_QuoteUpdate     type: <class 'CLR.MethodBinding'>   doc: Void remove_QuoteUpdate(System.EventHandler`1[MtApi.MtQuoteEventArgs])
attr: remove_QuoteUpdated    type: <class 'CLR.MethodBinding'>   doc: Void remove_QuoteUpdated(MtApi.MtApiQuoteHandler)


类似问题:

实际上有 100 个相关的 SO 问题,我可能已经查看了其中 60% 以上,但用例的适用性几乎为零。其中一些是:

  • Python 类是否像其他语言一样支持事件? https://stackoverflow.com/questions/6158602/does-python-classes-support-events-like-other-languages
  • 将此事件处理程序注册从 C# 转换为 VB.net 的正确方法是什么? https://stackoverflow.com/questions/28387577/whats-the-correct-way-to-convert-this-event-handler-registration-from-c-sharp-t
  • 如何将 VB 委托转换为 python 事件处理程序? https://stackoverflow.com/questions/64851726/how-do-i-convert-a-vb-delegate-into-a-python-event-handler
  • https://ironpython.net/documentation/dotnet/dotnet.html https://ironpython.net/documentation/dotnet/dotnet.html(也可能相关)
  • https://openbookproject.net/thinkcs/python/english3e/events.html https://openbookproject.net/thinkcs/python/english3e/events.html
  • https://code.activestate.com/recipes/410686-c-style-events-in-python/ https://code.activestate.com/recipes/410686-c-style-events-in-python/

经过几天和几个小时的时间,我发现了一些错误的组合。与往常一样,2-3 个简单错误的组合可能会让你的生活在很长一段时间内痛苦不堪。但最大的错误是被愚弄,认为听众(又名。delegate)必须由一堆复杂的__init__ and __iadd__功能。错误的! Python.NET 在大多数情况下都可以正常工作,但是如果您犯了任何小错误,您得到的错误(如果有的话)就毫无用处。

我原来的代码有1.5个问题。

  • 有 2 个不同的Quote函数,即:

  • QuoteUpdate返回sender and an object在 .NET 中命名为“MtQuoteEventArgs”

  • QuoteUpdated返回sender and 3 论点.

  • 因此我们需要同时修复打印刻度()函数和监听器线。

更正后的代码为:

def printTick(source, symbol, ask, bid):
    print('Tick: Symbol: {}  Ask: {:.5f}  Bid: {:.5f}'.format(symbol, ask, bid))

...

mtc.QuoteUpdates += printTick

有关 C# 的更多信息活动和代表:

  • https://www.tutorialsteacher.com/csharp/csharp-event https://www.tutorialsteacher.com/csharp/csharp-event
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 pythonnet 在 python 侦听器中订阅 .NET 事件? 的相关文章

随机推荐