Beispiel #1
0
            public PointerType(CodeContext/*!*/ context, string name, PythonTuple bases, IAttributesCollection members)
                : base(context, name, bases, members) {

                object type;
                if (members.TryGetValue(SymbolTable.StringToId("_type_"), out type) && !(type is INativeType)) {
                    throw PythonOps.TypeError("_type_ must be a type");
                }
                _type = (INativeType)type;
            }
Beispiel #2
0
            internal Field(INativeType fieldType, int offset, int index, int? bits, int? bitOffset) {
                _offset = offset;
                _fieldType = fieldType;
                _index = index;

                if (bits != null) {
                    _bits = bits.Value;
                    _bitsOffset = bitOffset.Value;
                }
            }
Beispiel #3
0
            public ArrayType(CodeContext/*!*/ context, string name, PythonTuple bases, IAttributesCollection dict)
                : base(context, name, bases, dict) {
                object len;
                int iLen;
                if (!dict.TryGetValue(SymbolTable.StringToId("_length_"), out len) || !(len is int) || (iLen = (int)len) < 0) {
                    throw PythonOps.AttributeError("arrays must have _length_ attribute and it must be a positive integer");
                }

                object type;
                if (!dict.TryGetValue(SymbolTable.StringToId("_type_"), out type)) {
                    throw PythonOps.AttributeError("class must define a '_type_' attribute");
                }

                _length = iLen;
                _type = (INativeType)type;

                if (_type is SimpleType) {
                    SimpleType st = (SimpleType)_type;
                    if (st._type == SimpleTypeKind.Char) {
                        // TODO: (c_int * 2).value isn't working
                        SetCustomMember(context,
                            SymbolTable.StringToId("value"),
                            new ReflectedExtensionProperty(
                                new ExtensionPropertyInfo(this, typeof(CTypes).GetMethod("GetCharArrayValue")),
                                NameType.Property | NameType.Python
                            )
                        );

                        SetCustomMember(context,
                            SymbolTable.StringToId("raw"),
                            new ReflectedExtensionProperty(
                                new ExtensionPropertyInfo(this, typeof(CTypes).GetMethod("GetWCharArrayRaw")),
                                NameType.Property | NameType.Python
                            )
                        );
                    } else if (st._type == SimpleTypeKind.WChar) {
                        SetCustomMember(context,
                            SymbolTable.StringToId("value"),
                            new ReflectedExtensionProperty(
                                new ExtensionPropertyInfo(this, typeof(CTypes).GetMethod("GetWCharArrayValue")),
                                NameType.Property | NameType.Python
                            )
                        );

                        SetCustomMember(context,
                            SymbolTable.StringToId("raw"),
                            new ReflectedExtensionProperty(
                                new ExtensionPropertyInfo(this, typeof(CTypes).GetMethod("GetWCharArrayRaw")),
                                NameType.Property | NameType.Python
                            )
                        );
                    }
                }
            }
Beispiel #4
0
            public PointerType(CodeContext/*!*/ context, string name, PythonTuple bases, PythonDictionary members)
                : base(context, name, bases, members) {

                object type;
                if (members.TryGetValue("_type_", out type) && !(type is INativeType)) {
                    throw PythonOps.TypeError("_type_ must be a type");
                }
                _type = (INativeType)type;
                if (_type != null) {
                    _typeFormat = _type.TypeFormat;
                }
            }
                private Expression MakeCall(ArgumentMarshaller[] signature, INativeType nativeRetType, bool retVoid, Expression address)
                {
                    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] = address;

                    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));
                }
Beispiel #6
0
            internal static void AddAnonymousFields(PythonType type, List<Field> allFields, INativeType cdata, Field newField) {
                Field[] childFields;
                if (cdata is StructType) {
                    childFields = ((StructType)cdata)._fields;
                } else if (cdata is UnionType) {
                    childFields = ((UnionType)cdata)._fields;
                } else {
                    throw PythonOps.TypeError("anonymous field must be struct or union");
                }

                foreach (Field existingField in childFields) {
                    Field anonField = new Field(
                        existingField.FieldName,
                        existingField.NativeType,
                        checked(existingField.offset + newField.offset),
                        allFields.Count
                    );

                    type.AddSlot(SymbolTable.StringToId(existingField.FieldName), anonField);
                    allFields.Add(anonField);
                }
            }
Beispiel #7
0
            public ArrayType(CodeContext /*!*/ context, string name, PythonTuple bases, PythonDictionary dict)
                : base(context, name, bases, dict)
            {
                object len;
                int    iLen;

                if (!dict.TryGetValue("_length_", out len) || !(len is int) || (iLen = (int)len) < 0)
                {
                    throw PythonOps.AttributeError("arrays must have _length_ attribute and it must be a positive integer");
                }

                object type;

                if (!dict.TryGetValue("_type_", out type))
                {
                    throw PythonOps.AttributeError("class must define a '_type_' attribute");
                }

                _length = iLen;
                _type   = (INativeType)type;

                if (_type is SimpleType)
                {
                    SimpleType st = (SimpleType)_type;
                    if (st._type == SimpleTypeKind.Char)
                    {
                        // TODO: (c_int * 2).value isn't working
                        SetCustomMember(context,
                                        "value",
                                        new ReflectedExtensionProperty(
                                            new ExtensionPropertyInfo(this, typeof(CTypes).GetMethod("GetCharArrayValue")),
                                            NameType.Property | NameType.Python
                                            )
                                        );

                        SetCustomMember(context,
                                        "raw",
                                        new ReflectedExtensionProperty(
                                            new ExtensionPropertyInfo(this, typeof(CTypes).GetMethod("GetWCharArrayRaw")),
                                            NameType.Property | NameType.Python
                                            )
                                        );
                    }
                    else if (st._type == SimpleTypeKind.WChar)
                    {
                        SetCustomMember(context,
                                        "value",
                                        new ReflectedExtensionProperty(
                                            new ExtensionPropertyInfo(this, typeof(CTypes).GetMethod("GetWCharArrayValue")),
                                            NameType.Property | NameType.Python
                                            )
                                        );

                        SetCustomMember(context,
                                        "raw",
                                        new ReflectedExtensionProperty(
                                            new ExtensionPropertyInfo(this, typeof(CTypes).GetMethod("GetWCharArrayRaw")),
                                            NameType.Property | NameType.Python
                                            )
                                        );
                    }
                }
            }
Beispiel #8
0
 internal Field(INativeType fieldType, int offset, int index) {
     _offset = offset;
     _fieldType = fieldType;
     _index = index;
 }
Beispiel #9
0
        /// <summary>
        /// Emits the marshalling code to create a CData object for reverse marshalling.
        /// </summary>
        private static void EmitCDataCreation(INativeType type, ILGenerator method, List<object> constantPool, int constantPoolArgument) {
            LocalBuilder locVal = method.DeclareLocal(type.GetNativeType());
            method.Emit(OpCodes.Stloc, locVal);
            method.Emit(OpCodes.Ldloca, locVal);

            constantPool.Add(type);
            method.Emit(OpCodes.Ldarg, constantPoolArgument);
            method.Emit(OpCodes.Ldc_I4, constantPool.Count - 1);
            method.Emit(OpCodes.Ldelem_Ref);

            method.Emit(OpCodes.Call, typeof(ModuleOps).GetMethod("CreateCData"));
        }
Beispiel #10
0
        /// <summary>
        /// Shared helper between struct and union for getting field info and validating it.
        /// </summary>
        private static void GetFieldInfo(INativeType type, object o, out string fieldName, out INativeType cdata, out int? bitCount) {
            PythonTuple pt = o as PythonTuple;
            if (pt.Count != 2 && pt.Count != 3) {
                throw PythonOps.AttributeError("'_fields_' must be a sequence of pairs");
            }

            fieldName = pt[0] as string;
            if (fieldName == null) {
                throw PythonOps.TypeError("first item in _fields_ tuple must be a string, got", PythonTypeOps.GetName(pt[0]));
            }

            cdata = pt[1] as INativeType;
            if (cdata == null) {
                throw PythonOps.TypeError("second item in _fields_ tuple must be a C type, got {0}", PythonTypeOps.GetName(pt[0]));
            } else if (cdata == type) {
                throw StructureCannotContainSelf();
            }

            StructType st = cdata as StructType;
            if (st != null) {
                st.EnsureFinal();
            }

            if (pt.Count != 3) {
                bitCount = null;
            } else {
                bitCount = CheckBits(cdata, pt);
            }
        }
Beispiel #11
0
            private void MakeReverseDelegateWorker(CodeContext context)
            {
                Type[] sigTypes;
                Type[] callSiteType;
                Type   retType;

                GetSignatureInfo(out sigTypes, out callSiteType, out retType);

                DynamicMethod dm    = new DynamicMethod("ReverseInteropInvoker", retType, ArrayUtils.RemoveLast(sigTypes), DynamicModule);
                ILGenerator   ilGen = dm.GetILGenerator();
                PythonContext pc    = context.LanguageContext;

                Type     callDelegateSiteType = CompilerHelpers.MakeCallSiteDelegateType(callSiteType);
                CallSite site = CallSite.Create(callDelegateSiteType, pc.Invoke(new CallSignature(_argtypes.Length)));

                List <object> constantPool = new List <object>();

                constantPool.Add(null); // 1st item is the target object, will be put in later.
                constantPool.Add(site);

                ilGen.BeginExceptionBlock();

                //CallSite<Func<CallSite, object, object>> mySite;
                //mySite.Target(mySite, target, ...);

                LocalBuilder siteLocal = ilGen.DeclareLocal(site.GetType());

                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldc_I4, constantPool.Count - 1);
                ilGen.Emit(OpCodes.Ldelem_Ref);
                ilGen.Emit(OpCodes.Castclass, site.GetType());
                ilGen.Emit(OpCodes.Stloc, siteLocal);
                ilGen.Emit(OpCodes.Ldloc, siteLocal);
                ilGen.Emit(OpCodes.Ldfld, site.GetType().GetField("Target"));
                ilGen.Emit(OpCodes.Ldloc, siteLocal);

                // load code context
                int contextIndex = constantPool.Count;

                Debug.Assert(pc.SharedContext != null);
                constantPool.Add(pc.SharedContext);
                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldc_I4, contextIndex);
                ilGen.Emit(OpCodes.Ldelem_Ref);

                // load function target, in constant pool slot 0
                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldc_I4_0);
                ilGen.Emit(OpCodes.Ldelem_Ref);

                // load arguments
                for (int i = 0; i < _argtypes.Length; i++)
                {
                    INativeType nativeType = _argtypes[i];
                    nativeType.EmitReverseMarshalling(ilGen, new Arg(i + 1, sigTypes[i + 1]), constantPool, 0);
                }

                ilGen.Emit(OpCodes.Call, callDelegateSiteType.GetMethod("Invoke"));

                LocalBuilder finalRes = null;

                // emit forward marshaling for return value
                if (_restype != null)
                {
                    LocalBuilder tmpRes = ilGen.DeclareLocal(typeof(object));
                    ilGen.Emit(OpCodes.Stloc, tmpRes);
                    finalRes = ilGen.DeclareLocal(retType);

                    ((INativeType)_restype).EmitMarshalling(ilGen, new Local(tmpRes), constantPool, 0);
                    ilGen.Emit(OpCodes.Stloc, finalRes);
                }
                else
                {
                    ilGen.Emit(OpCodes.Pop);
                }

                // } catch(Exception e) {
                // emit the cleanup code

                ilGen.BeginCatchBlock(typeof(Exception));

                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldc_I4, contextIndex);
                ilGen.Emit(OpCodes.Ldelem_Ref);
                ilGen.Emit(OpCodes.Call, typeof(ModuleOps).GetMethod("CallbackException"));

                ilGen.EndExceptionBlock();

                if (_restype != null)
                {
                    ilGen.Emit(OpCodes.Ldloc, finalRes);
                }
                ilGen.Emit(OpCodes.Ret);

                _reverseDelegateConstants = constantPool;
                _reverseDelegateType      = GetReverseDelegateType(ArrayUtils.RemoveFirst(sigTypes), CallingConvention);
                _reverseDelegate          = dm;
            }
Beispiel #12
0
 public CDataMarshaller(Expression /*!*/ container, Type /*!*/ type, INativeType /*!*/ cdataType)
     : base(container)
 {
     _type      = type;
     _cdataType = cdataType;
 }
Beispiel #13
0
 public void set_type(PythonType type) {
     _type = (INativeType)type;
 }
Beispiel #14
0
            public object this[Slice index] {
                get {
                    if (index.stop == null)
                    {
                        throw PythonOps.ValueError("slice stop is required");
                    }

                    int start = index.start != null ? (int)index.start : 0;
                    int stop  = index.stop != null ? (int)index.stop : 0;
                    int step  = index.step != null ? (int)index.step : 1;

                    if (step < 0 && index.start == null)
                    {
                        throw PythonOps.ValueError("slice start is required for step < 0");
                    }

                    if (start < 0)
                    {
                        start = 0;
                    }
                    INativeType type     = ((PointerType)NativeType)._type;
                    SimpleType  elemType = type as SimpleType;

                    if ((stop < start && step > 0) || (start < stop && step < 0))
                    {
                        if (elemType != null)
                        {
                            if (elemType._type == SimpleTypeKind.Char)
                            {
                                return(Bytes.Empty);
                            }
                            if (elemType._type == SimpleTypeKind.WChar)
                            {
                                return(string.Empty);
                            }
                        }
                        return(new PythonList());
                    }

                    MemoryHolder address = MemHolder.ReadMemoryHolder(0);
                    if (elemType != null)
                    {
                        if (elemType._type == SimpleTypeKind.Char)
                        {
                            Debug.Assert(((INativeType)elemType).Size == 1);
                            var sb = new MemoryStream();

                            for (int i = start; stop > start ? i <stop : i> stop; i += step)
                            {
                                sb.WriteByte(address.ReadByte(i));
                            }

                            return(Bytes.Make(sb.ToArray()));
                        }
                        if (elemType._type == SimpleTypeKind.WChar)
                        {
                            int elmSize = ((INativeType)elemType).Size;
                            var sb      = new StringBuilder();

                            for (int i = start; stop > start ? i <stop : i> stop; i += step)
                            {
                                sb.Append((char)address.ReadInt16(checked (i * elmSize)));
                            }

                            return(sb.ToString());
                        }
                    }

                    PythonList res = new PythonList((stop - start) / step);
                    for (int i = start; stop > start ? i <stop : i> stop; i += step)
                    {
                        res.AddNoLock(
                            type.GetValue(address, this, checked (type.Size * i), false)
                            );
                    }
                    return(res);
                }
            }
Beispiel #15
0
            private int UpdateSizeAndAlignment(INativeType cdata, int? bitCount, INativeType lastType, ref int size, ref int alignment, ref int? totalBitCount) {
                int prevSize = size;
                if (bitCount != null) {
                    if (lastType != null && lastType.Size != cdata.Size) {
                        totalBitCount = null;
                        prevSize = size += lastType.Size;
                    }

                    size = PythonStruct.Align(size, cdata.Alignment);

                    if (totalBitCount != null) {
                        if ((bitCount + totalBitCount + 7) / 8 <= cdata.Size) {
                            totalBitCount = bitCount + totalBitCount;
                        } else {
                            size += lastType.Size;
                            prevSize = size;
                            totalBitCount = bitCount;
                        }
                    } else {
                        totalBitCount = bitCount;
                    }
                } else {
                    if (totalBitCount != null) {
                        size += lastType.Size;
                        prevSize = size;
                        totalBitCount = null;
                    }

                    if (_pack != null) {
                        alignment = _pack.Value;
                        prevSize = size = PythonStruct.Align(size, _pack.Value);

                        size += cdata.Size;
                    } else {
                        alignment = Math.Max(alignment, cdata.Alignment);
                        prevSize = size = PythonStruct.Align(size, cdata.Alignment);
                        size += cdata.Size;
                    }
                }

                return prevSize;
            }
Beispiel #16
0
                /// <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
                }
Beispiel #17
0
 internal Field(string fieldName, INativeType fieldType, int offset, int index) {
     _offset = offset;
     _fieldType = fieldType;
     _index = index;
     _fieldName = fieldName;
 }
Beispiel #18
0
                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);
                }
Beispiel #19
0
                /// <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
                }
 public void set_type(PythonType type)
 {
     _type = (INativeType)type;
 }
Beispiel #21
0
 public CDataMarshaller(Expression/*!*/ container, Type/*!*/ type, INativeType/*!*/cdataType)
     : base(container) {
     _type = type;
     _cdataType = cdataType;
 }
Beispiel #22
0
        /// <summary>
        /// Verifies that the provided bit field settings are valid for this type.
        /// </summary>
        private static int CheckBits(INativeType cdata, PythonTuple pt) {
            int bitCount = Converter.ConvertToInt32(pt[2]);

            SimpleType simpType = cdata as SimpleType;
            if (simpType == null) {
                throw PythonOps.TypeError("bit fields not allowed for type {0}", ((PythonType)cdata).Name);
            }

            switch (simpType._type) {
                case SimpleTypeKind.Object:
                case SimpleTypeKind.Pointer:
                case SimpleTypeKind.Single:
                case SimpleTypeKind.Double:
                case SimpleTypeKind.Char:
                case SimpleTypeKind.CharPointer:
                case SimpleTypeKind.WChar:
                case SimpleTypeKind.WCharPointer:
                    throw PythonOps.TypeError("bit fields not allowed for type {0}", ((PythonType)cdata).Name);
            }

            if (bitCount <= 0 || bitCount > cdata.Size * 8) {
                throw PythonOps.ValueError("number of bits invalid for bit field");
            }
            return bitCount;
        }
Beispiel #23
0
        /// <summary>
        /// Shared helper between struct and union for getting field info and validating it.
        /// </summary>
        private static void GetFieldInfo(INativeType type, object o, out string fieldName, out INativeType cdata, out int?bitCount)
        {
            PythonTuple pt = o as PythonTuple;

            if (pt.Count != 2 && pt.Count != 3)
            {
                throw PythonOps.AttributeError("'_fields_' must be a sequence of pairs");
            }

            fieldName = pt[0] as string;
            if (fieldName == null)
            {
                throw PythonOps.TypeError("first item in _fields_ tuple must be a string, got", PythonTypeOps.GetName(pt[0]));
            }

            cdata = pt[1] as INativeType;
            if (cdata == null)
            {
                throw PythonOps.TypeError("second item in _fields_ tuple must be a C type, got {0}", PythonTypeOps.GetName(pt[0]));
            }
            else if (cdata == type)
            {
                throw StructureCannotContainSelf();
            }

            StructType st = cdata as StructType;

            if (st != null)
            {
                st.EnsureFinal();
            }

            if (pt.Count != 3)
            {
                bitCount = null;
            }
            else
            {
                bitCount = CheckBits(cdata, pt);
            }
        }
Beispiel #24
0
            internal static void AddAnonymousFields(PythonType type, List <Field> allFields, INativeType cdata, Field newField)
            {
                Field[] childFields;
                if (cdata is StructType)
                {
                    childFields = ((StructType)cdata)._fields;
                }
                else if (cdata is UnionType)
                {
                    childFields = ((UnionType)cdata)._fields;
                }
                else
                {
                    throw PythonOps.TypeError("anonymous field must be struct or union");
                }

                foreach (Field existingField in childFields)
                {
                    Field anonField = new Field(
                        existingField.FieldName,
                        existingField.NativeType,
                        checked (existingField.offset + newField.offset),
                        allFields.Count
                        );

                    type.AddSlot(existingField.FieldName, anonField);
                    allFields.Add(anonField);
                }
            }
Beispiel #25
0
                private ArgumentMarshaller/*!*/ GetMarshaller(Expression/*!*/ expr, object value, int index, INativeType nativeType) {
                    if (nativeType != null) {
                        return new CDataMarshaller(expr, CompilerHelpers.GetType(value), nativeType);
                    }

                    CData data = value as CData;
                    if (data != null) {
                        return new CDataMarshaller(expr, CompilerHelpers.GetType(value), data.NativeType);
                    }

                    NativeArgument arg = value as NativeArgument;
                    if (arg != null) {
                        return new NativeArgumentMarshaller(expr, value.GetType());
                    }

                    object val;
                    if (PythonOps.TryGetBoundAttr(value, SymbolTable.StringToId("_as_parameter_"), out val)) {
                        throw new NotImplementedException("_as_parameter");
                        //return new UserDefinedMarshaller(GetMarshaller(..., value, index));                    
                    }

                    // Marshalling primitive or an object
                    return new PrimitiveMarshaller(expr, CompilerHelpers.GetType(value));
                }