예제 #1
0
            MarshalCleanup INativeType.EmitMarshalling(ILGenerator /*!*/ method, LocalOrArg argIndex, List <object> /*!*/ constantPool, int constantPoolArgument)
            {
                Type  argumentType = argIndex.Type;
                Label nextTry      = method.DefineLabel();
                Label done         = method.DefineLabel();

                if (!argumentType.IsValueType)
                {
                    argIndex.Emit(method);
                    method.Emit(OpCodes.Ldnull);
                    method.Emit(OpCodes.Bne_Un, nextTry);
                    method.Emit(OpCodes.Ldc_I4_0);
                    method.Emit(OpCodes.Conv_I);
                    method.Emit(OpCodes.Br, done);
                }

                method.MarkLabel(nextTry);
                nextTry = method.DefineLabel();

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

                SimpleType     st  = _type as SimpleType;
                MarshalCleanup res = null;

                if (st != null && !argIndex.Type.IsValueType)
                {
                    if (st._type == SimpleTypeKind.Char || st._type == SimpleTypeKind.WChar)
                    {
                        if (st._type == SimpleTypeKind.Char)
                        {
                            SimpleType.TryToCharPtrConversion(method, argIndex, argumentType, done);
                        }
                        else
                        {
                            SimpleType.TryArrayToWCharPtrConversion(method, argIndex, argumentType, done);
                        }

                        Label      notStr = method.DefineLabel();
                        LocalOrArg str    = argIndex;
                        if (argumentType != typeof(string))
                        {
                            LocalBuilder lb = method.DeclareLocal(typeof(string));
                            method.Emit(OpCodes.Isinst, typeof(string));
                            method.Emit(OpCodes.Brfalse, notStr);
                            argIndex.Emit(method);
                            method.Emit(OpCodes.Castclass, typeof(string));
                            method.Emit(OpCodes.Stloc, lb);
                            method.Emit(OpCodes.Ldloc, lb);
                            str = new Local(lb);
                        }

                        if (st._type == SimpleTypeKind.Char)
                        {
                            res = SimpleType.MarshalCharPointer(method, str);
                        }
                        else
                        {
                            SimpleType.MarshalWCharPointer(method, str);
                        }
                        method.Emit(OpCodes.Br, done);
                        method.MarkLabel(notStr);
                        argIndex.Emit(method);
                    }
                }

                // native argument being pased (byref)
                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("CheckNativeArgument"));
                method.Emit(OpCodes.Dup);
                method.Emit(OpCodes.Brfalse, nextTry);
                method.Emit(OpCodes.Call, typeof(CData).GetMethod("get_UnsafeAddress"));
                method.Emit(OpCodes.Br, done);

                // lone cdata being passed
                method.MarkLabel(nextTry);
                nextTry = method.DefineLabel();
                method.Emit(OpCodes.Pop);   // extra null native arg
                argIndex.Emit(method);
                if (argumentType.IsValueType)
                {
                    method.Emit(OpCodes.Box, argumentType);
                }
                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("TryCheckCDataPointerType"));
                method.Emit(OpCodes.Dup);
                method.Emit(OpCodes.Brfalse, nextTry);
                method.Emit(OpCodes.Call, typeof(CData).GetMethod("get_UnsafeAddress"));
                method.Emit(OpCodes.Br, done);

                // pointer object being passed
                method.MarkLabel(nextTry);
                method.Emit(OpCodes.Pop);   // extra null cdata
                argIndex.Emit(method);
                if (argumentType.IsValueType)
                {
                    method.Emit(OpCodes.Box, argumentType);
                }
                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("CheckCDataType"));
                method.Emit(OpCodes.Call, typeof(CData).GetMethod("get_UnsafeAddress"));
                method.Emit(OpCodes.Ldind_I);

                method.MarkLabel(done);
                return(res);
            }