Beispiel #1
0
static void
rb_gi_argument_from_ruby_array_c(GIArgument *argument,
                                 G_GNUC_UNUSED GITypeInfo *type_info,
                                 GITypeInfo *element_type_info,
                                 VALUE rb_argument)
{
    GITypeTag element_type_tag;

    element_type_tag = g_type_info_get_tag(element_type_info);
    switch (element_type_tag) {
      case GI_TYPE_TAG_VOID:
      case GI_TYPE_TAG_BOOLEAN:
        rb_raise(rb_eNotImpError,
                 "TODO: Ruby -> GIArgument(array)[%s]",
                 g_type_tag_to_string(element_type_tag));
        break;
      case GI_TYPE_TAG_INT8:
        argument->v_pointer = StringValueCStr(rb_argument);
        break;
      case GI_TYPE_TAG_UINT8:
        argument->v_pointer = RSTRING_PTR(rb_argument);
        break;
      case GI_TYPE_TAG_INT16:
      case GI_TYPE_TAG_UINT16:
      case GI_TYPE_TAG_INT32:
      case GI_TYPE_TAG_UINT32:
      case GI_TYPE_TAG_INT64:
      case GI_TYPE_TAG_UINT64:
      case GI_TYPE_TAG_FLOAT:
      case GI_TYPE_TAG_DOUBLE:
      case GI_TYPE_TAG_GTYPE:
        rb_raise(rb_eNotImpError,
                 "TODO: Ruby -> GIArgument(array)[%s]",
                 g_type_tag_to_string(element_type_tag));
        break;
      case GI_TYPE_TAG_UTF8:
      case GI_TYPE_TAG_FILENAME:
        argument->v_pointer = RVAL2STRV(rb_argument);
        break;
      case GI_TYPE_TAG_ARRAY:
      case GI_TYPE_TAG_INTERFACE:
      case GI_TYPE_TAG_GLIST:
      case GI_TYPE_TAG_GSLIST:
      case GI_TYPE_TAG_GHASH:
      case GI_TYPE_TAG_ERROR:
      case GI_TYPE_TAG_UNICHAR:
        rb_raise(rb_eNotImpError,
                 "TODO: Ruby -> GIArgument(array)[%s]",
                 g_type_tag_to_string(element_type_tag));
        break;
      default:
        g_assert_not_reached();
        break;
    }
}
Beispiel #2
0
static gboolean
gi_argument_to_c_long (GIArgument *arg_in,
                       long *c_long_out,
                       GITypeTag type_tag)
{
    switch (type_tag) {
      case GI_TYPE_TAG_INT8:
          *c_long_out = arg_in->v_int8;
          return TRUE;
      case GI_TYPE_TAG_UINT8:
          *c_long_out = arg_in->v_uint8;
          return TRUE;
      case GI_TYPE_TAG_INT16:
          *c_long_out = arg_in->v_int16;
          return TRUE;
      case GI_TYPE_TAG_UINT16:
          *c_long_out = arg_in->v_uint16;
          return TRUE;
      case GI_TYPE_TAG_INT32:
          *c_long_out = arg_in->v_int32;
          return TRUE;
      case GI_TYPE_TAG_UINT32:
          *c_long_out = arg_in->v_uint32;
          return TRUE;
      case GI_TYPE_TAG_INT64:
          if (arg_in->v_int64 > G_MAXLONG || arg_in->v_int64 < G_MINLONG) {
              PyErr_Format (PyExc_TypeError,
                            "Unable to marshal %s to C long",
                            g_type_tag_to_string(type_tag));
              return FALSE;
          }
          *c_long_out = (glong)arg_in->v_int64;
          return TRUE;
      case GI_TYPE_TAG_UINT64:
          if (arg_in->v_uint64 > G_MAXLONG) {
              PyErr_Format (PyExc_TypeError,
                            "Unable to marshal %s to C long",
                            g_type_tag_to_string(type_tag));
              return FALSE;
          }
          *c_long_out = (glong)arg_in->v_uint64;
          return TRUE;
      default:
          PyErr_Format (PyExc_TypeError,
                        "Unable to marshal %s to C long",
                        g_type_tag_to_string (type_tag));
          return FALSE;
    }
}
Beispiel #3
0
void
_pygi_hash_pointer_to_arg (GIArgument *arg,
                           GITypeTag  type_tag)
{
    switch (type_tag) {
        case GI_TYPE_TAG_INT8:
            arg->v_int8 = GPOINTER_TO_INT (arg->v_pointer);
            break;
        case GI_TYPE_TAG_INT16:
            arg->v_int16 = GPOINTER_TO_INT (arg->v_pointer);
            break;
        case GI_TYPE_TAG_INT32:
            arg->v_int32 = GPOINTER_TO_INT (arg->v_pointer);
            break;
        case GI_TYPE_TAG_UINT8:
            arg->v_uint8 = GPOINTER_TO_UINT (arg->v_pointer);
            break;
        case GI_TYPE_TAG_UINT16:
            arg->v_uint16 = GPOINTER_TO_UINT (arg->v_pointer);
            break;
        case GI_TYPE_TAG_UINT32:
            arg->v_uint32 = GPOINTER_TO_UINT (arg->v_pointer);
            break;
        case GI_TYPE_TAG_GTYPE:
            arg->v_size = GPOINTER_TO_SIZE (arg->v_pointer);
            break;
        case GI_TYPE_TAG_UTF8:
        case GI_TYPE_TAG_FILENAME:
        case GI_TYPE_TAG_INTERFACE:
            break;
        default:
            g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag));
    }
}
Beispiel #4
0
gpointer
_pygi_arg_to_hash_pointer (const GIArgument *arg,
                           GITypeTag        type_tag)
{
    switch (type_tag) {
        case GI_TYPE_TAG_INT8:
            return GINT_TO_POINTER (arg->v_int8);
        case GI_TYPE_TAG_UINT8:
            return GINT_TO_POINTER (arg->v_uint8);
        case GI_TYPE_TAG_INT16:
            return GINT_TO_POINTER (arg->v_int16);
        case GI_TYPE_TAG_UINT16:
            return GINT_TO_POINTER (arg->v_uint16);
        case GI_TYPE_TAG_INT32:
            return GINT_TO_POINTER (arg->v_int32);
        case GI_TYPE_TAG_UINT32:
            return GINT_TO_POINTER (arg->v_uint32);
        case GI_TYPE_TAG_GTYPE:
            return GSIZE_TO_POINTER (arg->v_size);
        case GI_TYPE_TAG_UTF8:
        case GI_TYPE_TAG_FILENAME:
        case GI_TYPE_TAG_INTERFACE:
            return arg->v_pointer;
        default:
            g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag));
            return arg->v_pointer;
    }
}
gsize
_pygi_g_type_tag_size (GITypeTag type_tag)
{
    gsize size = 0;

    switch (type_tag) {
        case GI_TYPE_TAG_BOOLEAN:
            size = sizeof (gboolean);
            break;
        case GI_TYPE_TAG_INT8:
        case GI_TYPE_TAG_UINT8:
            size = sizeof (gint8);
            break;
        case GI_TYPE_TAG_INT16:
        case GI_TYPE_TAG_UINT16:
            size = sizeof (gint16);
            break;
        case GI_TYPE_TAG_INT32:
        case GI_TYPE_TAG_UINT32:
            size = sizeof (gint32);
            break;
        case GI_TYPE_TAG_INT64:
        case GI_TYPE_TAG_UINT64:
            size = sizeof (gint64);
            break;
        case GI_TYPE_TAG_FLOAT:
            size = sizeof (gfloat);
            break;
        case GI_TYPE_TAG_DOUBLE:
            size = sizeof (gdouble);
            break;
        case GI_TYPE_TAG_GTYPE:
            size = sizeof (GType);
            break;
        case GI_TYPE_TAG_UNICHAR:
            size = sizeof (gunichar);
            break;
        case GI_TYPE_TAG_VOID:
        case GI_TYPE_TAG_UTF8:
        case GI_TYPE_TAG_FILENAME:
        case GI_TYPE_TAG_ARRAY:
        case GI_TYPE_TAG_INTERFACE:
        case GI_TYPE_TAG_GLIST:
        case GI_TYPE_TAG_GSLIST:
        case GI_TYPE_TAG_GHASH:
        case GI_TYPE_TAG_ERROR:
            PyErr_Format (PyExc_TypeError,
                          "Unable to know the size (assuming %s is not a pointer)",
                          g_type_tag_to_string (type_tag));
            break;
    }

    return size;
}
Beispiel #6
0
static gboolean
gi_argument_from_c_long (GIArgument *arg_out,
                         long        c_long_in,
                         GITypeTag   type_tag)
{
    switch (type_tag) {
      case GI_TYPE_TAG_INT8:
          arg_out->v_int8 = (gint8)c_long_in;
          return TRUE;
      case GI_TYPE_TAG_UINT8:
          arg_out->v_uint8 = (guint8)c_long_in;
          return TRUE;
      case GI_TYPE_TAG_INT16:
          arg_out->v_int16 = (gint16)c_long_in;
          return TRUE;
      case GI_TYPE_TAG_UINT16:
          arg_out->v_uint16 = (guint16)c_long_in;
          return TRUE;
      case GI_TYPE_TAG_INT32:
          arg_out->v_int32 = (gint32)c_long_in;
          return TRUE;
      case GI_TYPE_TAG_UINT32:
          arg_out->v_uint32 = (guint32)c_long_in;
          return TRUE;
      case GI_TYPE_TAG_INT64:
          arg_out->v_int64 = (gint64)c_long_in;
          return TRUE;
      case GI_TYPE_TAG_UINT64:
          arg_out->v_uint64 = (guint64)c_long_in;
          return TRUE;
      default:
          PyErr_Format (PyExc_TypeError,
                        "Unable to marshal C long %ld to %s",
                        c_long_in,
                        g_type_tag_to_string (type_tag));
          return FALSE;
    }
}
VALUE
rb_gi_field_info_get_field_raw(GIFieldInfo *info, gpointer memory)
{
    GIArgument argument;
    GITypeInfo *type_info;
    GITypeTag type_tag;
    VALUE rb_field_value;

    type_info = g_field_info_get_type(info);
    type_tag = g_type_info_get_tag(type_info);

    if (!g_field_info_get_field(info, memory, &argument)) {
        g_base_info_unref(type_info);
        rb_raise(rb_eArgError, "failed to get field value: %s[%s]",
                 g_base_info_get_name(info),
                 g_type_tag_to_string(type_tag));
    }

    if (type_tag == GI_TYPE_TAG_UTF8) {
        int offset;
        offset = g_field_info_get_offset(info);
        argument.v_string = G_STRUCT_MEMBER(gchar *, memory, offset);
    }
Beispiel #8
0
static gboolean
gi_argument_to_gsize (GIArgument *arg_in,
                      gsize      *gsize_out,
                      GITypeTag   type_tag)
{
    switch (type_tag) {
      case GI_TYPE_TAG_INT8:
          *gsize_out = arg_in->v_int8;
          return TRUE;
      case GI_TYPE_TAG_UINT8:
          *gsize_out = arg_in->v_uint8;
          return TRUE;
      case GI_TYPE_TAG_INT16:
          *gsize_out = arg_in->v_int16;
          return TRUE;
      case GI_TYPE_TAG_UINT16:
          *gsize_out = arg_in->v_uint16;
          return TRUE;
      case GI_TYPE_TAG_INT32:
          *gsize_out = arg_in->v_int32;
          return TRUE;
      case GI_TYPE_TAG_UINT32:
          *gsize_out = arg_in->v_uint32;
          return TRUE;
      case GI_TYPE_TAG_INT64:
          *gsize_out = arg_in->v_int64;
          return TRUE;
      case GI_TYPE_TAG_UINT64:
          *gsize_out = arg_in->v_uint64;
          return TRUE;
      default:
          PyErr_Format (PyExc_TypeError,
                        "Unable to marshal %s to gsize",
                        g_type_tag_to_string (type_tag));
          return FALSE;
    }
}
static gboolean
get_enum_size_alignment (GIrNodeEnum *enum_node,
			 gint        *size,
			 gint        *alignment)
{
  ffi_type *type_ffi;

  compute_enum_storage_type (enum_node);

  switch (enum_node->storage_type)
    {
    case GI_TYPE_TAG_INT8:
    case GI_TYPE_TAG_UINT8:
      type_ffi = &ffi_type_uint8;
      break;
    case GI_TYPE_TAG_INT16:
    case GI_TYPE_TAG_UINT16:
      type_ffi = &ffi_type_uint16;
      break;
    case GI_TYPE_TAG_INT32:
    case GI_TYPE_TAG_UINT32:
      type_ffi = &ffi_type_uint32;
      break;
    case GI_TYPE_TAG_INT64:
    case GI_TYPE_TAG_UINT64:
      type_ffi = &ffi_type_uint64;
      break;
    default:
      g_error ("Unexpected enum storage type %s",
	       g_type_tag_to_string (enum_node->storage_type));
    }

  *size = type_ffi->size;
  *alignment = type_ffi->alignment;

  return TRUE;
}
Beispiel #10
0
static void
_pygi_closure_convert_ffi_arguments (PyGIInvokeArgState *state,
                                     PyGICallableCache *cache,
                                     void **args)
{
    gint i;

    for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
        PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i);

        if (arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
            state[i].arg_value.v_pointer = * (gpointer *) args[i];

            if (state[i].arg_value.v_pointer == NULL)
                continue;

            state[i].arg_pointer.v_pointer = state[i].arg_value.v_pointer;
            state[i].arg_value = *(GIArgument *) state[i].arg_value.v_pointer;
            continue;
        }

        switch (arg_cache->type_tag) {
            case GI_TYPE_TAG_BOOLEAN:
                state[i].arg_value.v_boolean = * (gboolean *) args[i];
                break;
            case GI_TYPE_TAG_INT8:
                state[i].arg_value.v_int8 = * (gint8 *) args[i];
                break;
            case GI_TYPE_TAG_UINT8:
                state[i].arg_value.v_uint8 = * (guint8 *) args[i];
                break;
            case GI_TYPE_TAG_INT16:
                state[i].arg_value.v_int16 = * (gint16 *) args[i];
                break;
            case GI_TYPE_TAG_UINT16:
                state[i].arg_value.v_uint16 = * (guint16 *) args[i];
                break;
            case GI_TYPE_TAG_INT32:
                state[i].arg_value.v_int32 = * (gint32 *) args[i];
                break;
            case GI_TYPE_TAG_UINT32:
                state[i].arg_value.v_uint32 = * (guint32 *) args[i];
                break;
            case GI_TYPE_TAG_INT64:
                state[i].arg_value.v_int64 = * (glong *) args[i];
                break;
            case GI_TYPE_TAG_UINT64:
                state[i].arg_value.v_uint64 = * (glong *) args[i];
                break;
            case GI_TYPE_TAG_FLOAT:
                state[i].arg_value.v_float = * (gfloat *) args[i];
                break;
            case GI_TYPE_TAG_DOUBLE:
                state[i].arg_value.v_double = * (gdouble *) args[i];
                break;
            case GI_TYPE_TAG_UTF8:
                state[i].arg_value.v_string = * (gchar **) args[i];
                break;
            case GI_TYPE_TAG_INTERFACE:
            {
                GIBaseInfo *interface;
                GIInfoType interface_type;

                interface = ((PyGIInterfaceCache *) arg_cache)->interface_info;
                interface_type = g_base_info_get_type (interface);

                if (interface_type == GI_INFO_TYPE_ENUM) {
                    state[i].arg_value.v_int = * (gint *) args[i];
                } else if (interface_type == GI_INFO_TYPE_FLAGS) {
                    state[i].arg_value.v_uint = * (guint *) args[i];
                } else {
                    state[i].arg_value.v_pointer = * (gpointer *) args[i];
                }
                break;
            }
            case GI_TYPE_TAG_ERROR:
            case GI_TYPE_TAG_GHASH:
            case GI_TYPE_TAG_GLIST:
            case GI_TYPE_TAG_GSLIST:
            case GI_TYPE_TAG_ARRAY:
            case GI_TYPE_TAG_VOID:
                state[i].arg_value.v_pointer = * (gpointer *) args[i];
                break;
            default:
                g_warning ("Unhandled type tag %s",
                           g_type_tag_to_string (arg_cache->type_tag));
                state[i].arg_value.v_pointer = 0;
        }
    }

    if (cache->throws) {
        gssize error_index = _pygi_callable_cache_args_len (cache);

        state[error_index].arg_value.v_pointer = * (gpointer *) args[error_index];
    }
}
Beispiel #11
0
void
gy_value_push(GValue * pval, GITypeInfo * info, gy_Object* o)
{
  GITypeTag tag = g_type_info_get_tag(info);
  GY_DEBUG("Pushing %s from GValue\n", g_type_tag_to_string(tag));
  switch (tag) {
    /* basic types */
  case GI_TYPE_TAG_VOID:{
    GITypeInfo * cellinfo = g_type_info_get_param_type(info, 0);
    if (cellinfo) {
      GITypeTag ctag = g_type_info_get_tag(cellinfo);
      GY_DEBUG("void contains %s\n", g_type_tag_to_string(ctag));
      g_base_info_unref(cellinfo);
    }
    ypush_nil();
    break;}
  case GI_TYPE_TAG_BOOLEAN:
    *ypush_c(NULL) = g_value_get_boolean(pval);
    break;
  case GI_TYPE_TAG_INT8:
    *ypush_gint8(NULL) = g_value_get_schar(pval);
    break;
  case GI_TYPE_TAG_UINT8:
    *ypush_guint8(NULL)= g_value_get_uchar(pval);
    break;
  case GI_TYPE_TAG_INT16:
  case GI_TYPE_TAG_INT32:
    *ypush_gint32(NULL) = g_value_get_int(pval);
    break;
  case GI_TYPE_TAG_UINT16:
  case GI_TYPE_TAG_UINT32:
    *ypush_guint32(NULL) = g_value_get_uint(pval);
    break;
  case GI_TYPE_TAG_INT64:
    ypush_long(g_value_get_int64(pval));
    break;
  case GI_TYPE_TAG_UINT64:
    ypush_long(g_value_get_uint64(pval));
    break;
  case GI_TYPE_TAG_FLOAT:
    *ypush_f(NULL)=g_value_get_float(pval);
    break;
  case GI_TYPE_TAG_DOUBLE:
    ypush_double(g_value_get_double(pval));
    break;
  case GI_TYPE_TAG_GTYPE:
    ypush_long(g_value_get_gtype(pval));
    break;
  case GI_TYPE_TAG_UTF8:
  case GI_TYPE_TAG_FILENAME:
    *ypush_q(NULL) = p_strcpy(g_value_get_string(pval));
    break;
    /* array types */
  case GI_TYPE_TAG_ARRAY:
    y_error("array");
    break;
    /* interface types */
  case GI_TYPE_TAG_INTERFACE:
    {
      GIBaseInfo * itrf = g_type_info_get_interface (info);
      switch(g_base_info_get_type (itrf)) {
      case GI_INFO_TYPE_ENUM:
	ypush_long(g_value_get_enum(pval));
	g_base_info_unref(itrf);
	break;
      case GI_INFO_TYPE_OBJECT:
	{
	  GObject * prop=g_value_get_object(pval);
	  g_object_ref_sink(prop);
	  if (!prop) {
	    g_base_info_unref(itrf);
	    y_error("get property failed");
	  }
	  GY_DEBUG("pushing result... ");
	  ypush_check(1);
	  gy_Object * out = ypush_gy_Object();

	  out->info=itrf;
	  out->object=prop;
	  out->repo=o->repo;
	}
	break;
      default:
      	g_base_info_unref(itrf);
      	y_error ("fix me: only properties of type object supported yet");
      }
      break;
    }
  default:
    y_error("Unimplemented");
  }


}
Beispiel #12
0
void
gy_value_init(GValue * val, GITypeInfo * info)
{
  GY_DEBUG("in gy_value_init\n");
  GITypeTag type = g_type_info_get_tag(info);
  GIBaseInfo * itrf;
  GY_DEBUG("Initializing GValue to %s\n", g_type_tag_to_string(type));
  switch (type) {
    /* basic types */
  case GI_TYPE_TAG_BOOLEAN:
    g_value_init(val, G_TYPE_BOOLEAN);
    break;
  case GI_TYPE_TAG_INT8:
    g_value_init(val, G_TYPE_CHAR);
    break;
  case GI_TYPE_TAG_UINT8:
    g_value_init(val, G_TYPE_UCHAR);
    break;
  case GI_TYPE_TAG_INT16:
  case GI_TYPE_TAG_INT32:
    g_value_init(val, G_TYPE_INT);
    break;
  case GI_TYPE_TAG_UINT16:
  case GI_TYPE_TAG_UINT32:
    g_value_init(val, G_TYPE_INT);
    break;
  case GI_TYPE_TAG_INT64:
    g_value_init(val, G_TYPE_INT64);
    break;
  case GI_TYPE_TAG_UINT64:
    g_value_init(val, G_TYPE_UINT64);
    break;
  case GI_TYPE_TAG_FLOAT:
    g_value_init(val, G_TYPE_FLOAT);
    break;
  case GI_TYPE_TAG_DOUBLE:
    g_value_init(val, G_TYPE_DOUBLE);
    break;
  case GI_TYPE_TAG_GTYPE:
    g_value_init(val, G_TYPE_GTYPE);
    break;
  case GI_TYPE_TAG_UTF8:
  case GI_TYPE_TAG_FILENAME:
    g_value_init(val, G_TYPE_STRING);
    GY_DEBUG("GValue is string\n");
    break;
    /* interface types */
  case GI_TYPE_TAG_INTERFACE:
    itrf = g_type_info_get_interface(info);
    switch(g_base_info_get_type (itrf)) {
    case GI_INFO_TYPE_OBJECT:
      g_value_init(val, G_TYPE_OBJECT);
      break;
    case GI_INFO_TYPE_ENUM:
      g_value_init(val,  g_registered_type_info_get_g_type(itrf));
      GY_DEBUG("GValue is enum\n");
      break;
    default:
      y_errorn("Unimplemented GValue interface type %ld",
	       g_base_info_get_type (itrf));
    }
    g_base_info_unref(itrf);
    break;
  case GI_TYPE_TAG_VOID:
  default:
    y_error("Unimplement property GValue type");
  }
  GY_DEBUG("out gy_value_init\n");
}
Beispiel #13
0
PyObject *
pygi_get_property_value_real (PyGObject *instance,
                              const gchar *attr_name)
{
    GType g_type;
    GIPropertyInfo *property_info = NULL;
    char *property_name = g_strdup (attr_name);
    GParamSpec *pspec = NULL;
    GValue value = { 0, };
    GIArgument arg = { 0, };
    PyObject *py_value = NULL;
    GITypeInfo *type_info = NULL;
    GITransfer transfer;

    canonicalize_key (property_name);

    g_type = pyg_type_from_object ((PyObject *)instance);
    property_info = _pygi_lookup_property_from_g_type (g_type, property_name);

    if (property_info == NULL)
        goto out;

    pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (instance->obj),
                                          attr_name);
    if (pspec == NULL)
        goto out;

    g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
    g_object_get_property (instance->obj, attr_name, &value);

    type_info = g_property_info_get_type (property_info);
    transfer = g_property_info_get_ownership_transfer (property_info);

    GITypeTag type_tag = g_type_info_get_tag (type_info);
    switch (type_tag) {
        case GI_TYPE_TAG_BOOLEAN:
            arg.v_boolean = g_value_get_boolean (&value);
            break;
        case GI_TYPE_TAG_INT8:
            arg.v_int8 = g_value_get_schar (&value);
            break;
        case GI_TYPE_TAG_INT16:
        case GI_TYPE_TAG_INT32:
            if (G_VALUE_HOLDS_LONG (&value))
                arg.v_long = g_value_get_long (&value);
            else
                arg.v_int = g_value_get_int (&value);
            break;
        case GI_TYPE_TAG_INT64:
            if (G_VALUE_HOLDS_LONG (&value))
                arg.v_long = g_value_get_long (&value);
            else
                arg.v_int64 = g_value_get_int64 (&value);
            break;
        case GI_TYPE_TAG_UINT8:
            arg.v_uint8 = g_value_get_uchar (&value);
            break;
        case GI_TYPE_TAG_UINT16:
        case GI_TYPE_TAG_UINT32:
            if (G_VALUE_HOLDS_ULONG (&value))
                arg.v_ulong = g_value_get_ulong (&value);
            else
                arg.v_uint = g_value_get_uint (&value);
            break;
        case GI_TYPE_TAG_UINT64:
            if (G_VALUE_HOLDS_ULONG (&value))
                arg.v_ulong = g_value_get_ulong (&value);
            else
                arg.v_uint64 = g_value_get_uint64 (&value);
            break;
        case GI_TYPE_TAG_FLOAT:
            arg.v_float = g_value_get_float (&value);
            break;
        case GI_TYPE_TAG_DOUBLE:
            arg.v_double = g_value_get_double (&value);
            break;
        case GI_TYPE_TAG_GTYPE:
            arg.v_size = g_value_get_gtype (&value);
            break;
        case GI_TYPE_TAG_UTF8:
        case GI_TYPE_TAG_FILENAME:
            arg.v_string = g_value_dup_string (&value);
            break;
        case GI_TYPE_TAG_INTERFACE:
        {
            GIBaseInfo *info;
            GIInfoType info_type;
            GType type;

            info = g_type_info_get_interface (type_info);
            type = g_registered_type_info_get_g_type (info);
            info_type = g_base_info_get_type (info);

            g_base_info_unref (info);

            switch (info_type) {
                case GI_INFO_TYPE_ENUM:
                    arg.v_int32 = g_value_get_enum (&value);
                    break;
                case GI_INFO_TYPE_INTERFACE:
                case GI_INFO_TYPE_OBJECT:
                    arg.v_pointer = g_value_get_object (&value);
                    break;
                case GI_INFO_TYPE_BOXED:
                case GI_INFO_TYPE_STRUCT:
                case GI_INFO_TYPE_UNION:

                    if (g_type_is_a (type, G_TYPE_BOXED)) {
                        arg.v_pointer = g_value_get_boxed (&value);
                    } else if (g_type_is_a (type, G_TYPE_POINTER)) {
                        arg.v_pointer = g_value_get_pointer (&value);
                    } else {
                        PyErr_Format (PyExc_NotImplementedError,
                                      "Retrieving properties of type '%s' is not implemented",
                                      g_type_name (type));
                    }
                    break;
                default:
                    PyErr_Format (PyExc_NotImplementedError,
                                  "Retrieving properties of type '%s' is not implemented",
                                  g_type_name (type));
                    goto out;
            }
            break;
        }
        case GI_TYPE_TAG_GHASH:
            arg.v_pointer = g_value_get_boxed (&value);
            break;
        case GI_TYPE_TAG_GLIST:
            arg.v_pointer = g_value_get_pointer (&value);
            break;
        case GI_TYPE_TAG_ARRAY:
        {
            gchar** strings;
            GArray *arg_items;
            int i;

            strings = g_value_get_boxed (&value);
            if (strings == NULL)
                arg.v_pointer = NULL;
            else {
                arg_items = g_array_sized_new (TRUE, TRUE, sizeof (GIArgument), g_strv_length (strings));
                g_array_set_size (arg_items, g_strv_length (strings));
                for (i = 0; strings[i] != NULL; ++i) {
                    g_array_index (arg_items, GIArgument, i).v_string = strings[i];
                }
                arg.v_pointer = arg_items;
            }
            break;
        }
        default:
            PyErr_Format (PyExc_NotImplementedError,
                          "Retrieving properties of type %s is not implemented",
                          g_type_tag_to_string (g_type_info_get_tag (type_info)));
            goto out;
    }

    py_value = _pygi_argument_to_object (&arg, type_info, transfer);

out:
    g_free (property_name);
    if (property_info != NULL)
        g_base_info_unref (property_info);
    if (type_info != NULL)
        g_base_info_unref (type_info);

    return py_value;
}
Beispiel #14
0
gint
pygi_set_property_value_real (PyGObject *instance,
                              const gchar *attr_name,
                              PyObject *py_value)
{
    GType g_type;
    GIPropertyInfo *property_info = NULL;
    char *property_name = g_strdup (attr_name);
    GITypeInfo *type_info = NULL;
    GITypeTag type_tag;
    GITransfer transfer;
    GValue value = { 0, };
    GIArgument arg = { 0, };
    GParamSpec *pspec = NULL;
    gint ret_value = -1;

    canonicalize_key (property_name);

    g_type = pyg_type_from_object ((PyObject *)instance);
    property_info = _pygi_lookup_property_from_g_type (g_type, property_name);

    if (property_info == NULL)
        goto out;

    pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (instance->obj),
                                          attr_name);
    if (pspec == NULL)
        goto out;

    if (! (pspec->flags & G_PARAM_WRITABLE))
        goto out;

    type_info = g_property_info_get_type (property_info);
    transfer = g_property_info_get_ownership_transfer (property_info);
    arg = _pygi_argument_from_object (py_value, type_info, transfer);

    if (PyErr_Occurred())
        goto out;

    g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));

    // FIXME: Lots of types still unhandled
    type_tag = g_type_info_get_tag (type_info);
    switch (type_tag) {
        case GI_TYPE_TAG_INTERFACE:
        {
            GIBaseInfo *info;
            GIInfoType info_type;
            GType type;

            info = g_type_info_get_interface (type_info);
            type = g_registered_type_info_get_g_type (info);
            info_type = g_base_info_get_type (info);

            g_base_info_unref (info);

            switch (info_type) {
                case GI_INFO_TYPE_ENUM:
                    g_value_set_enum (&value, arg.v_int32);
                    break;
                case GI_INFO_TYPE_INTERFACE:
                case GI_INFO_TYPE_OBJECT:
                    g_value_set_object (&value, arg.v_pointer);
                    break;
                case GI_INFO_TYPE_BOXED:
                case GI_INFO_TYPE_STRUCT:
                case GI_INFO_TYPE_UNION:
                    if (g_type_is_a (type, G_TYPE_BOXED)) {
                        g_value_set_boxed (&value, arg.v_pointer);
                    } else {
                        PyErr_Format (PyExc_NotImplementedError,
                                      "Setting properties of type '%s' is not implemented",
                                      g_type_name (type));
                    }
                    break;
                default:
                    PyErr_Format (PyExc_NotImplementedError,
                                  "Setting properties of type '%s' is not implemented",
                                  g_type_name (type));
                    goto out;
            }
            break;
        }
        case GI_TYPE_TAG_BOOLEAN:
            g_value_set_boolean (&value, arg.v_boolean);
            break;
        case GI_TYPE_TAG_INT8:
            g_value_set_schar (&value, arg.v_int8);
            break;
        case GI_TYPE_TAG_INT16:
        case GI_TYPE_TAG_INT32:
            if (G_VALUE_HOLDS_LONG (&value))
                g_value_set_long (&value, arg.v_long);
            else
                g_value_set_int (&value, arg.v_int);
            break;
        case GI_TYPE_TAG_INT64:
            if (G_VALUE_HOLDS_LONG (&value))
                g_value_set_long (&value, arg.v_long);
            else
                g_value_set_int64 (&value, arg.v_int64);
            break;
        case GI_TYPE_TAG_UINT8:
            g_value_set_uchar (&value, arg.v_uint8);
            break;
        case GI_TYPE_TAG_UINT16:
        case GI_TYPE_TAG_UINT32:
            if (G_VALUE_HOLDS_ULONG (&value))
                g_value_set_ulong (&value, arg.v_ulong);
            else
                g_value_set_uint (&value, arg.v_uint);
            break;
        case GI_TYPE_TAG_UINT64:
            if (G_VALUE_HOLDS_ULONG (&value))
                g_value_set_ulong (&value, arg.v_ulong);
            else
                g_value_set_uint64 (&value, arg.v_uint64);
            break;
        case GI_TYPE_TAG_FLOAT:
            g_value_set_float (&value, arg.v_float);
            break;
        case GI_TYPE_TAG_DOUBLE:
            g_value_set_double (&value, arg.v_double);
            break;
        case GI_TYPE_TAG_GTYPE:
            g_value_set_gtype (&value, arg.v_size);
            break;
        case GI_TYPE_TAG_UTF8:
        case GI_TYPE_TAG_FILENAME:
            g_value_set_string (&value, arg.v_string);
            break;
        case GI_TYPE_TAG_GHASH:
            g_value_set_boxed (&value, arg.v_pointer);
            break;
        case GI_TYPE_TAG_GLIST:
            g_value_set_pointer (&value, arg.v_pointer);
            break;
        case GI_TYPE_TAG_ARRAY:
        {
            GArray *arg_items = (GArray*) arg.v_pointer;
            gchar** strings;
            int i;

            if (arg_items == NULL)
                goto out;

            strings = g_new0 (char*, arg_items->len);
            for (i = 0; i < arg_items->len; ++i) {
                strings[i] = g_array_index (arg_items, GIArgument, i).v_string;
            }
            g_array_free (arg_items, TRUE);
            g_value_set_boxed (&value, strings);
            break;
        }
        default:
            PyErr_Format (PyExc_NotImplementedError,
                          "Setting properties of type %s is not implemented",
                          g_type_tag_to_string (g_type_info_get_tag (type_info)));
            goto out;
    }

    g_object_set_property (instance->obj, attr_name, &value);

    ret_value = 0;

out:
    g_free (property_name);
    if (property_info != NULL)
        g_base_info_unref (property_info);
    if (type_info != NULL)
        g_base_info_unref (type_info);

    return ret_value;
}
/**
 * g_field_info_get_field:
 * @field_info: a #GIFieldInfo
 * @mem: pointer to a block of memory representing a C structure or union
 * @value: a #GArgument into which to store the value retrieved
 *
 * Reads a field identified by a #GFieldInfo from a C structure or
 * union.  This only handles fields of simple C types. It will fail
 * for a field of a composite type like a nested structure or union
 * even if that is actually readable.
 *
 * Returns: %TRUE if reading the field succeeded, otherwise %FALSE
 */
gboolean
g_field_info_get_field (GIFieldInfo *field_info,
			gpointer     mem,
			GArgument   *value)
{
    int offset;
    GITypeInfo *type_info;
    gboolean result = FALSE;

    if ((g_field_info_get_flags (field_info) & GI_FIELD_IS_READABLE) == 0)
      return FALSE;

    offset = g_field_info_get_offset (field_info);
    type_info = g_field_info_get_type (field_info);

    if (g_type_info_is_pointer (type_info))
      {
	value->v_pointer = G_STRUCT_MEMBER(gpointer, mem, offset);
	result = TRUE;
      }
    else
      {
	switch (g_type_info_get_tag (type_info))
	  {
	  case GI_TYPE_TAG_VOID:
	    g_warning("Field %s: should not be have void type",
		      g_base_info_get_name ((GIBaseInfo *)field_info));
	    break;
	  case GI_TYPE_TAG_BOOLEAN:
	    value->v_boolean = G_STRUCT_MEMBER(gboolean, mem, offset) != FALSE;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT8:
	  case GI_TYPE_TAG_UINT8:
	    value->v_uint8 = G_STRUCT_MEMBER(guint8, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT16:
	  case GI_TYPE_TAG_UINT16:
	  case GI_TYPE_TAG_SHORT:
	  case GI_TYPE_TAG_USHORT:
	    value->v_uint16 = G_STRUCT_MEMBER(guint16, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT32:
	  case GI_TYPE_TAG_UINT32:
	  case GI_TYPE_TAG_INT:
	  case GI_TYPE_TAG_UINT:
	    value->v_uint32 = G_STRUCT_MEMBER(guint32, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT64:
	  case GI_TYPE_TAG_UINT64:
	    value->v_uint64 = G_STRUCT_MEMBER(guint64, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_LONG:
	  case GI_TYPE_TAG_ULONG:
	    value->v_ulong = G_STRUCT_MEMBER(gulong, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_SSIZE:
	  case GI_TYPE_TAG_SIZE:
	  case GI_TYPE_TAG_GTYPE:
	    value->v_size = G_STRUCT_MEMBER(gsize, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_FLOAT:
	    value->v_float = G_STRUCT_MEMBER(gfloat, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_DOUBLE:
	    value->v_double = G_STRUCT_MEMBER(gdouble, mem, offset);
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_TIME_T:
#if SIZEOF_TIME_T == 4
	    value->v_int32 = G_STRUCT_MEMBER(time_t, mem, offset);
#elif SIZEOF_TIME_T == 8
	    value->v_int64 = G_STRUCT_MEMBER(time_t, mem, offset);
#else
#  error "Unexpected size for time_t: not 4 or 8"
#endif
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_UTF8:
	  case GI_TYPE_TAG_FILENAME:
	  case GI_TYPE_TAG_ARRAY:
	  case GI_TYPE_TAG_GLIST:
	  case GI_TYPE_TAG_GSLIST:
	  case GI_TYPE_TAG_GHASH:
	    g_warning("Field %s: type %s should have is_pointer set",
		      g_base_info_get_name ((GIBaseInfo *)field_info),
		      g_type_tag_to_string (g_type_info_get_tag (type_info)));
	    break;
	  case GI_TYPE_TAG_ERROR:
	    /* Needs to be handled by the language binding directly */
	    break;
	  case GI_TYPE_TAG_INTERFACE:
	    {
	      GIBaseInfo *interface = g_type_info_get_interface (type_info);
	      switch (g_base_info_get_type (interface))
		{
		case GI_INFO_TYPE_STRUCT:
		case GI_INFO_TYPE_UNION:
		case GI_INFO_TYPE_BOXED:
		  /* Needs to be handled by the language binding directly */
		  break;
		case GI_INFO_TYPE_OBJECT:
		  break;
		case GI_INFO_TYPE_ENUM:
		case GI_INFO_TYPE_FLAGS:
		  {
		    /* FIXME: there's a mismatch here between the value->v_int we use
		     * here and the glong result returned from g_value_info_get_value().
		     * But to switch this to glong, we'd have to make g_function_info_invoke()
		     * translate value->v_long to the proper ABI for an enum function
		     * call parameter, which will usually be int, and then fix up language
		     * bindings.
		     */
		    GITypeTag storage_type = g_enum_info_get_storage_type ((GIEnumInfo *)interface);
		    switch (storage_type)
		      {
		      case GI_TYPE_TAG_INT8:
		      case GI_TYPE_TAG_UINT8:
			value->v_int = (gint)G_STRUCT_MEMBER(guint8, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT16:
		      case GI_TYPE_TAG_UINT16:
		      case GI_TYPE_TAG_SHORT:
		      case GI_TYPE_TAG_USHORT:
			value->v_int = (gint)G_STRUCT_MEMBER(guint16, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT32:
		      case GI_TYPE_TAG_UINT32:
		      case GI_TYPE_TAG_INT:
		      case GI_TYPE_TAG_UINT:
			value->v_int = (gint)G_STRUCT_MEMBER(guint32, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT64:
		      case GI_TYPE_TAG_UINT64:
			value->v_int = (gint)G_STRUCT_MEMBER(guint64, mem, offset);
			result = TRUE;
			break;
		      case GI_TYPE_TAG_LONG:
		      case GI_TYPE_TAG_ULONG:
			value->v_int = (gint)G_STRUCT_MEMBER(gulong, mem, offset);
			result = TRUE;
			break;
		      default:
			g_warning("Field %s: Unexpected enum storage type %s",
				  g_base_info_get_name ((GIBaseInfo *)field_info),
				  g_type_tag_to_string (storage_type));
			break;
		      }
		    break;
		  }
		case GI_INFO_TYPE_VFUNC:
		case GI_INFO_TYPE_CALLBACK:
		  g_warning("Field %s: Interface type %d should have is_pointer set",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		case GI_INFO_TYPE_INVALID:
		case GI_INFO_TYPE_INTERFACE:
		case GI_INFO_TYPE_FUNCTION:
		case GI_INFO_TYPE_CONSTANT:
		case GI_INFO_TYPE_ERROR_DOMAIN:
		case GI_INFO_TYPE_VALUE:
		case GI_INFO_TYPE_SIGNAL:
		case GI_INFO_TYPE_PROPERTY:
		case GI_INFO_TYPE_FIELD:
		case GI_INFO_TYPE_ARG:
		case GI_INFO_TYPE_TYPE:
		case GI_INFO_TYPE_UNRESOLVED:
		  g_warning("Field %s: Interface type %d not expected",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		}

	      g_base_info_unref ((GIBaseInfo *)interface);
	      break;
	    }
	    break;
	  }
      }

    g_base_info_unref ((GIBaseInfo *)type_info);

    return result;
}
/**
 * g_field_info_set_field:
 * @field_info: a #GIFieldInfo
 * @mem: pointer to a block of memory representing a C structure or union
 * @value: a #GArgument holding the value to store
 *
 * Writes a field identified by a #GFieldInfo to a C structure or
 * union.  This only handles fields of simple C types. It will fail
 * for a field of a composite type like a nested structure or union
 * even if that is actually writable. Note also that that it will refuse
 * to write fields where memory management would by required. A field
 * with a type such as 'char *' must be set with a setter function.
 *
 * Returns: %TRUE if writing the field succeeded, otherwise %FALSE
 */
gboolean
g_field_info_set_field (GIFieldInfo     *field_info,
			gpointer         mem,
			const GArgument *value)
{
    int offset;
    GITypeInfo *type_info;
    gboolean result = FALSE;

    if ((g_field_info_get_flags (field_info) & GI_FIELD_IS_WRITABLE) == 0)
      return FALSE;

    offset = g_field_info_get_offset (field_info);
    type_info = g_field_info_get_type (field_info);

    if (!g_type_info_is_pointer (type_info))
      {
	switch (g_type_info_get_tag (type_info))
	  {
	  case GI_TYPE_TAG_VOID:
	    g_warning("Field %s: should not be have void type",
		      g_base_info_get_name ((GIBaseInfo *)field_info));
	    break;
	  case GI_TYPE_TAG_BOOLEAN:
	    G_STRUCT_MEMBER(gboolean, mem, offset) = value->v_boolean != FALSE;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT8:
	  case GI_TYPE_TAG_UINT8:
	    G_STRUCT_MEMBER(guint8, mem, offset) = value->v_uint8;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT16:
	  case GI_TYPE_TAG_UINT16:
	  case GI_TYPE_TAG_SHORT:
	  case GI_TYPE_TAG_USHORT:
	    G_STRUCT_MEMBER(guint16, mem, offset) = value->v_uint16;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT32:
	  case GI_TYPE_TAG_UINT32:
	  case GI_TYPE_TAG_INT:
	  case GI_TYPE_TAG_UINT:
	    G_STRUCT_MEMBER(guint32, mem, offset) = value->v_uint32;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_INT64:
	  case GI_TYPE_TAG_UINT64:
	    G_STRUCT_MEMBER(guint64, mem, offset) = value->v_uint64;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_LONG:
	  case GI_TYPE_TAG_ULONG:
	    G_STRUCT_MEMBER(gulong, mem, offset)= value->v_ulong;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_SSIZE:
	  case GI_TYPE_TAG_SIZE:
	  case GI_TYPE_TAG_GTYPE:
	    G_STRUCT_MEMBER(gsize, mem, offset) = value->v_size;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_FLOAT:
	    G_STRUCT_MEMBER(gfloat, mem, offset) = value->v_float;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_DOUBLE:
	    G_STRUCT_MEMBER(gdouble, mem, offset)= value->v_double;
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_TIME_T:
#if SIZEOF_TIME_T == 4
            G_STRUCT_MEMBER(time_t, mem, offset) = value->v_int32;
#elif SIZEOF_TIME_T == 8
            G_STRUCT_MEMBER(time_t, mem, offset) = value->v_int64;
#else
#  error "Unexpected size for time_t: not 4 or 8"
#endif
	    result = TRUE;
	    break;
	  case GI_TYPE_TAG_UTF8:
	  case GI_TYPE_TAG_FILENAME:
	  case GI_TYPE_TAG_ARRAY:
	  case GI_TYPE_TAG_GLIST:
	  case GI_TYPE_TAG_GSLIST:
	  case GI_TYPE_TAG_GHASH:
	    g_warning("Field %s: type %s should have is_pointer set",
		      g_base_info_get_name ((GIBaseInfo *)field_info),
		      g_type_tag_to_string (g_type_info_get_tag (type_info)));
	    break;
	  case GI_TYPE_TAG_ERROR:
	    /* Needs to be handled by the language binding directly */
	    break;
	  case GI_TYPE_TAG_INTERFACE:
	    {
	      GIBaseInfo *interface = g_type_info_get_interface (type_info);
	      switch (g_base_info_get_type (interface))
		{
		case GI_INFO_TYPE_STRUCT:
		case GI_INFO_TYPE_UNION:
		case GI_INFO_TYPE_BOXED:
		  /* Needs to be handled by the language binding directly */
		  break;
		case GI_INFO_TYPE_OBJECT:
		  break;
		case GI_INFO_TYPE_ENUM:
		case GI_INFO_TYPE_FLAGS:
		  {
		    /* See FIXME above
		     */
		    GITypeTag storage_type = g_enum_info_get_storage_type ((GIEnumInfo *)interface);
		    switch (storage_type)
		      {
		      case GI_TYPE_TAG_INT8:
		      case GI_TYPE_TAG_UINT8:
			G_STRUCT_MEMBER(guint8, mem, offset) = (guint8)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT16:
		      case GI_TYPE_TAG_UINT16:
		      case GI_TYPE_TAG_SHORT:
		      case GI_TYPE_TAG_USHORT:
			G_STRUCT_MEMBER(guint16, mem, offset) = (guint16)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT32:
		      case GI_TYPE_TAG_UINT32:
		      case GI_TYPE_TAG_INT:
		      case GI_TYPE_TAG_UINT:
			G_STRUCT_MEMBER(guint32, mem, offset) = (guint32)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_INT64:
		      case GI_TYPE_TAG_UINT64:
			G_STRUCT_MEMBER(guint64, mem, offset) = (guint64)value->v_int;
			result = TRUE;
			break;
		      case GI_TYPE_TAG_LONG:
		      case GI_TYPE_TAG_ULONG:
			G_STRUCT_MEMBER(gulong, mem, offset) = (gulong)value->v_int;
			result = TRUE;
			break;
		      default:
			g_warning("Field %s: Unexpected enum storage type %s",
				  g_base_info_get_name ((GIBaseInfo *)field_info),
				  g_type_tag_to_string (storage_type));
			break;
		      }
		    break;
		  }
		  break;
		case GI_INFO_TYPE_VFUNC:
		case GI_INFO_TYPE_CALLBACK:
		  g_warning("Field%s: Interface type %d should have is_pointer set",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		case GI_INFO_TYPE_INVALID:
		case GI_INFO_TYPE_INTERFACE:
		case GI_INFO_TYPE_FUNCTION:
		case GI_INFO_TYPE_CONSTANT:
		case GI_INFO_TYPE_ERROR_DOMAIN:
		case GI_INFO_TYPE_VALUE:
		case GI_INFO_TYPE_SIGNAL:
		case GI_INFO_TYPE_PROPERTY:
		case GI_INFO_TYPE_FIELD:
		case GI_INFO_TYPE_ARG:
		case GI_INFO_TYPE_TYPE:
		case GI_INFO_TYPE_UNRESOLVED:
		  g_warning("Field %s: Interface type %d not expected",
			    g_base_info_get_name ((GIBaseInfo *)field_info),
			    g_base_info_get_type (interface));
		  break;
		}

	      g_base_info_unref ((GIBaseInfo *)interface);
	      break;
	    }
	    break;
	  }
      }

    g_base_info_unref ((GIBaseInfo *)type_info);

    return result;
}
Beispiel #17
0
GIArgument *
rb_gi_in_argument_from_ruby(GIArgument *argument, GITypeInfo *type_info,
                            VALUE rb_argument)
{
    GITypeTag type_tag;

    memset(argument, 0, sizeof(GIArgument));

    type_tag = g_type_info_get_tag(type_info);
    switch (type_tag) {
      case GI_TYPE_TAG_VOID:
        break;
      case GI_TYPE_TAG_BOOLEAN:
        argument->v_boolean = RVAL2CBOOL(rb_argument);
        break;
      case GI_TYPE_TAG_INT8:
        argument->v_int8 = NUM2INT(rb_argument);
        break;
      case GI_TYPE_TAG_UINT8:
        argument->v_uint8 = NUM2UINT(rb_argument);
        break;
      case GI_TYPE_TAG_INT16:
        argument->v_int16 = NUM2INT(rb_argument);
        break;
      case GI_TYPE_TAG_UINT16:
        argument->v_uint16 = NUM2UINT(rb_argument);
        break;
      case GI_TYPE_TAG_INT32:
        argument->v_int32 = NUM2INT(rb_argument);
        break;
      case GI_TYPE_TAG_UINT32:
        argument->v_uint32 = NUM2UINT(rb_argument);
        break;
      case GI_TYPE_TAG_INT64:
        argument->v_int64 = NUM2LONG(rb_argument);
        break;
      case GI_TYPE_TAG_UINT64:
        argument->v_uint64 = NUM2ULONG(rb_argument);
        break;
      case GI_TYPE_TAG_FLOAT:
        argument->v_float = NUM2DBL(rb_argument);
        break;
      case GI_TYPE_TAG_DOUBLE:
        argument->v_double = NUM2DBL(rb_argument);
        break;
      case GI_TYPE_TAG_GTYPE:
        /* TODO: support GLib::Type and String as GType name. */
        argument->v_size = NUM2ULONG(rb_argument);
        break;
      case GI_TYPE_TAG_UTF8:
        /* TODO: support UTF-8 convert like rb_argument.encode("UTF-8"). */
        argument->v_string = (gchar *)RVAL2CSTR(rb_argument);
        break;
      case GI_TYPE_TAG_FILENAME:
        argument->v_string = (gchar *)RVAL2CSTR(rb_argument);
        break;
      case GI_TYPE_TAG_ARRAY:
        rb_gi_argument_from_ruby_array(argument, type_info, rb_argument);
        break;
      case GI_TYPE_TAG_INTERFACE:
        rb_gi_argument_from_ruby_interface(argument, type_info, rb_argument);
        break;
      case GI_TYPE_TAG_GLIST:
      case GI_TYPE_TAG_GSLIST:
      case GI_TYPE_TAG_GHASH:
      case GI_TYPE_TAG_ERROR:
      case GI_TYPE_TAG_UNICHAR:
        rb_raise(rb_eNotImpError,
                 "TODO: Ruby -> GIArgument(%s)",
                 g_type_tag_to_string(type_tag));
        break;
      default:
        g_assert_not_reached();
        break;
    }

    return argument;
}
static SV *
ghash_to_sv (GITypeInfo *info,
             gpointer pointer,
             GITransfer transfer)
{
	GITypeInfo *key_param_info, *value_param_info;
#ifdef NOISY
        GITypeTag key_type_tag, value_type_tag;
#endif
        gpointer key_p, value_p;
	GITransfer item_transfer;
	GHashTableIter iter;
	HV *hv;

	if (pointer == NULL) {
		return &PL_sv_undef;
	}

	item_transfer = transfer == GI_TRANSFER_EVERYTHING
		      ? GI_TRANSFER_EVERYTHING
                      : GI_TRANSFER_NOTHING;

	key_param_info = g_type_info_get_param_type (info, 0);
        value_param_info = g_type_info_get_param_type (info, 1);

#ifdef NOISY
        key_type_tag = g_type_info_get_tag (key_param_info);
        value_type_tag = g_type_info_get_tag (value_param_info);
#endif

	dwarn ("    GHashTable: pointer %p\n"
               "      key type tag %d (%s)\n"
               "      value type tag %d (%s)\n",
	       pointer,
	       key_type_tag, g_type_tag_to_string (key_type_tag),
	       value_type_tag, g_type_tag_to_string (value_type_tag));

	hv = newHV ();

        g_hash_table_iter_init (&iter, pointer);
        while (g_hash_table_iter_next (&iter, &key_p, &value_p)) {
		GIArgument arg = { 0, };
                SV *key_sv, *value_sv;

		dwarn ("      converting key pointer %p\n", key_p);
		arg.v_pointer = key_p;
		key_sv = arg_to_sv (&arg, key_param_info, item_transfer, NULL);
		if (key_sv == NULL)
                        break;

                dwarn ("      converting value pointer %p\n", value_p);
                arg.v_pointer = value_p;
                value_sv = arg_to_sv (&arg, value_param_info, item_transfer, NULL);
                if (value_sv == NULL)
                        break;

                (void) hv_store_ent (hv, key_sv, value_sv, 0);
	}

	g_base_info_unref ((GIBaseInfo *) key_param_info);
        g_base_info_unref ((GIBaseInfo *) value_param_info);

	return newRV_noinc ((SV *) hv);
}
static gpointer
sv_to_ghash (GITransfer transfer,
             GITypeInfo *type_info,
             SV *sv)
{
	HV *hv;
        HE *he;
	GITransfer item_transfer;
	gpointer hash;
	GITypeInfo *key_param_info, *value_param_info;
        GITypeTag key_type_tag;
        GHashFunc hash_func;
        GEqualFunc equal_func;
        I32 n_keys;

	dwarn ("%s: sv %p\n", G_STRFUNC, sv);

	if (!gperl_sv_is_defined (sv))
		return NULL;

	if (!gperl_sv_is_hash_ref (sv))
		ccroak ("need an hash ref to convert to GHashTable");

	hv = (HV *) SvRV (sv);

	item_transfer = GI_TRANSFER_NOTHING;
	switch (transfer) {
	    case GI_TRANSFER_EVERYTHING:
		item_transfer = GI_TRANSFER_EVERYTHING;
		break;
	    case GI_TRANSFER_CONTAINER:
		/* nothing special to do */
		break;
	    case GI_TRANSFER_NOTHING:
		/* FIXME: need to free hash after call */
		break;
	}

	key_param_info = g_type_info_get_param_type (type_info, 0);
        value_param_info = g_type_info_get_param_type (type_info, 1);

        key_type_tag = g_type_info_get_tag (key_param_info);

        switch (key_type_tag)
          {
          case GI_TYPE_TAG_FILENAME:
          case GI_TYPE_TAG_UTF8:
            hash_func = g_str_hash;
            equal_func = g_str_equal;
            break;

          default:
            hash_func = NULL;
            equal_func = NULL;
            break;
          }

	dwarn ("  GHashTable with transfer %d\n"
               "    key_param_info %p with type tag %d (%s)\n"
               "    value_param_info %p with type tag %d (%s)\n",
               transfer,
	       key_param_info,
	       g_type_info_get_tag (key_param_info),
	       g_type_tag_to_string (g_type_info_get_tag (key_param_info)),
	       value_param_info,
	       g_type_info_get_tag (value_param_info),
	       g_type_tag_to_string (g_type_info_get_tag (value_param_info)));

        hash = g_hash_table_new (hash_func, equal_func);

        n_keys = hv_iterinit (hv);
        if (n_keys == 0)
                goto out;

        while ((he = hv_iternext (hv)) != NULL) {
                SV *sv;
                GIArgument arg = { 0, };
                gpointer key_p, value_p;

                key_p = value_p = NULL;

                sv = hv_iterkeysv (he);
		if (sv && gperl_sv_is_defined (sv)) {
			dwarn ("    converting key SV %p\n", sv);
			/* FIXME: Is it OK to always allow undef here? */
			sv_to_arg (sv, &arg, NULL, key_param_info,
			           item_transfer, TRUE, NULL);
                        key_p = arg.v_pointer;
		}

                sv = hv_iterval (hv, he);
                if (sv && gperl_sv_is_defined (sv)) {
                        dwarn ("    converting value SV %p\n", sv);
                        sv_to_arg (sv, &arg, NULL, key_param_info,
                                   item_transfer, TRUE, NULL);
                        value_p = arg.v_pointer;
                }

                if (key_p != NULL && value_p != NULL)
                        g_hash_table_insert (hash, key_p, value_p);
	}

out:
	dwarn ("    -> hash %p of size %d\n", hash, g_hash_table_size (hash));

        g_base_info_unref ((GIBaseInfo *) key_param_info);
	g_base_info_unref ((GIBaseInfo *) value_param_info);

	return hash;
}
static gboolean
get_type_size_alignment (GIrTypelibBuild   *build,
			 GIrNodeType *type,
                         gint        *size,
                         gint        *alignment,
                         const char  *who)
{
  ffi_type *type_ffi;

  if (type->is_pointer)
    {
      type_ffi = &ffi_type_pointer;
    }
  else if (type->tag == GI_TYPE_TAG_ARRAY)
    {
      gint elt_size, elt_alignment;

      if (!type->has_size
          || !get_type_size_alignment(build, type->parameter_type1,
                                      &elt_size, &elt_alignment, who))
        {
          *size = -1;
          *alignment = -1;
          return FALSE;
        }

      *size = type->size * elt_size;
      *alignment = elt_alignment;

      return TRUE;
    }
  else
    {
      if (type->tag == GI_TYPE_TAG_INTERFACE)
	{
	  return get_interface_size_alignment (build, type, size, alignment, who);
	}
      else
	{
	  type_ffi = gi_type_tag_get_ffi_type (type->tag, type->is_pointer);

	  if (type_ffi == &ffi_type_void)
	    {
	      g_warning ("%s has void type", who);
	      *size = -1;
	      *alignment = -1;
	      return FALSE;
	    }
	  else if (type_ffi == &ffi_type_pointer)
	    {
	      g_warning ("%s has is not a pointer and is of type %s",
                         who,
			 g_type_tag_to_string (type->tag));
	      *size = -1;
	      *alignment = -1;
	      return FALSE;
	    }
	}
    }

  g_assert (type_ffi);
  *size = type_ffi->size;
  *alignment = type_ffi->alignment;

  return TRUE;
}
static void
invoke_callback (ffi_cif* cif, gpointer resp, gpointer* args, gpointer userdata)
{
	GPerlI11nPerlCallbackInfo *info;
	GICallableInfo *cb_interface;
	GPerlI11nInvocationInfo iinfo = {0,};
	guint i;
	guint in_inout;
	guint n_return_values, n_returned;
	I32 context;
	dGPERL_CALLBACK_MARSHAL_SP;

	PERL_UNUSED_VAR (cif);

	/* unwrap callback info struct from userdata */
	info = (GPerlI11nPerlCallbackInfo *) userdata;
	cb_interface = (GICallableInfo *) info->interface;

	prepare_perl_invocation_info (&iinfo, cb_interface);

	/* set perl context */
	GPERL_CALLBACK_MARSHAL_INIT (info);

	ENTER;
	SAVETMPS;

	PUSHMARK (SP);

	/* find arguments; use type information from interface to find in and
	 * in-out args and their types, count in-out and out args, and find
	 * suitable converters; push in and in-out arguments onto the perl
	 * stack */
	in_inout = 0;
	for (i = 0; i < iinfo.n_args; i++) {
		GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i);
		GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
		GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
		GIDirection direction = g_arg_info_get_direction (arg_info);

		iinfo.current_pos = i;

		/* the closure argument, which we handle separately, is marked
		 * by having get_closure == i */
		if (g_arg_info_get_closure (arg_info) == (gint) i) {
			g_base_info_unref ((GIBaseInfo *) arg_info);
			g_base_info_unref ((GIBaseInfo *) arg_type);
			continue;
		}

		dwarn ("arg info: %s (%p)\n"
		       "  direction: %d\n"
		       "  is return value: %d\n"
		       "  is optional: %d\n"
		       "  may be null: %d\n"
		       "  transfer: %d\n",
		       g_base_info_get_name (arg_info), arg_info,
		       g_arg_info_get_direction (arg_info),
		       g_arg_info_is_return_value (arg_info),
		       g_arg_info_is_optional (arg_info),
		       g_arg_info_may_be_null (arg_info),
		       g_arg_info_get_ownership_transfer (arg_info));

		dwarn ("arg type: %p\n"
		       "  is pointer: %d\n"
		       "  tag: %s (%d)\n",
		       arg_type,
		       g_type_info_is_pointer (arg_type),
		       g_type_tag_to_string (g_type_info_get_tag (arg_type)), g_type_info_get_tag (arg_type));

		if (direction == GI_DIRECTION_IN ||
		    direction == GI_DIRECTION_INOUT)
		{
			GIArgument arg;
			SV *sv;
			raw_to_arg (args[i], &arg, arg_type);
			sv = arg_to_sv (&arg, arg_type, transfer, &iinfo);
			/* If arg_to_sv returns NULL, we take that as 'skip
			 * this argument'; happens for GDestroyNotify, for
			 * example. */
			if (sv)
				XPUSHs (sv_2mortal (sv));
		}

		if (direction == GI_DIRECTION_INOUT ||
		    direction == GI_DIRECTION_OUT)
		{
			in_inout++;
		}

		g_base_info_unref ((GIBaseInfo *) arg_info);
		g_base_info_unref ((GIBaseInfo *) arg_type);
	}

	/* push user data onto the Perl stack */
	if (info->data)
		XPUSHs (sv_2mortal (SvREFCNT_inc (info->data)));

	PUTBACK;

	/* determine suitable Perl call context */
	context = G_VOID | G_DISCARD;
	if (iinfo.has_return_value) {
		context = in_inout > 0
		  ? G_ARRAY
		  : G_SCALAR;
	} else {
		if (in_inout == 1) {
			context = G_SCALAR;
		} else if (in_inout > 1) {
			context = G_ARRAY;
		}
	}

	/* do the call, demand #in-out+#out+#return-value return values */
	n_return_values = iinfo.has_return_value
	  ? in_inout + 1
	  : in_inout;
	n_returned = info->sub_name
		? call_method (info->sub_name, context)
		: call_sv (info->code, context);
	if (n_return_values != 0 && n_returned != n_return_values) {
		ccroak ("callback returned %d values "
		        "but is supposed to return %d values",
		        n_returned, n_return_values);
	}

	/* call-scoped callback infos are freed by
	 * Glib::Object::Introspection::_FuncWrapper::DESTROY */

	SPAGAIN;

	/* convert in-out and out values and stuff them back into args */
	if (in_inout > 0) {
		SV **returned_values;
		int out_index;

		returned_values = g_new0 (SV *, in_inout);

		/* pop scalars off the stack and put them into the array;
		 * reverse the order since POPs pops items off of the end of
		 * the stack. */
		for (i = 0; i < in_inout; i++) {
			returned_values[in_inout - i - 1] = POPs;
		}

		out_index = 0;
		for (i = 0; i < iinfo.n_args; i++) {
			GIArgInfo *arg_info = g_callable_info_get_arg (cb_interface, i);
			GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
			GIDirection direction = g_arg_info_get_direction (arg_info);
			gpointer out_pointer = * (gpointer *) args[i];

			if (!out_pointer) {
				dwarn ("skipping out arg %d\n", i);
				g_base_info_unref (arg_info);
				g_base_info_unref (arg_type);
				continue;
			}

			if (direction == GI_DIRECTION_INOUT ||
			    direction == GI_DIRECTION_OUT)
			{
				GIArgument tmp_arg;
				GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
				gboolean may_be_null = g_arg_info_may_be_null (arg_info);
				gboolean is_caller_allocated = g_arg_info_is_caller_allocates (arg_info);
				if (is_caller_allocated) {
					tmp_arg.v_pointer = out_pointer;
				}
				sv_to_arg (returned_values[out_index], &tmp_arg,
				           arg_info, arg_type,
				           transfer, may_be_null, &iinfo);
				if (!is_caller_allocated) {
					arg_to_raw (&tmp_arg, out_pointer, arg_type);
				}
				out_index++;
			}

			g_base_info_unref (arg_info);
			g_base_info_unref (arg_type);
		}

		g_free (returned_values);
	}
static SV *
arg_to_sv (GIArgument * arg,
           GITypeInfo * info,
           GITransfer transfer,
           GPerlI11nInvocationInfo *iinfo)
{
	GITypeTag tag = g_type_info_get_tag (info);
	gboolean own = transfer >= GI_TRANSFER_CONTAINER;

	dwarn ("  arg_to_sv: info %p with type tag %d (%s)\n",
	       info, tag, g_type_tag_to_string (tag));

	switch (tag) {
	    case GI_TYPE_TAG_VOID:
	    {
		SV *sv = callback_data_to_sv (arg->v_pointer, iinfo);
		dwarn ("    argument with no type information -> %s\n",
		       sv ? "callback data" : "undef");
		return sv ? SvREFCNT_inc (sv) : &PL_sv_undef;
	    }

	    case GI_TYPE_TAG_BOOLEAN:
		return boolSV (arg->v_boolean);

	    case GI_TYPE_TAG_INT8:
		return newSViv (arg->v_int8);

	    case GI_TYPE_TAG_UINT8:
		return newSVuv (arg->v_uint8);

	    case GI_TYPE_TAG_INT16:
		return newSViv (arg->v_int16);

	    case GI_TYPE_TAG_UINT16:
		return newSVuv (arg->v_uint16);

	    case GI_TYPE_TAG_INT32:
		return newSViv (arg->v_int32);

	    case GI_TYPE_TAG_UINT32:
		return newSVuv (arg->v_uint32);

	    case GI_TYPE_TAG_INT64:
		return newSVGInt64 (arg->v_int64);

	    case GI_TYPE_TAG_UINT64:
		return newSVGUInt64 (arg->v_uint64);

	    case GI_TYPE_TAG_FLOAT:
		return newSVnv (arg->v_float);

	    case GI_TYPE_TAG_DOUBLE:
		return newSVnv (arg->v_double);

	    case GI_TYPE_TAG_UNICHAR:
	    {
		SV *sv;
		gchar buffer[6];
		gint length = g_unichar_to_utf8 (arg->v_uint32, buffer);
		sv = newSVpv (buffer, length);
		SvUTF8_on (sv);
		return sv;
	    }

	    case GI_TYPE_TAG_GTYPE: {
		/* GType == gsize */
		const char *package = gperl_package_from_type (arg->v_size);
		if (!package)
			package = g_type_name (arg->v_size);
		return newSVpv (package, PL_na);
	    }

	    case GI_TYPE_TAG_ARRAY:
		return array_to_sv (info, arg->v_pointer, transfer, iinfo);

	    case GI_TYPE_TAG_INTERFACE:
		return interface_to_sv (info, arg, own, iinfo);

	    case GI_TYPE_TAG_GLIST:
	    case GI_TYPE_TAG_GSLIST:
		return glist_to_sv (info, arg->v_pointer, transfer);

	    case GI_TYPE_TAG_GHASH:
                return ghash_to_sv (info, arg->v_pointer, transfer);

	    case GI_TYPE_TAG_ERROR:
		ccroak ("FIXME - GI_TYPE_TAG_ERROR");
		break;

	    case GI_TYPE_TAG_UTF8:
	    {
		SV *sv = newSVGChar (arg->v_string);
		if (own)
			g_free (arg->v_string);
		return sv;
	    }

	    case GI_TYPE_TAG_FILENAME:
	    {
		SV *sv = newSVpv (arg->v_string, PL_na);
		if (own)
			g_free (arg->v_string);
		return sv;
	    }

	    default:
		ccroak ("Unhandled info tag %d in arg_to_sv", tag);
	}

	return NULL;
}
Beispiel #23
0
VALUE
rb_gi_argument_to_ruby(GIArgument *argument, GITypeInfo *type_info)
{
    VALUE rb_argument = Qnil;
    GITypeTag type_tag;

    type_tag = g_type_info_get_tag(type_info);
    switch (type_tag) {
      case GI_TYPE_TAG_VOID:
        rb_argument = Qnil;
        break;
      case GI_TYPE_TAG_BOOLEAN:
        rb_argument = CBOOL2RVAL(argument->v_boolean);
        break;
      case GI_TYPE_TAG_INT8:
        rb_argument = INT2NUM(argument->v_int8);
        break;
      case GI_TYPE_TAG_UINT8:
        rb_argument = UINT2NUM(argument->v_uint8);
        break;
      case GI_TYPE_TAG_INT16:
        rb_argument = INT2NUM(argument->v_int16);
        break;
      case GI_TYPE_TAG_UINT16:
        rb_argument = UINT2NUM(argument->v_uint16);
        break;
      case GI_TYPE_TAG_INT32:
        rb_argument = INT2NUM(argument->v_int32);
        break;
      case GI_TYPE_TAG_UINT32:
        rb_argument = UINT2NUM(argument->v_uint32);
        break;
      case GI_TYPE_TAG_INT64:
        rb_argument = LONG2NUM(argument->v_int64);
        break;
      case GI_TYPE_TAG_UINT64:
        rb_argument = ULONG2NUM(argument->v_uint64);
        break;
      case GI_TYPE_TAG_FLOAT:
        rb_argument = DBL2NUM(argument->v_float);
        break;
      case GI_TYPE_TAG_DOUBLE:
        rb_argument = DBL2NUM(argument->v_double);
        break;
      case GI_TYPE_TAG_GTYPE:
        rb_argument = rbgobj_gtype_new(argument->v_size);
        break;
      case GI_TYPE_TAG_UTF8:
        rb_argument = CSTR2RVAL(argument->v_string);
        break;
      case GI_TYPE_TAG_FILENAME:
        /* TODO: set encoding */
        rb_argument = CSTR2RVAL(argument->v_string);
        break;
      case GI_TYPE_TAG_ARRAY:
        rb_argument = array_to_ruby(argument->v_pointer, type_info);
        break;
      case GI_TYPE_TAG_INTERFACE:
        rb_argument = interface_to_ruby(argument, type_info);
        break;
      case GI_TYPE_TAG_GLIST:
      case GI_TYPE_TAG_GSLIST:
      case GI_TYPE_TAG_GHASH:
        rb_raise(rb_eNotImpError, "TODO: GIArgument(unichar) -> Ruby");
        break;
      case GI_TYPE_TAG_ERROR:
        rb_argument = GERROR2RVAL(argument->v_pointer);
        break;
      case GI_TYPE_TAG_UNICHAR:
        rb_raise(rb_eNotImpError,
                 "TODO: GIArgument(%s) -> Ruby",
                 g_type_tag_to_string(type_tag));
        break;
      default:
        g_assert_not_reached();
        break;
    }

    return rb_argument;
}