Exemple #1
0
        public static GType RegisterStatic(string typeName, FlagsValue[] values)
        {
            GType.AssertGTypeName(typeName);
            var typeName_ = GMarshal.StringToUtf8Ptr(typeName);
            var values_   = GMarshal.CArrayToPtr <FlagsValue> (values, nullTerminated: true);
            var ret       = g_flags_register_static(typeName_, values_);

            // values are never freed for the liftime of the program
            return(ret);
        }
Exemple #2
0
        /// <summary>
        /// ClassInit callback for managed classes.
        /// </summary>
        /// <param name="classPtr">Pointer to <see cref="Struct"/>.</param>
        /// <param name="userDataPtr">Pointer to user data from <see cref="TypeInfo"/>.</param>
        /// <remarks>
        /// This takes care of overriding the methods to make the managed type
        /// interop with the GObject type system.
        /// </remarks>
        static void UnmanagedInitManagedClass(IntPtr classPtr, IntPtr userDataPtr)
        {
            try {
                // Can't use type.GetGType () here since the type registration has
                // not finished. So, we get the GType this way instead.
                var gtype = Marshal.PtrToStructure <GType> (classPtr);
                var type  = (Type)GCHandle.FromIntPtr(userDataPtr).Target;

                // override property native accessors

                Marshal.WriteIntPtr(classPtr, (int)setPropertyOffset, setPropertyPtr);
                Marshal.WriteIntPtr(classPtr, (int)getPropertyOffset, getPropertyPtr);
                Marshal.WriteIntPtr(classPtr, (int)notifyOffset, notifyPtr);

                // Install Properties

                uint propId = 1; // propId 0 is used internally, so we start with 1
                foreach (var propInfo in type.GetProperties())
                {
                    if (propInfo.DeclaringType != type)
                    {
                        // only register properties declared in this type or in interfaces
                        continue;
                    }

                    var name = propInfo.TryGetGPropertyName();
                    if (name == null)
                    {
                        // this property is not to be registered with the GObject type system
                        continue;
                    }
                    // TODO: localize strings for nick and blurb
                    var nick = propInfo.GetCustomAttribute <DisplayNameAttribute> (true)
                               ?.DisplayName ?? name;
                    var blurb = propInfo.GetCustomAttribute <DescriptionAttribute> (true)
                                ?.Description ?? nick;
                    var defaultValue = propInfo.GetCustomAttribute <DefaultValueAttribute> (true)
                                       ?.Value;

                    // setup the flags

                    var flags = default(ParamFlags);

                    if (propInfo.CanRead)
                    {
                        flags |= ParamFlags.Readable;
                    }
                    if (propInfo.CanWrite)
                    {
                        flags |= ParamFlags.Writable;
                    }
                    // Construct properties don't work with managed types because they
                    // require setting the property before the class has been instantiated.
                    // So, we don't ever set ParamFlags.Construct or ParamFlags.ConstructOnly

                    flags |= ParamFlags.StaticName;
                    flags |= ParamFlags.StaticNick;
                    flags |= ParamFlags.StaticBlurb;

                    // Always explicit notify. Setting properties from managed code
                    // must manually call notify, so if a property was set via
                    // unmanaged code, it would result in double notification if
                    // ExplicitNotify was not set.
                    flags |= ParamFlags.ExplicitNotify;

                    if (propInfo.GetCustomAttribute <ObsoleteAttribute> (true) != null)
                    {
                        flags |= ParamFlags.Deprecated;
                    }

                    // create the pspec instance based on type

                    ParamSpec pspec;
                    // TODO: Need to create special boxed type for non-GType objects
                    var propertyGType    = (GType)propInfo.PropertyType;
                    var fundamentalGType = propertyGType.Fundamental;
                    if (fundamentalGType == GType.Boolean)
                    {
                        pspec = new ParamSpecBoolean(name, nick, blurb, (bool)(defaultValue ?? default(bool)), flags);
                    }
                    else if (fundamentalGType == GType.Boxed)
                    {
                        pspec = new ParamSpecBoxed(name, nick, blurb, propertyGType, flags);
                    }
                    else if (fundamentalGType == GType.Char)
                    {
                        pspec = new ParamSpecChar(name, nick, blurb, sbyte.MinValue, sbyte.MaxValue, (sbyte)(defaultValue ?? default(sbyte)), flags);
                    }
                    else if (fundamentalGType == GType.UChar)
                    {
                        pspec = new ParamSpecUChar(name, nick, blurb, byte.MinValue, byte.MaxValue, (byte)(defaultValue ?? default(byte)), flags);
                    }
                    else if (fundamentalGType == GType.Double)
                    {
                        pspec = new ParamSpecDouble(name, nick, blurb, double.MinValue, double.MaxValue, (double)(defaultValue ?? default(double)), flags);
                    }
                    else if (fundamentalGType == GType.Float)
                    {
                        pspec = new ParamSpecFloat(name, nick, blurb, float.MinValue, float.MaxValue, (float)(defaultValue ?? default(float)), flags);
                    }
                    else if (fundamentalGType == GType.Enum)
                    {
                        pspec = new ParamSpecEnum(name, nick, blurb, propertyGType, (System.Enum)defaultValue, flags);
                    }
                    else if (fundamentalGType == GType.Flags)
                    {
                        pspec = new ParamSpecFlags(name, nick, blurb, propertyGType, (System.Enum)defaultValue, flags);
                    }
                    else if (fundamentalGType == GType.Int)
                    {
                        pspec = new ParamSpecInt(name, nick, blurb, int.MinValue, int.MaxValue, (int)(defaultValue ?? default(int)), flags);
                    }
                    else if (fundamentalGType == GType.UInt)
                    {
                        pspec = new ParamSpecUInt(name, nick, blurb, uint.MinValue, uint.MaxValue, (uint)(defaultValue ?? default(uint)), flags);
                    }
                    else if (fundamentalGType == GType.Int64)
                    {
                        pspec = new ParamSpecInt64(name, nick, blurb, long.MinValue, long.MaxValue, (long)(defaultValue ?? default(long)), flags);
                    }
                    else if (fundamentalGType == GType.UInt64)
                    {
                        pspec = new ParamSpecUInt64(name, nick, blurb, ulong.MinValue, ulong.MaxValue, (ulong)(defaultValue ?? default(ulong)), flags);
                    }
                    else if (fundamentalGType == GType.Long)
                    {
                        pspec = new ParamSpecLong(name, nick, blurb, nlong.MinValue, nlong.MaxValue, (nlong)(defaultValue ?? default(nlong)), flags);
                    }
                    else if (fundamentalGType == GType.ULong)
                    {
                        pspec = new ParamSpecULong(name, nick, blurb, nulong.MinValue, nulong.MaxValue, (nulong)(defaultValue ?? default(nulong)), flags);
                    }
                    else if (fundamentalGType == GType.Object)
                    {
                        pspec = new ParamSpecObject(name, nick, blurb, propertyGType, flags);
                    }
                    // TODO: do we need this one?
                    //                else if (fundamentalGType == GType.Param) {
                    //                    pspec = new ParamSpecParam (name, nick, blurb, ?, flags);
                    //                }
                    else if (fundamentalGType == GType.Pointer)
                    {
                        pspec = new ParamSpecPointer(name, nick, blurb, flags);
                    }
                    else if (fundamentalGType == GType.String)
                    {
                        pspec = new ParamSpecString(name, nick, blurb, (string)defaultValue, flags);
                    }
                    else if (fundamentalGType == GType.Type)
                    {
                        pspec = new ParamSpecGType(name, nick, blurb, propertyGType, flags);
                    }
                    else if (fundamentalGType == GType.Variant)
                    {
                        // TODO: need to pass variant type using attribute?
                        // for now, always using any type
                        var variantType = VariantType.Any;
                        pspec = new ParamSpecVariant(name, nick, blurb, variantType, defaultValue == null ? null : (Variant)defaultValue, flags);
                    }
                    else
                    {
                        // TODO: Need more specific exception
                        throw new Exception("unhandled GType");
                    }

                    var methodInfo = propInfo.GetAccessors().First();
                    if (methodInfo.GetBaseDefinition() != methodInfo || propInfo.TryGetMatchingInterfacePropertyInfo() != null)
                    {
                        // if this type did not declare the property, the we know
                        // we are overriding a property from a base class or interface
                        var namePtr = GMarshal.StringToUtf8Ptr(name);
                        g_object_class_override_property(classPtr, propId, namePtr);
                        GMarshal.Free(namePtr);
                    }
                    else
                    {
                        g_object_class_install_property(classPtr, propId, pspec.Handle);
                        GC.KeepAlive(pspec);
                    }
                    propId++;
                }

                foreach (var eventInfo in type.GetEvents())
                {
                    if (eventInfo.DeclaringType != type)
                    {
                        // only register events declared in this type
                        continue;
                    }

                    var signalAttr = eventInfo.GetCustomAttribute <GSignalAttribute>(true);
                    if (signalAttr == null)
                    {
                        // events without SignalAttribute are not installed
                        continue;
                    }

                    // figure out the name

                    var name = signalAttr.Name ?? eventInfo.Name;
                    Signal.ValidateName(name);

                    // figure out the flags

                    var flags = default(SignalFlags);

                    switch (signalAttr.When)
                    {
                    case EmissionStage.First:
                        flags |= SignalFlags.RunFirst;
                        break;

                    case EmissionStage.Last:
                    default:
                        flags |= SignalFlags.RunLast;
                        break;

                    case EmissionStage.Cleanup:
                        flags |= SignalFlags.RunCleanup;
                        break;
                    }

                    if (signalAttr.NoRecurse)
                    {
                        flags |= SignalFlags.NoRecurse;
                    }

                    if (signalAttr.Detailed)
                    {
                        flags |= SignalFlags.Detailed;
                    }

                    if (signalAttr.Action)
                    {
                        flags |= SignalFlags.Action;
                    }

                    if (signalAttr.NoHooks)
                    {
                        flags |= SignalFlags.NoHooks;
                    }

                    if (eventInfo.GetCustomAttribute <ObsoleteAttribute> (true) != null)
                    {
                        flags |= SignalFlags.Deprecated;
                    }

                    // figure out the parameter types

                    var methodInfo      = eventInfo.EventHandlerType.GetMethod("Invoke");
                    var returnGType     = methodInfo.ReturnType.GetGType();
                    var parameters      = methodInfo.GetParameters();
                    var parameterGTypes = new GType[parameters.Length];
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        parameterGTypes[i] = parameters[i].ParameterType.GetGType();
                    }

                    // create a closure that will be called when the signal is emitted

                    var fieldInfo = type.GetField(eventInfo.Name,
                                                  System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

                    var closure = new Closure((p) => {
                        var eventDelegate = (MulticastDelegate)fieldInfo.GetValue(p[0]);
                        return(eventDelegate?.DynamicInvoke(p.Skip(1).ToArray()));
                    });

                    // register the signal

                    var namePtr            = GMarshal.StringToUtf8Ptr(name);
                    var parameterGTypesPtr = GMarshal.CArrayToPtr <GType> (parameterGTypes, false);
                    Signal.g_signal_newv(namePtr, gtype, flags, closure.Handle,
                                         null, IntPtr.Zero, null, returnGType,
                                         (uint)parameterGTypes.Length, parameterGTypesPtr);
                }
            }
            catch (Exception ex) {
                ex.LogUnhandledException();
            }
        }
Exemple #3
0
        /// <summary>
        /// This function is meant to be called from the complete_type_info()
        /// function of a #GTypePlugin implementation, see the example for
        /// g_enum_complete_type_info() above.
        /// </summary>
        /// <param name="gFlagsType">
        /// the type identifier of the type being completed
        /// </param>
        /// <param name="info">
        /// the #GTypeInfo struct to be filled in
        /// </param>
        /// <param name="constValues">
        /// An array of #GFlagsValue structs for the possible
        ///  enumeration values.
        /// </param>
        public static void CompleteTypeInfo(GType gFlagsType, out TypeInfo info, FlagsValue[] constValues)
        {
            var constValues_ = GMarshal.CArrayToPtr <FlagsValue> (constValues, nullTerminated: true);

            g_flags_complete_type_info(gFlagsType, out info, constValues_);
        }
Exemple #4
0
        /// <summary>
        /// This function is meant to be called from the `complete_type_info`
        /// function of a #GTypePlugin implementation, as in the following
        /// example:
        /// </summary>
        /// <remarks>
        /// |[&lt;!-- language="C" --&gt;
        /// static void
        /// my_enum_complete_type_info (GTypePlugin     *plugin,
        ///                             GType            g_type,
        ///                             GTypeInfo       *info,
        ///                             GTypeValueTable *value_table)
        /// {
        ///   static const GEnumValue values[] = {
        ///     { MY_ENUM_FOO, "MY_ENUM_FOO", "foo" },
        ///     { MY_ENUM_BAR, "MY_ENUM_BAR", "bar" },
        ///     { 0, NULL, NULL }
        ///   };
        ///
        ///   g_enum_complete_type_info (type, info, values);
        /// }
        /// ]|
        /// </remarks>
        /// <param name="gEnumType">
        /// the type identifier of the type being completed
        /// </param>
        /// <param name="info">
        /// the #GTypeInfo struct to be filled in
        /// </param>
        /// <param name="constValues">
        /// An array of #GEnumValue structs for the possible
        ///  enumeration values. The array is terminated by a struct with all
        ///  members being 0.
        /// </param>
        static void CompleteTypeInfo(GType gEnumType, out TypeInfo info, EnumValue[] constValues)
        {
            var constValues_ = GMarshal.CArrayToPtr <EnumValue> (constValues, nullTerminated: true);

            g_enum_complete_type_info(gEnumType, out info, constValues_);
        }