ironpython3
ironpython3 copied to clipboard
ipy throws StandardError on EventHandler
Concerns IronPython 2.7.12 2.7.12.0 on .NET 4.0.30319.42000
and IronPython 3.4.0b1
. Maybe related to IronLanguages/ironpython2#594
Description
Assigning an EventHandler throws a StandardError
in ipy with external dll. It works in the C# project but fails with ipy. dll is an external dll from ABB's PC SDK . It works with an older version of the dll.
Steps to Reproduce
Works in C# (full code at end of issue)
ctrl.EventLog.MessageWritten += new EventHandler<MessageWrittenEventArgs>(ctrl_EventMessageWritten);
In ipy:
delegate = EventHandler[EventLogDomain.MessageWrittenEventArgs](message)
c.EventLog.MessageWritten += delegate
I get a StandardError: Exception has been thrown by the target of an invocation.
with a newer dll from ABB.
All dll versions work in C#. Works in ipy only with ABB dll version up to (and including) 6.8.8307.1040
. Starting with the next version PC SDK 2019.3 aka 7.8.8617.559
the error is thrown.
How can I debug what the underlying problem is? I tried -v -u -X:Debug -X:ExceptionDetail -X:FullFrames -X:ShowClrExceptions -X:Tracing -X:PassExceptions
but did not get any deeper insights. Is this more related to ipy or to ABB? (All their dlls work in C#)
Full code
Full Python code:
import clr
import os
from encodings import utf_8 # Preload so that module is not loaded when exeception occurrs
from System import EventHandler
clr.AddReferenceToFileAndPath(os.path.abspath("ABB.Robotics.Controllers.PC.dll"))
def message(sender, event_args):
print('message')
return None
from ABB.Robotics.Controllers import *
try:
netScanner = Discovery.NetworkScanner()
except SystemError as se:
print('Cannot create NetworkScanner. Are RobotStudio.Services.RobApi.Desktop.dll and RobotStudio.Services.RobApi.dll present?')
controllers = netScanner.GetControllers()
for cinfo in controllers:
print("cinfo", cinfo.Id)
if len(controllers) > 0:
cinfo = controllers[0]
# c = Controller.Connect(cinfo, ConnectionType.Standalone) # New variant, replaced CreateFrom
c = ControllerFactory.CreateFrom(cinfo)
c.Logon(UserInfo.DefaultUser)
delegate = EventHandler[EventLogDomain.MessageWrittenEventArgs](message)
try:
c.EventLog.MessageWritten += delegate
# c.EventLog.MessageWritten += message # Alternative
except Exception as ex:
import traceback
traceback.print_exc()
Full code in C#, example project from ABB. SDK must be installed and ABB.Robotics.Controllers.PC.dll
, RobotStudio.Services.RobApi.Desktop.dll
and RobotStudio.Services.RobApi.dll
must be referenced.
/*
Copyright (c) 2011, ABB
All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that
the following conditions are met:
* Redistributions of source code must retain the
above copyright notice, this list of conditions
and the following disclaimer.
* Redistributions in binary form must reproduce the
above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the
distribution.
* Neither the name of ABB nor the names of its
contributors may be used to endorse or promote
products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using ABB.Robotics.Controllers;
using ABB.Robotics.Controllers.Discovery;
using ABB.Robotics.Controllers.EventLogDomain;
using System;
namespace ControllerAPI
{
/// <summary>
/// Listens for events on the Controller object
/// </summary>
class Listener
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[MTAThread]
static void Main(string[] args)
{
Controller ctrl;
while( ( ctrl = CreateController() ) == null )
{
}
ctrl.Logon( UserInfo.DefaultUser );
ctrl.OperatingModeChanged += new EventHandler<OperatingModeChangeEventArgs>(ctrl_OperatingModeChanged);
ctrl.EventLog.MessageWritten += new EventHandler<MessageWrittenEventArgs>(ctrl_EventMessageWritten);
Console.WriteLine("Press any key to terminate");
Console.ReadKey();
ctrl.Logoff();
}
static Controller CreateController()
{
NetworkScanner scanner = new NetworkScanner();
ControllerInfo[] controllers = scanner.GetControllers( NetworkScannerSearchCriterias.Real);
if( controllers.Length > 0 )
{
Controller dynamic = ControllerFactory.CreateFrom( controllers[0] );
return dynamic;
}
return null;
}
private static void ctrl_OperatingModeChanged(object sender, OperatingModeChangeEventArgs e)
{
Console.WriteLine( "New Operating mode at: {0} new mode is: {1}", e.Time, e.NewMode );
}
private static void ctrl_EventMessageWritten(object sender, MessageWrittenEventArgs e)
{
Console.WriteLine("New Event at: {0} event is {1}", e.Time, e.Message.Title);
}
}
}
Added print(ex.clsException)
and got
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: Incorrect number of arguments supplied for call to method 'Void _Scripting_(System.Object[], System.Object, ABB.Robotics.Controllers.EventLogDomain.MessageWrittenEventArgs)'
at System.Linq.Expressions.Expression.ValidateArgumentCount(MethodBase method, ExpressionType nodeKind, Int32 count, ParameterInfo[] pis)
at System.Linq.Expressions.Expression.Call(MethodInfo method, Expression arg0, Expression arg1)
at ControllerAPI.Internal.WeakEventSource`1.WeakDelegate.CreateOpenHandler(MethodInfo method)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at ControllerAPI.Internal.WeakEventSource`1.WeakDelegate..ctor(Object sender, Delegate handler, Boolean strong)
at ControllerAPI.Internal.WeakEventSource`1.<>c__DisplayClass3_0.<Subscribe>b__0(Delegate d)
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at ControllerAPI.Internal.WeakEventSource`1.Subscribe(Object sender, EventHandler`1 handler, Boolean strong)
at ABB.Robotics.Controllers.EventLogDomain.EventLog.Subscribe(EventHandler`1 handler)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.Scripting.Actions.EventTracker.AddHandler(Object target, Object handler, DynamicDelegateCreator delegateCreator)
at IronPython.Runtime.Types.ReflectedEvent.BoundEvent.InPlaceAdd(CodeContext context, Object func)
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
Thanks for the report. I managed to reproduce the issue here. I think it's ABB doing something funny with the EventHandler delegates (but I don't know enough about all this delegate stuff to rule out IronPython being at fault). You can maybe try wrapping your delegate like this:
delegate = EventHandler[EventLogDomain.MessageWrittenEventArgs](message)
delegate = EventHandler[EventLogDomain.MessageWrittenEventArgs](delegate.Invoke)
Thank you @slozier for looking into this and suggesting a solution / workaround.
I can confirm that this works with the latest ABB SDK (2022.1) both with IPython 2.7.12 and 3.4 beta.
Is this more an artifact of IronPython or is it worth to involve ABB in this matter?