Exemplo n.º 1
0
        /// <summary>
        /// Create an interface instance and context and whether to try and create a map
        /// </summary>
        /// <param name="name"></param>
        /// <param name="try_create_map"></param>
        /// <returns></returns>
        public static (IntPtr, IBaseInterface, bool) CreateInterface(string name, bool try_create_map = false)
        {
            // TODO: this really should "try" create map this should fail if it cant find a map and we want a map
            // Otherwise we are going to get unexpected behaviour
            // But then again some createinterfaces dont know whether they are going to be a map or not so...

            // Ensure that we are loaded before trying to query loaded plugins
            Loader.Load();

            Plugin.InterfaceImpl impl = null;

            var is_map = try_create_map;

            if (try_create_map)
            {
                impl = FindInterfaceMap(name);
            }

            // Not trying to find a map or we couldnt find one (in the case that an interface is not servermapped)
            if (impl == null)
            {
                is_map = false;

                impl = FindImpl(name);
            }

            if (impl == null)
            {
                Log.WriteLine("Unable to find map or impl for interface {0}", name);
                return(IntPtr.Zero, null, false);
            }

            var iface = FindInterfaceDelegates(impl.name);

            if (iface == null)
            {
                Log.WriteLine("Unable to find delegates for interface that implements {0}", impl.name);
                return(IntPtr.Zero, null, false);
            }

            // Try to create a new context based on this interface + impl pair
            var(context, instance) = Create(iface, impl);
            return(context, instance, is_map);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Create a new implementation context based on the delegate types and implementation
        /// </summary>
        /// <param name="iface"></param>
        /// <param name="impl"></param>
        /// <returns></returns>
        private static (IntPtr, IBaseInterface) Create(Plugin.InterfaceDelegates iface, Plugin.InterfaceImpl impl)
        {
            var instance = CreateInterfaceInstance(impl);

            var new_delegates = new List <Delegate>();

            for (var i = 0; i < impl.methods.Count; i++)
            {
                // Find the delegate type that matches the method
                var mi = impl.methods[i];

                var type = iface.delegate_types.Find(x => x.Name.Equals(mi.Name));

                if (type == null)
                {
                    Log.WriteLine("Unable to find delegate for {0} in {1}! (maybe you need to regen autogen?)", mi.Name, iface.name);
                    return(IntPtr.Zero, null);
                }

                // Create new delegates that are bounded to this instance
                Delegate new_delegate;
                try
                {
                    new_delegate = Delegate.CreateDelegate(type, instance, mi, true);
                }
                catch (Exception e)
                {
                    Log.WriteLine("EXCEPTION whilst binding function {0}", mi.Name);
                    throw e;
                }

                new_delegates.Add(new_delegate);
            }

            impl.stored_delegates.Add(new_delegates);


            // Create a new context (class) that mimics what the C++ compiler would generate

            // class:
            //  vtable:
            //   1
            //   2
            //   3
            //   ...

            var ptr_size = Marshal.SizeOf(typeof(IntPtr));

            // Allocate enough space for the new pointers in local memory
            var vtable = Marshal.AllocHGlobal(impl.methods.Count * ptr_size);

            for (var i = 0; i < new_delegates.Count; i++)
            {
                // Create all function pointers as neccessary
                Marshal.WriteIntPtr(vtable, i * ptr_size, Marshal.GetFunctionPointerForDelegate(new_delegates[i]));
            }

            impl.stored_function_pointers.Add(vtable);

            // create the context
            var new_context = Marshal.AllocHGlobal(ptr_size);

            // Write the pointer to the vtable at the address pointed to by new_context;
            Marshal.WriteIntPtr(new_context, vtable);

            return(new_context, (IBaseInterface)instance);
        }
Exemplo n.º 3
0
 /// <summary>
 /// Create an instance based on this implementation
 /// </summary>
 /// <param name="impl"></param>
 /// <returns></returns>
 public static object CreateInterfaceInstance(Plugin.InterfaceImpl impl)
 {
     return(Activator.CreateInstance(impl.this_type));
 }
Exemplo n.º 4
0
        public static void Load()
        {
            if (loaded)
            {
                return;
            }

            LoadedPlugins = new List <Plugin>();

            foreach (var a in GetInterfaceAssemblies())
            {
                var p = new Plugin {
                    name = a.GetName().Name
                };

                foreach (var t in a.GetTypes())
                {
                    if (IsInterfaceDelegate(t))
                    {
                        var attribute = t.GetCustomAttribute <DelegateAttribute>();
                        var name      = attribute.Name;

                        var new_interface = new Plugin.InterfaceDelegates {
                            name = name
                        };

                        Log.WriteLine("Found interface delegates \"{0}\"", name);

                        var types = t.GetNestedTypes(BindingFlags.Public);

                        foreach (var type in types)
                        {
                            // Filter out types that are not delegates
                            if (type.IsSubclassOf(typeof(System.Delegate)))
                            {
                                new_interface.delegate_types.Add(type);
                            }
                        }

                        // Just assume all members are delegate types
                        p.interface_delegates.Add(new_interface);
                    }
                    else if (IsInterfaceMap(t))
                    {
                        var attribute = t.GetCustomAttribute <MapAttribute>();
                        var name      = attribute.Name;

                        var new_interface_map = new Plugin.InterfaceMap
                        {
                            name      = name,
                            this_type = t,
                            methods   = InterfaceMethodsForType(t),
                        };

                        Log.WriteLine("Found interface map \"{0}\"", name);

                        p.interface_maps.Add(new_interface_map);
                    }
                    else if (IsInterfaceImpl(t))
                    {
                        var attribute = t.GetCustomAttribute <ImplAttribute>();
                        var name      = attribute.Name;

                        var new_interface_impl = new Plugin.InterfaceImpl
                        {
                            name      = name,
                            this_type = t,
                            methods   = InterfaceMethodsForType(t)
                        };

                        Log.WriteLine("Found interface impl \"{0}\"", name);

                        p.interface_impls.Add(new_interface_impl);
                    }
                }

                LoadedPlugins.Add(p);
            }

            loaded = true;
            return;
        }