如何使用pythonnet在python侦听器中订阅.NET事件? [英] How to subscribe to a .NET event in a python listener using pythonnet?
问题描述
我正在尝试使用Python使事件侦听器从FX交易应用程序中订阅 QuoteUpdate
和 QuoteUpdated
.
I'm trying to make an event listener to subscribe to a tick (price) event from a FX trading application, using Python. The original application is a native 32-bit Windows app called MetaTrader4. This does not have any API, so the mtapi bridge has been designed in .NET to allow other programming languages to interact with it. The application has some events defined, two of which are: QuoteUpdate
and QuoteUpdated
.
所以我想使用 python.net编写一个侦听器( delegate ?).订阅此活动.但是由于我无法理解.NET代码是如何产生这些事件的,也无法理解如何正确使用 pythonnet ,因此无法使它正常工作.我还不断遇到错误:
So I would like to write a listener (delegate?) using python.net to subscribe to this event. But since I am not able to understand how the .NET code is producing these events, and neither how to properly use pythonnet, I have not been able to get this to work. I also keep running into the error:
TypeError:'EventBinding'对象不可调用
TypeError: 'EventBinding' object is not callable
使用Google谷歌搜索功能不会返回任何有用的信息,除了此"FIXME"评论.
Googling this doesn't return anything useful, apart this "FIXME" comment.
这是我的代码:
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
#...
我的代码的意图应该很清楚.
The intention for my code should be clear.
问:接收到 QuoteUpdate
.NET事件时如何激发我的监听器?
Q: How can I make my listener fire when receiving the QuoteUpdate
.NET event?
供参考:
- C#中的.NET代码(来自 MtApiClient.cs. a>看起来像这样:
- The .NET code in C# (from MtApiClient.cs look like this:
...
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测试应用看起来像这样:
- And a small VB Test app look like this:
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
更新
作为参考,我们有以下相关的DLL调用,它们由属性,类型和 __ doc __
提供:
For reference, we have the following relevant DLL calls, given by the attributes, types 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)
类似问题:
Similar Issues:
从字面上看,相关的SO问题有100多个,我大概研究了其中的60%以上,但对用例的适用性几乎没有成功.其中一些是:
There are literally 100's of related SO issue, and I've probably looked at over 60% of them but with nearly zero success to applicability to by use case. Some of which are:
- Python类是否支持其他语言的事件?
- 是什么将该事件处理程序注册从C#转换为VB.net的正确方法是什么?
- 如何转换VB委托到python事件处理程序中?
- https://ironpython.net/documentation/dotnet/dotnet.html (可能也相关)
- https://openbookproject.net/thinkcs/python/english3e/events.html
- https://code.activestate.com/recipes/410686-c-style-events-in-python/
- Does Python classes support events like other languages?
- What's the correct way to convert this event handler registration from C# to VB.net?
- How do I convert a VB delegate into a python event handler?
- https://ironpython.net/documentation/dotnet/dotnet.html (may also be relevant)
- https://openbookproject.net/thinkcs/python/english3e/events.html
- https://code.activestate.com/recipes/410686-c-style-events-in-python/
推荐答案
几天和很长时间之后,我发现了一系列错误.与往常一样,将2-3个简单的错误结合在一起会使您的生活长期处于悲惨境地.但是,最大的错误是,愚蠢的以为列表员(又名 delegate )必须要加上一堆 __ init __
和 __ iadd __ 代码>函数.错误的!Python.NET大部分时间都可以正常工作,但是如果您犯了任何小错误,那么您得到的错误(如果有的话)几乎是没有用的.
After a few days and some long hours I found a combination of mistake(s). As always, a combination of 2-3 simple mistakes can make your life miserable for a long time. But the biggest mistake of all, was being fooled to think that a listner (aka. delegate) had to be complicated with a bunch of __init__
and __iadd__
functions. Wrong! Python.NET just works most of the time but the errors you get (if any at all) are pretty useless if you make any small mistake.
我的原始代码有1.5个问题.
There are 1.5 problems with my original code.
-
有2种不同的 Quote 函数,即:
QuoteUpdate
,它返回发件人和一个名为"MtQuoteEventArgs"的对象.在.NET中
QuoteUpdate
which returns sender and an object named "MtQuoteEventArgs" in .NET
QuoteUpdated
会返回发件人和3个参数.
因此,我们需要修复 printTick()函数和侦听器行.
Therefore we need to fix both the printTick() function and the listener line.
更正后的代码是:
def printTick(source, symbol, ask, bid):
print('Tick: Symbol: {} Ask: {:.5f} Bid: {:.5f}'.format(symbol, ask, bid))
...
mtc.QuoteUpdates += printTick
有关C#事件&代表:
这篇关于如何使用pythonnet在python侦听器中订阅.NET事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!