private ArgumentMarshaller /*!*/[] /*!*/ GetArgumentMarshallers(DynamicMetaObject /*!*/[] /*!*/ args) { CFuncPtrType funcType = ((CFuncPtrType)Value.NativeType); ArgumentMarshaller[] res = new ArgumentMarshaller[args.Length]; // first arg is taken by self if we're a com method for (int i = 0; i < args.Length; i++) { DynamicMetaObject mo = args[i]; object argType = null; if (Value._comInterfaceIndex == -1 || i != 0) { int argtypeIndex = Value._comInterfaceIndex == -1 ? i : i - 1; if (Value._argtypes != null && argtypeIndex < Value._argtypes.Count) { argType = Value._argtypes[argtypeIndex]; } else if (funcType._argtypes != null && argtypeIndex < funcType._argtypes.Length) { argType = funcType._argtypes[argtypeIndex]; } } res[i] = GetMarshaller(mo.Expression, mo.Value, i, argType); } return(res); }
public void Should_return_empty_string_from_new_argument_marshaller() { var stringArgumentMarshaller = new ArgumentMarshaller <string> { Value = string.Empty }; Assert.That(stringArgumentMarshaller.Value, Is.EqualTo(string.Empty)); }
private ArgumentMarshaller /*!*/[] /*!*/ GetArgumentMarshallers(DynamicMetaObject /*!*/[] /*!*/ args) { CFuncPtrType funcType = ((CFuncPtrType)Value.NativeType); ArgumentMarshaller[] res = new ArgumentMarshaller[args.Length]; for (int i = 0; i < args.Length; i++) { DynamicMetaObject mo = args[i]; object argType = null; if (Value._argtypes != null && i < Value._argtypes.Count) { argType = Value._argtypes[i]; } else if (funcType._argtypes != null && i < funcType._argtypes.Length) { argType = funcType._argtypes[i]; } res[i] = GetMarshaller(mo.Expression, mo.Value, i, argType); } return(res); }
public UserDefinedMarshaller(Expression /*!*/ container, ArgumentMarshaller /*!*/ marshaller) : base(container) { _marshaller = marshaller; }
public UserDefinedMarshaller(Expression/*!*/ container, ArgumentMarshaller/*!*/ marshaller) : base(container) { _marshaller = marshaller; }
private static SignatureHelper GetCalliSignature(CallingConvention convention, ArgumentMarshaller/*!*/[] sig, Type calliRetType) { SignatureHelper signature = SignatureHelper.GetMethodSigHelper(convention, calliRetType); foreach (ArgumentMarshaller argMarshaller in sig) { signature.AddArgument(argMarshaller.NativeType); } return signature; }
/// <summary> /// Creates a method for calling with the specified signature. The returned method has a signature /// of the form: /// /// (IntPtr funcAddress, arg0, arg1, ..., object[] constantPool) /// /// where IntPtr is the address of the function to be called. The arguments types are based upon /// the types that the ArgumentMarshaller requires. /// </summary> private static MethodInfo/*!*/ CreateInteropInvoker(CallingConvention convention, ArgumentMarshaller/*!*/[]/*!*/ sig, INativeType nativeRetType, bool retVoid, List<object> constantPool) { Type[] sigTypes = new Type[sig.Length + 2]; sigTypes[0] = typeof(IntPtr); for (int i = 0; i < sig.Length; i++) { sigTypes[i + 1] = sig[i].ArgumentExpression.Type; } sigTypes[sigTypes.Length - 1] = typeof(object[]); Type retType = retVoid ? typeof(void) : nativeRetType != null ? nativeRetType.GetPythonType() : typeof(int); Type calliRetType = retVoid ? typeof(void) : nativeRetType != null ? nativeRetType.GetNativeType() : typeof(int); #if !CTYPES_USE_SNIPPETS DynamicMethod dm = new DynamicMethod("InteropInvoker", retType, sigTypes, DynamicModule); #else TypeGen tg = Snippets.Shared.DefineType("InteropInvoker", typeof(object), false, false); MethodBuilder dm = tg.TypeBuilder.DefineMethod("InteropInvoker", CompilerHelpers.PublicStatic, retType, sigTypes); #endif ILGenerator method = dm.GetILGenerator(); LocalBuilder calliRetTmp = null, finalRetValue = null; if (dm.ReturnType != typeof(void)) { calliRetTmp = method.DeclareLocal(calliRetType); finalRetValue = method.DeclareLocal(dm.ReturnType); } // try { // emit all of the arguments, save their cleanups method.BeginExceptionBlock(); List<MarshalCleanup> cleanups = null; for (int i = 0; i < sig.Length; i++) { #if DEBUG method.Emit(OpCodes.Ldstr, String.Format("Argument #{0}, Marshaller: {1}, Native Type: {2}", i, sig[i], sig[i].NativeType)); method.Emit(OpCodes.Pop); #endif MarshalCleanup cleanup = sig[i].EmitCallStubArgument(method, i + 1, constantPool, sigTypes.Length - 1); if (cleanup != null) { if (cleanups == null) { cleanups = new List<MarshalCleanup>(); } cleanups.Add(cleanup); } } // emit the target function pointer and the calli #if DEBUG method.Emit(OpCodes.Ldstr, "!!! CALLI !!!"); method.Emit(OpCodes.Pop); #endif method.Emit(OpCodes.Ldarg_0); method.Emit(OpCodes.Calli, GetCalliSignature(convention, sig, calliRetType)); // if we have a return value we need to store it and marshal to Python // before we run any cleanup code. if (retType != typeof(void)) { #if DEBUG method.Emit(OpCodes.Ldstr, "!!! Return !!!"); method.Emit(OpCodes.Pop); #endif if (nativeRetType != null) { method.Emit(OpCodes.Stloc, calliRetTmp); nativeRetType.EmitReverseMarshalling(method, new Local(calliRetTmp), constantPool, sig.Length + 1); method.Emit(OpCodes.Stloc, finalRetValue); } else { Debug.Assert(retType == typeof(int)); // no marshalling necessary method.Emit(OpCodes.Stloc, finalRetValue); } } // } finally { // emit the cleanup code method.BeginFinallyBlock(); if (cleanups != null) { foreach (MarshalCleanup mc in cleanups) { mc.Cleanup(method); } } method.EndExceptionBlock(); // } // load the temporary value and return it. if (retType != typeof(void)) { method.Emit(OpCodes.Ldloc, finalRetValue); } method.Emit(OpCodes.Ret); #if CTYPES_USE_SNIPPETS return tg.TypeBuilder.CreateType().GetMethod("InteropInvoker"); #else return dm; #endif }
private ArgumentMarshaller/*!*/[]/*!*/ GetArgumentMarshallers(DynamicMetaObject/*!*/[]/*!*/ args) { CFuncPtrType funcType = ((CFuncPtrType)Value.NativeType); ArgumentMarshaller[] res = new ArgumentMarshaller[args.Length]; for (int i = 0; i < args.Length; i++) { DynamicMetaObject mo = args[i]; object argType = null; if (Value._argtypes != null && i < Value._argtypes.Count) { argType = Value._argtypes[i]; } else if (funcType._argtypes != null && i < funcType._argtypes.Length) { argType = funcType._argtypes[i]; } res[i] = GetMarshaller(mo.Expression, mo.Value, i, argType); } return res; }
private Expression MakeCall(ArgumentMarshaller[] signature, INativeType nativeRetType, bool retVoid) { List<object> constantPool = new List<object>(); MethodInfo interopInvoker = CreateInteropInvoker( GetCallingConvention(), signature, nativeRetType, retVoid, constantPool ); // build the args - IntPtr, user Args, constant pool Expression[] callArgs = new Expression[signature.Length + 2]; callArgs[0] = Expression.Property( Expression.Convert(Expression, typeof(_CFuncPtr)), "addr" ); for (int i = 0; i < signature.Length; i++) { callArgs[i + 1] = signature[i].ArgumentExpression; } callArgs[callArgs.Length - 1] = Expression.Constant(constantPool.ToArray()); return Expression.Call(interopInvoker, callArgs); }
/// <summary> /// we need to keep alive any methods which have arguments for the duration of the /// call. Otherwise they could be collected on the finalizer thread before we come back. /// </summary> private void AddKeepAlives(ArgumentMarshaller[] signature, List<Expression> block) { foreach (ArgumentMarshaller marshaller in signature) { Expression keepAlive = marshaller.GetKeepAlive(); if (keepAlive != null) { block.Add(keepAlive); } } }
private ArgumentMarshaller/*!*/[]/*!*/ GetArgumentMarshallers(DynamicMetaObject/*!*/[]/*!*/ args) { CFuncPtrType funcType = ((CFuncPtrType)Value.NativeType); ArgumentMarshaller[] res = new ArgumentMarshaller[args.Length]; // first arg is taken by self if we're a com method for (int i = 0; i < args.Length; i++) { DynamicMetaObject mo = args[i]; object argType = null; if (Value._comInterfaceIndex == -1 || i != 0) { int argtypeIndex = Value._comInterfaceIndex == -1 ? i : i - 1; if (Value._argtypes != null && argtypeIndex < Value._argtypes.Count) { argType = Value._argtypes[argtypeIndex]; } else if (funcType._argtypes != null && argtypeIndex < funcType._argtypes.Length) { argType = funcType._argtypes[argtypeIndex]; } } res[i] = GetMarshaller(mo.Expression, mo.Value, i, argType); } return res; }