Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/net_ure/source/bridge/native/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 28 kB image not shown  

Quelle  Marshaller.cs   Sprache: CS

 
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using com.sun.star.uno.helper;

namespace com.sun.star.uno.native
{
    internal class Marshaller
    {
        private readonly NetEnvironment _env;
        public Marshaller(NetEnvironment env) => _env = env;

        public unsafe void MarshalObject(Type type, object src, InteropValue* value, bool destructValue)
            => MarshalObject(type, src, (void*)value, destructValue);

        public unsafe void UnmarshalObject(Type type, ref object dst, InteropValue* value, bool assignObject)
            => UnmarshalObject(type, ref dst, (void*)value, assignObject);

        private unsafe void MarshalObject(Type type, object source, void* value, bool destructValue)
        {
            switch (Type.GetTypeCode(type))
            {
                case TypeCode.Boolean:
                    *(byte*)value = (byte)((bool)source ? 1 : 0);
                    break;
                case TypeCode.SByte:
                    *(sbyte*)value = (sbyte)source;
                    break;
                case TypeCode.Char:
                    *(char*)value = (char)source;
                    break;
                case TypeCode.Int16:
                    *(short*)value = (short)source;
                    break;
                case TypeCode.UInt16:
                    *(ushort*)value = (ushort)source;
                    break;
                case TypeCode.Int32:
                    *(int*)value = (int)source;
                    break;
                case TypeCode.UInt32:
                    *(uint*)value = (uint)source;
                    break;
                case TypeCode.Int64:
                    *(long*)value = (long)source;
                    break;
                case TypeCode.UInt64:
                    *(ulong*)value = (ulong)source;
                    break;
                case TypeCode.Single:
                    *(float*)value = (float)source;
                    break;
                case TypeCode.Double:
                    *(double*)value = (double)source;
                    break;
                case TypeCode.String:
                    {
                        IntPtr* valueStr = (IntPtr*)value;
                        string netStr = (string)source;

                        if (destructValue && *valueStr != IntPtr.Zero)
                            InteropMethods.freeMemory(*valueStr);

                        *valueStr = MarshalString(netStr);
                        break;
                    }
                default:
                    if (type == typeof(void))
                    {
                        *(IntPtr*)value = IntPtr.Zero;
                    }
                    else if (type == typeof(Type))
                    {
                        IntPtr* valueType = (IntPtr*)value;
                        Type netType = (Type)source;

                        if (destructValue && *valueType != IntPtr.Zero)
                            InteropMethods.freeMemory(*valueType);
                        *valueType = MarshalString(netType.FullName);
                    }
                    else if (type == typeof(Any))
                    {
                        InteropValue.Any* valueAny = (InteropValue.Any*)value;
                        Any netAny = (Any)source;

                        switch (Type.GetTypeCode(netAny.Type))
                        {
                            case TypeCode.Boolean:
                            case TypeCode.SByte:
                            case TypeCode.Char:
                            case TypeCode.Int16:
                            case TypeCode.UInt16:
                            case TypeCode.Int32:
                            case TypeCode.UInt32:
                            case TypeCode.Single:
                                MarshalObject(netAny.Type, netAny.Value, (void*)&valueAny->data, destructValue);
                                break;
                            case TypeCode.Int64:
                            case TypeCode.UInt64:
                            case TypeCode.Double:
                                {
                                    int size = SizeOf(netAny.Type);
                                    if (size <= IntPtr.Size)
                                        MarshalObject(netAny.Type, netAny.Value, (void*)&valueAny->data, destructValue);
                                    else
                                    {
                                        IntPtr mem = InteropMethods.allocateMemory(size);
                                        MarshalObject(netAny.Type, netAny.Value, (void*)mem, false);
                                        if (destructValue)
                                            InteropMethods.freeMemory(valueAny->data);
                                        valueAny->data = mem;
                                    }
                                    break;
                                }
                            default:
                                if (netAny.Type == typeof(Any) || netAny.Type.IsArray)
                                {
                                    IntPtr mem = InteropMethods.allocateMemory(SizeOf(netAny.Type));
                                    MarshalObject(netAny.Type, netAny.Value, (void*)mem, false);
                                    if (destructValue)
                                        InteropMethods.freeMemory(valueAny->data);
                                    valueAny->data = mem;
                                }
                                else
                                {
                                    MarshalObject(netAny.Type, netAny.Value, (void*)&valueAny->data, destructValue);
                                }
                                break;
                        }

                        MarshalObject(typeof(Type), netAny.Type, (void*)&valueAny->type, destructValue);
                    }
                    else if (type.IsEnum)
                    {
                        *(int*)value = (int)source;
                    }
                    else if (type.IsArray)
                    {
                        InteropValue.Sequence* valueSeq = (InteropValue.Sequence*)value;
                        Array netArray = (Array)source;

                        Type elemType = type.GetElementType();
                        int elemSize = SizeOf(elemType);

                        int memSize = elemSize * netArray.Length;
                        IntPtr mem = InteropMethods.allocateMemory(memSize);

                        switch (Type.GetTypeCode(elemType))
                        {
                            case TypeCode.Boolean:
                                fixed (void* src = (bool[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.SByte:
                                fixed (void* src = (sbyte[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.Char:
                                fixed (void* src = (char[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.Int16:
                                fixed (void* src = (short[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.UInt16:
                                fixed (void* src = (ushort[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.Int32:
                                fixed (void* src = (int[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.UInt32:
                                fixed (void* src = (uint[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.Int64:
                                fixed (void* src = (long[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.UInt64:
                                fixed (void* src = (ulong[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.Single:
                                fixed (void* src = (float[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            case TypeCode.Double:
                                fixed (void* src = (double[])netArray)
                                    Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                break;
                            default:
                                if (elemType.IsEnum)
                                {
                                    fixed (void* src = (int[])netArray)
                                        Buffer.MemoryCopy(src, (void*)mem, memSize, memSize);
                                }
                                else
                                {
                                    for (int i = 0; i < netArray.Length; i++)
                                        MarshalObject(elemType, netArray.GetValue(i), (void*)(mem + elemSize * i), destructValue);
                                }
                                break;
                        }

                        if (destructValue && valueSeq->data != IntPtr.Zero)
                            InteropMethods.freeMemory(valueSeq->data);

                        valueSeq->data = mem;
                        valueSeq->length = netArray.Length;
                    }
                    else if (typeof(IQueryInterface).IsAssignableFrom(type))
                    {
                        *(IntPtr*)value = source is NativeUnoProxy nup
                            ? _env.LookupInterface(nup.Oid, nup.Type)
                            : _env.RegisterLocal(source, type);
                    }
                    else
                    {
                        IntPtr* valueStruct = (IntPtr*)value;

                        (Action<objectobject[]> dtor, Type[] fieldTypes) = StructHelper.GetDeconstructor(type);
                        object[] fields = new object[fieldTypes.Length];
                        dtor.Invoke(source, fields);

                        IntPtr mem = InteropMethods.allocateMemory(fieldTypes.Sum(SizeOf));

                        int offset = 0;
                        for (int i = 0; i < fieldTypes.Length; i++)
                        {
                            MarshalObject(fieldTypes[i], fields[i], (void*)(mem + offset), destructValue);
                            offset += SizeOf(fieldTypes[i]);
                        }

                        if (destructValue && *valueStruct != IntPtr.Zero)
                            InteropMethods.freeMemory(*valueStruct);

                        *valueStruct = mem;
                    }
                    break;
            }
        }

        private unsafe void UnmarshalObject(Type type, ref object target, void* value, bool assignObject)
        {
            switch (Type.GetTypeCode(type))
            {
                case TypeCode.Boolean:
                    if (assignObject)
                        target = *(byte*)value != 0;
                    break;
                case TypeCode.SByte:
                    if (assignObject)
                        target = *(byte*)value;
                    break;
                case TypeCode.Char:
                    if (assignObject)
                        target = *(char*)value;
                    break;
                case TypeCode.Int16:
                    if (assignObject)
                        target = *(short*)value;
                    break;
                case TypeCode.UInt16:
                    if (assignObject)
                        target = *(ushort*)value;
                    break;
                case TypeCode.Int32:
                    if (assignObject)
                        target = *(int*)value;
                    break;
                case TypeCode.UInt32:
                    if (assignObject)
                        target = *(uint*)value;
                    break;
                case TypeCode.Int64:
                    if (assignObject)
                        target = *(long*)value;
                    break;
                case TypeCode.UInt64:
                    if (assignObject)
                        target = *(ulong*)value;
                    break;
                case TypeCode.Single:
                    if (assignObject)
                        target = *(float*)value;
                    break;
                case TypeCode.Double:
                    if (assignObject)
                        target = *(double*)value;
                    break;
                case TypeCode.String:
                    {
                        IntPtr valueStr = *(IntPtr*)value;
                        if (assignObject)
                            target = UnmarshalString(valueStr);
                        else
                            InteropMethods.freeMemory(valueStr);
                    }
                    break;
                default:
                    if (type == typeof(void))
                    {
                        if (assignObject)
                            target = null;
                    }
                    else if (type == typeof(Type))
                    {
                        IntPtr valueType = *(IntPtr*)value;
                        if (assignObject)
                            target = TypeHelper.ParseType(UnmarshalString(valueType));
                        else
                            InteropMethods.freeMemory(valueType);
                    }
                    else if (type == typeof(Any))
                    {
                        InteropValue.Any* valueAny = (InteropValue.Any*)value;

                        object contents = null;
                        Type containedType = TypeHelper.ParseType(UnmarshalString(valueAny->type));

                        if (assignObject)
                        {
                            switch (Type.GetTypeCode(containedType))
                            {
                                case TypeCode.Boolean:
                                case TypeCode.SByte:
                                case TypeCode.Char:
                                case TypeCode.Int16:
                                case TypeCode.UInt16:
                                case TypeCode.Int32:
                                case TypeCode.UInt32:
                                case TypeCode.Single:
                                    UnmarshalObject(containedType, ref contents, (void*)&valueAny->data, true);
                                    break;
                                case TypeCode.Int64:
                                case TypeCode.UInt64:
                                case TypeCode.Double:
                                    {
                                        int size = SizeOf(containedType);
                                        if (size <= IntPtr.Size)
                                        {
                                            UnmarshalObject(containedType, ref contents, (void*)&valueAny->data, true);
                                        }
                                        else
                                        {
                                            UnmarshalObject(containedType, ref contents, (void*)valueAny->data, true);
                                            InteropMethods.freeMemory(valueAny->data);
                                        }
                                        break;
                                    }
                                default:
                                    if (containedType == typeof(Any) || containedType.IsArray)
                                    {
                                        UnmarshalObject(containedType, ref contents, (void*)valueAny->data, true);
                                        InteropMethods.freeMemory(valueAny->data);
                                    }
                                    else
                                    {
                                        UnmarshalObject(containedType, ref contents, (void*)&valueAny->data, true);
                                    }
                                    break;
                            }
                            target = new Any(containedType, contents);
                        }
                        else
                        {
                            switch (Type.GetTypeCode(containedType))
                            {
                                case TypeCode.Boolean:
                                case TypeCode.SByte:
                                case TypeCode.Char:
                                case TypeCode.Int16:
                                case TypeCode.UInt16:
                                case TypeCode.Int32:
                                case TypeCode.UInt32:
                                case TypeCode.Single:
                                    break;
                                case TypeCode.Int64:
                                case TypeCode.UInt64:
                                case TypeCode.Double:
                                    if (SizeOf(containedType) > IntPtr.Size)
                                        InteropMethods.freeMemory(valueAny->data);
                                    break;
                                default:
                                    if (containedType == typeof(Any) || containedType.IsArray)
                                    {
                                        UnmarshalObject(containedType, ref contents, (void*)valueAny->data, false);
                                        InteropMethods.freeMemory(valueAny->data);
                                    }
                                    else
                                    {
                                        UnmarshalObject(containedType, ref contents, (void*)&valueAny->data, false);
                                    }
                                    break;
                            }
                        }
                    }
                    else if (type.IsEnum)
                    {
                        target = *(int*)value;
                    }
                    else if (type.IsArray)
                    {
                        InteropValue.Sequence* valueSeq = (InteropValue.Sequence*)value;

                        Type elemType = type.GetElementType();
                        int elemSize = SizeOf(elemType);

                        if (assignObject)
                        {
                            int memSize = elemSize * valueSeq->length;
                            Array netArray = Array.CreateInstance(elemType, valueSeq->length);

                            switch (Type.GetTypeCode(elemType))
                            {
                                case TypeCode.Boolean:
                                    fixed (void* dst = (bool[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.SByte:
                                    fixed (void* dst = (sbyte[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.Char:
                                    fixed (void* dst = (char[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.Int16:
                                    fixed (void* dst = (short[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.UInt16:
                                    fixed (void* dst = (ushort[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.Int32:
                                    fixed (void* dst = (int[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.UInt32:
                                    fixed (void* dst = (uint[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.Int64:
                                    fixed (void* dst = (long[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.UInt64:
                                    fixed (void* dst = (ulong[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.Single:
                                    fixed (void* dst = (float[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                case TypeCode.Double:
                                    fixed (void* dst = (double[])netArray)
                                        Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    break;
                                default:
                                    if (elemType.IsEnum)
                                    {
                                        fixed (void* dst = (int[])netArray)
                                            Buffer.MemoryCopy((void*)valueSeq->data, dst, memSize, memSize);
                                    }
                                    else
                                    {
                                        object inner = null;
                                        for (int i = 0; i < netArray.Length; i++)
                                        {
                                            UnmarshalObject(elemType, ref inner, (void*)(valueSeq->data + elemSize * i), true);
                                            netArray.SetValue(inner, i);
                                        }
                                    }
                                    break;
                            }
                            target = netArray;
                        }
                        else
                        {
                            switch (Type.GetTypeCode(elemType))
                            {
                                case TypeCode.Boolean:
                                case TypeCode.SByte:
                                case TypeCode.Char:
                                case TypeCode.Int16:
                                case TypeCode.UInt16:
                                case TypeCode.Int32:
                                case TypeCode.UInt32:
                                case TypeCode.Int64:
                                case TypeCode.UInt64:
                                case TypeCode.Single:
                                case TypeCode.Double:
                                    break;
                                default:
                                    if (elemType.IsEnum || typeof(IQueryInterface).IsAssignableFrom(type))
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        object dummy = null;
                                        for (int i = 0; i < valueSeq->length; i++)
                                            UnmarshalObject(elemType, ref dummy, (void*)(valueSeq->data + elemSize * i), false);
                                    }
                                    break;
                            }
                        }

                        InteropMethods.freeMemory(valueSeq->data);
                    }
                    else if (typeof(IQueryInterface).IsAssignableFrom(type))
                    {
                        if (assignObject)
                            target = _env.GetRegisteredObject(*(IntPtr*)value);
                    }
                    else
                    {
                        IntPtr valueStruct = *(IntPtr*)value;

                        (Func<object[], object> ctor, Type[] paramTypes) = StructHelper.GetConstructor(type);
                        if (assignObject)
                        {
                            object[] args = new object[paramTypes.Length];
                            int offset = 0;
                            for (int i = 0; i < paramTypes.Length; i++)
                            {
                                UnmarshalObject(paramTypes[i], ref args[i], (void*)(valueStruct + offset), true);
                                offset += SizeOf(paramTypes[i]);
                            }
                            target = ctor(args);
                        }
                        else
                        {
                            object dummy = null;
                            int offset = 0;
                            for (int i = 0; i < paramTypes.Length; i++)
                            {
                                UnmarshalObject(paramTypes[i], ref dummy, (void*)(valueStruct + offset), false);
                                offset += SizeOf(paramTypes[i]);
                            }
                        }

                        InteropMethods.freeMemory(valueStruct);
                    }
                    break;
            }
        }

        private unsafe IntPtr MarshalString(string str)
        {
            char* buffer = (char*)InteropMethods.allocateMemory((str.Length + 1) * sizeof(char));
            fixed (char* data = str)
            {
                Buffer.MemoryCopy(data, buffer, str.Length * sizeof(char), str.Length * sizeof(char));
                buffer[str.Length] = '\0';
            }
            return (IntPtr)buffer;
        }

        private string UnmarshalString(IntPtr ptr)
        {
            string s = Marshal.PtrToStringUni(ptr);
            InteropMethods.freeMemory(ptr);
            return s;
        }

        private int SizeOf(Type type)
        {
            switch (Type.GetTypeCode(type))
            {
                case TypeCode.Boolean: return sizeof(bool);
                case TypeCode.SBytereturn sizeof(sbyte);
                case TypeCode.Charreturn sizeof(char);
                case TypeCode.Int16: return sizeof(short);
                case TypeCode.UInt16: return sizeof(ushort);
                case TypeCode.Int32: return sizeof(int);
                case TypeCode.UInt32: return sizeof(uint);
                case TypeCode.Int64: return sizeof(long);
                case TypeCode.UInt64: return sizeof(ulong);
                case TypeCode.Single: return sizeof(float);
                case TypeCode.Doublereturn sizeof(double);
            }
            if (type.IsEnum)
                return sizeof(int);
            else if (type.IsArray)
                return IntPtr.Size + sizeof(int);
            else if (type == typeof(Any))
                return IntPtr.Size * 2;
            return IntPtr.Size;
        }
    }
}

Messung V0.5
C=100 H=97 G=98

¤ Dauer der Verarbeitung: 0.51 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.