示例#1
0
            MarshalCleanup INativeType.EmitMarshalling(ILGenerator /*!*/ method, LocalOrArg argIndex, List <object> /*!*/ constantPool, int constantPoolArgument)
            {
                MarshalCleanup cleanup      = null;
                Label          marshalled   = method.DefineLabel();
                Type           argumentType = argIndex.Type;

                if (!argumentType.IsValueType && _type != SimpleTypeKind.Object && _type != SimpleTypeKind.Pointer)
                {
                    // check if we have an explicit CData instance.  If we have a CData but it's the
                    // wrong type CheckSimpleCDataType will throw.
                    Label primitive = method.DefineLabel();

                    argIndex.Emit(method);

                    constantPool.Add(this);
                    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("CheckSimpleCDataType"));
                    method.Emit(OpCodes.Brfalse, primitive);

                    argIndex.Emit(method);
                    method.Emit(OpCodes.Castclass, typeof(CData));
                    method.Emit(OpCodes.Call, typeof(CData).GetMethod("get_UnsafeAddress"));
                    method.Emit(OpCodes.Ldobj, ((INativeType)this).GetNativeType());
                    method.Emit(OpCodes.Br, marshalled);

                    method.MarkLabel(primitive);
                }

                argIndex.Emit(method);
                if (argumentType.IsValueType)
                {
                    method.Emit(OpCodes.Box, argumentType);
                }
                switch (_type)
                {
                case SimpleTypeKind.Boolean:
                case SimpleTypeKind.Char:
                case SimpleTypeKind.SignedByte:
                case SimpleTypeKind.UnsignedByte:
                case SimpleTypeKind.SignedShort:
                case SimpleTypeKind.UnsignedShort:
                case SimpleTypeKind.WChar:
                case SimpleTypeKind.SignedInt:
                case SimpleTypeKind.UnsignedInt:
                case SimpleTypeKind.UnsignedLong:
                case SimpleTypeKind.SignedLong:
                case SimpleTypeKind.Single:
                case SimpleTypeKind.Double:
                case SimpleTypeKind.UnsignedLongLong:
                case SimpleTypeKind.SignedLongLong:
                case SimpleTypeKind.VariantBool:
                    constantPool.Add(this);
                    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("Get" + _type));
                    break;

                case SimpleTypeKind.Pointer:
                    Label done = method.DefineLabel();
                    TryBytesConversion(method, done);


                    Label nextTry = method.DefineLabel();
                    argIndex.Emit(method);
                    if (argumentType.IsValueType)
                    {
                        method.Emit(OpCodes.Box, argumentType);
                    }

                    method.Emit(OpCodes.Isinst, typeof(string));
                    method.Emit(OpCodes.Dup);
                    method.Emit(OpCodes.Brfalse, nextTry);

                    LocalBuilder lb = method.DeclareLocal(typeof(string), true);
                    method.Emit(OpCodes.Stloc, lb);
                    method.Emit(OpCodes.Ldloc, lb);
                    method.Emit(OpCodes.Conv_I);
                    method.Emit(OpCodes.Ldc_I4, RuntimeHelpers.OffsetToStringData);
                    method.Emit(OpCodes.Add);
                    method.Emit(OpCodes.Br, done);

                    method.MarkLabel(nextTry);
                    method.Emit(OpCodes.Pop);

                    argIndex.Emit(method);
                    if (argumentType.IsValueType)
                    {
                        method.Emit(OpCodes.Box, argumentType);
                    }

                    method.Emit(OpCodes.Call, typeof(ModuleOps).GetMethod("GetPointer"));

                    method.MarkLabel(done);
                    break;

                case SimpleTypeKind.Object:
                    // TODO: Need cleanup here
                    method.Emit(OpCodes.Call, typeof(CTypes).GetMethod("PyObj_ToPtr"));
                    break;

                case SimpleTypeKind.CharPointer:
                    done = method.DefineLabel();
                    TryToCharPtrConversion(method, argIndex, argumentType, done);

                    cleanup = MarshalCharPointer(method, argIndex);

                    method.MarkLabel(done);
                    break;

                case SimpleTypeKind.WCharPointer:
                    done = method.DefineLabel();
                    TryArrayToWCharPtrConversion(method, argIndex, argumentType, done);

                    MarshalWCharPointer(method, argIndex);

                    method.MarkLabel(done);
                    break;

                case SimpleTypeKind.BStr:
                    throw new NotImplementedException("BSTR marshalling");
                }

                method.MarkLabel(marshalled);
                return(cleanup);
            }