diff --git a/src/ScriptEngine/Machine/ComReflectionNameToIdMapper.cs b/src/ScriptEngine/Machine/ComReflectionNameToIdMapper.cs index 1feacb1cf..e16c06d3c 100644 --- a/src/ScriptEngine/Machine/ComReflectionNameToIdMapper.cs +++ b/src/ScriptEngine/Machine/ComReflectionNameToIdMapper.cs @@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the using System.Collections.Generic; using System.Linq; using System.Reflection; +using ScriptEngine.Machine.Contexts; namespace ScriptEngine.Machine { @@ -70,13 +71,24 @@ public int FindMethod(object instance, string name) try { - return instance.GetType().InvokeMember(name, + var arrayOfArgs = callParams.Select(x => ContextValuesMarshaller.CastToCLRObject(x.GetRawValue())).ToArray(); + var retValue = instance.GetType().InvokeMember(name, BindingFlags.InvokeMethod | BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.Instance, new ValueBinder(), instance, - callParams.Cast().ToArray()); + arrayOfArgs); + + for (int i = 0; i < callParams.Length; i++) + { + if (callParams[i] is IVariable variable) + { + variable.Value = ContextValuesMarshaller.ConvertReturnValue(arrayOfArgs[i]); + } + } + + return retValue; } catch (TargetInvocationException e) { diff --git a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs index e72a06b2e..7c6780f4f 100644 --- a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs +++ b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs @@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; namespace ScriptEngine.Machine.Contexts { @@ -66,7 +67,7 @@ public static COMWrapperContext Create(string progId, IValue[] arguments) type = type.MakeGenericType(genericTypes.ToArray()); } - object instance = Activator.CreateInstance(type, MarshalArguments(arguments)); + object instance = Activator.CreateInstance(type, MarshalArguments(arguments).values); return InitByInstance(type, instance); } @@ -105,10 +106,17 @@ private static bool TypeIsRuntimeCallableWrapper(Type type) return type.FullName == "System.__ComObject" || type.BaseType.FullName == "System.__ComObject"; // string, cause it's hidden type } - public static object[] MarshalArguments(IValue[] arguments) + public static (object[] values, ParameterModifier flags) MarshalArguments(IValue[] arguments) { - var args = arguments.Select(x => MarshalIValue(x)).ToArray(); - return args; + var values = new object[arguments.Length]; + var flags = new ParameterModifier(arguments.Length); + for (int i = 0; i < arguments.Length; i++) + { + values[i] = MarshalIValue(arguments[i]); + flags[i] = arguments[i] is IVariable; + } + + return (values, flags); } public static object MarshalIValue(IValue val) diff --git a/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs b/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs index 0a94cc9f9..3e14bf485 100644 --- a/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs +++ b/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs @@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Reflection; using ScriptEngine.Machine.Rcw; namespace ScriptEngine.Machine.Contexts @@ -191,7 +192,9 @@ public override void CallAsProcedure(int methodNumber, IValue[] arguments) { try { - DispatchUtility.Invoke(Instance, dispId, MarshalArguments(arguments)); + var argsData = MarshalArguments(arguments); + DispatchUtility.Invoke(Instance, dispId, argsData.values, new [] { argsData.flags }); + RemapOutputParams(arguments, argsData.values, argsData.flags); } catch (System.Reflection.TargetInvocationException e) { @@ -217,7 +220,9 @@ public override void CallAsFunction(int methodNumber, IValue[] arguments, out IV { try { - var result = DispatchUtility.Invoke(Instance, dispId, MarshalArguments(arguments)); + var argsData = MarshalArguments(arguments); + var result = DispatchUtility.Invoke(Instance, dispId, argsData.values, new [] { argsData.flags }); + RemapOutputParams(arguments, argsData.values, argsData.flags); retValue = CreateIValue(result); } catch (System.Reflection.TargetInvocationException e) @@ -230,6 +235,18 @@ public override void CallAsFunction(int methodNumber, IValue[] arguments, out IV throw RuntimeException.MethodNotFoundException(method.Name); } } + + private void RemapOutputParams(IValue[] arguments, object[] values, ParameterModifier flags) + { + for (int i = 0; i < arguments.Length; i++) + { + if (flags[i]) + { + var variable = (IVariable)arguments[i]; + variable.Value = CreateIValue(values[i]); + } + } + } private bool TryFindMethod(string name, out RcwMethodMetadata md) { diff --git a/src/ScriptEngine/Machine/MachineInstance.cs b/src/ScriptEngine/Machine/MachineInstance.cs index 671076b63..e1f1a9356 100644 --- a/src/ScriptEngine/Machine/MachineInstance.cs +++ b/src/ScriptEngine/Machine/MachineInstance.cs @@ -1116,7 +1116,7 @@ private void PrepareContextCallArguments(int arg, out IRuntimeContextInstance co var argValue = factArgs[i]; if (argValue.DataType != DataType.NotAValidValue) { - argValues[i] = argValue.GetRawValue(); + argValues[i] = argValue; } } } diff --git a/src/ScriptEngine/Machine/Rcw/DispatchUtility.cs b/src/ScriptEngine/Machine/Rcw/DispatchUtility.cs index 04f8524a4..ace03a758 100644 --- a/src/ScriptEngine/Machine/Rcw/DispatchUtility.cs +++ b/src/ScriptEngine/Machine/Rcw/DispatchUtility.cs @@ -103,9 +103,27 @@ public static bool TryGetDispId(object obj, string name, out int dispId) /// This can invoke a method or a property get accessor. /// public static object Invoke(object obj, int dispId, object[] args) + { + object result = Invoke(obj, dispId, args, null); + return result; + } + + /// + /// Invokes a member by DISPID. + /// + /// An object that implements IDispatch. + /// The DISPID of a member. This can be obtained using + /// . + /// The arguments to pass to the member. + /// ByRef modifiers + /// The member's return value. + /// + /// This can invoke a method or a property get accessor. + /// + public static object Invoke(object obj, int dispId, object[] args, ParameterModifier[] modifiers) { string memberName = "[DispId=" + dispId + "]"; - object result = Invoke(obj, memberName, args); + object result = Invoke(obj, memberName, args, modifiers); return result; } @@ -119,12 +137,12 @@ public static object Invoke(object obj, int dispId, object[] args) /// /// This can invoke a method or a property get accessor. /// - public static object Invoke(object obj, string memberName, object[] args) + public static object Invoke(object obj, string memberName, object[] args, ParameterModifier[] modifiers) { RequireReference(obj, "obj"); Type type = obj.GetType(); object result = type.InvokeMember(memberName, BindingFlags.InvokeMethod | BindingFlags.GetProperty, - null, obj, args, null); + null, obj, args, modifiers, null, null); return result; }