static PyObject *
_wrap_g_constant_info_get_value (PyGIBaseInfo *self)
{
    GITypeInfo *type_info;
    GIArgument value;
    PyObject *py_value;
    gboolean free_array = FALSE;

    if (g_constant_info_get_value ( (GIConstantInfo *) self->info, &value) < 0) {
        PyErr_SetString (PyExc_RuntimeError, "unable to get value");
        return NULL;
    }

    type_info = g_constant_info_get_type ( (GIConstantInfo *) self->info);

    if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY) {
        value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL,
                                                   type_info, &free_array);
    }

    py_value = _pygi_argument_to_object (&value, type_info, GI_TRANSFER_NOTHING);
    
    if (free_array) {
        g_array_free (value.v_pointer, FALSE);
    }

    g_constant_info_free_value (self->info, &value);
    g_base_info_unref ( (GIBaseInfo *) type_info);

    return py_value;
}
Beispiel #2
0
/**
 * _pygi_argument_array_length_marshal:
 * @length_arg_index: Index of length argument in the callables args list.
 * @user_data1: (type Array(GValue)): Array of GValue arguments to retrieve length
 * @user_data2: (type GICallableInfo): Callable info to get the argument from.
 *
 * Generic marshalling policy for array length arguments in callables.
 *
 * Returns: The length of the array or -1 on failure.
 */
gssize
_pygi_argument_array_length_marshal (gsize length_arg_index,
                                     void *user_data1,
                                     void *user_data2)
{
    GIArgInfo length_arg_info;
    GITypeInfo length_type_info;
    GIArgument length_arg;
    gssize array_len = -1;
    GValue *values = (GValue *)user_data1;
    GICallableInfo *callable_info = (GICallableInfo *)user_data2;

    g_callable_info_load_arg (callable_info, length_arg_index, &length_arg_info);
    g_arg_info_load_type (&length_arg_info, &length_type_info);

    length_arg = _pygi_argument_from_g_value (&(values[length_arg_index]),
                                              &length_type_info);
    if (!pygi_argument_to_gssize (&length_arg,
                                  g_type_info_get_tag (&length_type_info),
                                  &array_len)) {
        return -1;
    }

    return array_len;
}
Beispiel #3
0
static VALUE
rg_invoke(VALUE self, VALUE rb_arguments)
{
    GIFunctionInfo *info;
    VALUE rb_out_args;
    VALUE rb_return_value;

    info = SELF(self);
    /* TODO: use rb_protect() */
    rb_out_args = rb_gi_function_info_invoke_raw(info,
                                                 self,
                                                 Qnil,
                                                 rb_arguments,
                                                 NULL,
                                                 &rb_return_value);

    if (NIL_P(rb_out_args)) {
        return rb_return_value;
    } else {
        GICallableInfo *callable_info = (GICallableInfo *)info;
        GITypeInfo return_value_info;
        g_callable_info_load_return_type(callable_info, &return_value_info);
        if (g_type_info_get_tag(&return_value_info) != GI_TYPE_TAG_VOID) {
            rb_ary_unshift(rb_out_args, rb_return_value);
        }
        if (RARRAY_LEN(rb_out_args) == 1) {
            return RARRAY_PTR(rb_out_args)[0];
        } else {
            return rb_out_args;
        }
    }
}
Beispiel #4
0
static gboolean
pygi_arg_basic_type_setup_from_info (PyGIArgCache  *arg_cache,
                                     GITypeInfo    *type_info,
                                     GIArgInfo     *arg_info,
                                     GITransfer     transfer,
                                     PyGIDirection  direction)
{
    GITypeTag type_tag = g_type_info_get_tag (type_info);

    if (!pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction))
        return FALSE;

    switch (type_tag) {
       case GI_TYPE_TAG_VOID:
           if (direction & PYGI_DIRECTION_FROM_PYTHON)
               _arg_cache_from_py_void_setup (arg_cache);

           if (direction & PYGI_DIRECTION_TO_PYTHON)
               _arg_cache_to_py_void_setup (arg_cache);

           break;
       case GI_TYPE_TAG_BOOLEAN:
       case GI_TYPE_TAG_INT8:
       case GI_TYPE_TAG_UINT8:
       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_UNICHAR:
       case GI_TYPE_TAG_GTYPE:
           if (direction & PYGI_DIRECTION_FROM_PYTHON)
               _arg_cache_from_py_basic_type_setup (arg_cache);

           if (direction & PYGI_DIRECTION_TO_PYTHON)
               _arg_cache_to_py_basic_type_setup (arg_cache);

           break;
       case GI_TYPE_TAG_UTF8:
       case GI_TYPE_TAG_FILENAME:
           if (direction & PYGI_DIRECTION_FROM_PYTHON)
               _arg_cache_from_py_utf8_setup (arg_cache, transfer);

           if (direction & PYGI_DIRECTION_TO_PYTHON)
               _arg_cache_to_py_utf8_setup (arg_cache, transfer);

           break;
       default:
           g_assert_not_reached ();
    }

    return TRUE;
}
Beispiel #5
0
static gboolean
source_func_p(GIArgInfo *info)
{
    GITypeInfo type_info;
    GIBaseInfo *interface_info;
    GICallableInfo *callback_info;
    GITypeInfo return_type_info;
    GIArgInfo first_arg_info;
    GITypeInfo first_arg_type_info;

    g_arg_info_load_type(info, &type_info);
    if (g_type_info_get_tag(&type_info) != GI_TYPE_TAG_INTERFACE) {
        return FALSE;
    }

    interface_info = g_type_info_get_interface(&type_info);
    if (g_base_info_get_type(interface_info) != GI_INFO_TYPE_CALLBACK) {
        g_base_info_unref(interface_info);
        return FALSE;
    }

    callback_info = (GICallableInfo *)interface_info;
    g_callable_info_load_return_type(callback_info, &return_type_info);
    if (g_type_info_get_tag(&return_type_info) != GI_TYPE_TAG_BOOLEAN) {
        g_base_info_unref(interface_info);
        return FALSE;
    }

    if (g_callable_info_get_n_args(interface_info) != 1) {
        g_base_info_unref(interface_info);
        return FALSE;
    }

    g_callable_info_load_arg(interface_info, 0, &first_arg_info);
    g_arg_info_load_type(&first_arg_info, &first_arg_type_info);
    if (g_type_info_get_tag(&first_arg_type_info) != GI_TYPE_TAG_VOID) {
        g_base_info_unref(interface_info);
        return FALSE;
    }

    g_base_info_unref(interface_info);
    return TRUE;
}
Beispiel #6
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;
    }
}
static void
prepare_invocation_info (GPerlI11nInvocationInfo *iinfo,
                         GICallableInfo *info)
{
	gint orig_n_args;
	guint i;

	dwarn ("invoke: %s\n"
	       "  n_args: %d\n",
	       g_base_info_get_name (info),
	       g_callable_info_get_n_args (info));

	iinfo->interface = info;

	iinfo->is_function = GI_IS_FUNCTION_INFO (info);
	iinfo->is_vfunc = GI_IS_VFUNC_INFO (info);
	iinfo->is_callback = (g_base_info_get_type (info) == GI_INFO_TYPE_CALLBACK);
	iinfo->is_signal = GI_IS_SIGNAL_INFO (info);
	dwarn ("  is_function = %d, is_vfunc = %d, is_callback = %d\n",
	       iinfo->is_function, iinfo->is_vfunc, iinfo->is_callback);

	orig_n_args = g_callable_info_get_n_args (info);
	g_assert (orig_n_args >= 0);
	iinfo->n_args = (guint) orig_n_args;

	if (iinfo->n_args) {
		iinfo->arg_infos = gperl_alloc_temp (sizeof (GITypeInfo*) * iinfo->n_args);
		iinfo->arg_types = gperl_alloc_temp (sizeof (GITypeInfo*) * iinfo->n_args);
		iinfo->aux_args = gperl_alloc_temp (sizeof (GIArgument) * iinfo->n_args);
	} else {
		iinfo->arg_infos = NULL;
		iinfo->arg_types = NULL;
		iinfo->aux_args = NULL;
	}

	for (i = 0 ; i < iinfo->n_args ; i++) {
		iinfo->arg_infos[i] = g_callable_info_get_arg (info, (gint) i);
		iinfo->arg_types[i] = g_arg_info_get_type (iinfo->arg_infos[i]);
	}

	iinfo->return_type_info = g_callable_info_get_return_type (info);
	iinfo->has_return_value =
		GI_TYPE_TAG_VOID != g_type_info_get_tag (iinfo->return_type_info);
	iinfo->return_type_ffi = g_type_info_get_ffi_type (iinfo->return_type_info);
	iinfo->return_type_transfer = g_callable_info_get_caller_owns (info);

	iinfo->callback_infos = NULL;
	iinfo->array_infos = NULL;

	iinfo->free_after_call = NULL;
}
/**
 * g_type_info_get_ffi_type:
 * @info: A #GITypeInfo
 *
 * Returns: A #ffi_type corresponding to the platform default C ABI for @info.
 */
ffi_type *
g_type_info_get_ffi_type (GITypeInfo *info)
{
  gboolean is_enum = FALSE;
  GIBaseInfo *iinfo;

  if (g_type_info_get_tag (info) == GI_TYPE_TAG_INTERFACE)
    {
      iinfo = g_type_info_get_interface (info);
      switch (g_base_info_get_type (iinfo))
        {
        case GI_INFO_TYPE_ENUM:
        case GI_INFO_TYPE_FLAGS:
          is_enum = TRUE;
          break;
        default:
          break;
        }
      g_base_info_unref (iinfo);
    }

  return gi_type_tag_get_ffi_type_internal (g_type_info_get_tag (info), g_type_info_is_pointer (info), is_enum);
}
static void
initialize_receiver(VALUE receiver, GITypeInfo *info, GIArgument *value)
{
    GIBaseInfo *interface_info;
    GIInfoType interface_type;

    if (g_type_info_get_tag(info) != GI_TYPE_TAG_INTERFACE) {
        rb_raise(rb_eRuntimeError, "TODO: returned value isn't interface");
    }

    interface_info = g_type_info_get_interface(info);
    interface_type = g_base_info_get_type(interface_info);
    g_base_info_unref(interface_info);
    switch (interface_type) {
    case GI_INFO_TYPE_OBJECT:
        G_INITIALIZE(receiver, value->v_pointer);
        break;
    case GI_INFO_TYPE_STRUCT:
        G_INITIALIZE(receiver, value->v_pointer);
        break;
    case GI_INFO_TYPE_INVALID:
    case GI_INFO_TYPE_FUNCTION:
    case GI_INFO_TYPE_CALLBACK:
    case GI_INFO_TYPE_BOXED:
    case GI_INFO_TYPE_ENUM:
    case GI_INFO_TYPE_FLAGS:
    case GI_INFO_TYPE_INTERFACE:
    case GI_INFO_TYPE_CONSTANT:
    case GI_INFO_TYPE_INVALID_0:
        rb_raise(rb_eRuntimeError,
                 "TODO: returned value isn't object, struct or union");
        break;
    case GI_INFO_TYPE_UNION:
        G_INITIALIZE(receiver, value->v_pointer);
        break;
    case GI_INFO_TYPE_VALUE:
    case GI_INFO_TYPE_SIGNAL:
    case GI_INFO_TYPE_VFUNC:
    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:
    default:
        rb_raise(rb_eRuntimeError,
                 "TODO: returned value isn't object, struct or union");
        break;
    }
}
Beispiel #10
0
/**
 * g_callable_info_get_ffi_return_type:
 * @callable_info: a callable info from a typelib
 *
 * Fetches the ffi_type for a corresponding return value of
 * a #GICallableInfo
 * Return value: the ffi_type for the return value
 */
static ffi_type *
g_callable_info_get_ffi_return_type (GICallableInfo *callable_info)
{
  GITypeInfo *return_type;
  GITypeTag type_tag;
  ffi_type *return_ffi_type;

  g_return_val_if_fail (callable_info != NULL, NULL);

  return_type = g_callable_info_get_return_type (callable_info);
  type_tag = g_type_info_get_tag (return_type);
  return_ffi_type = g_type_info_get_ffi_type (return_type);
  g_base_info_unref((GIBaseInfo*)return_type);

  return return_ffi_type;
}
Beispiel #11
0
Datei: marshal.c Projekt: ntd/lgi
/* Gets or sets the length of the array. */
static void
array_get_or_set_length (GITypeInfo *ti, gssize *get_length, gssize set_length,
			 GICallableInfo *ci, void **args)
{
  gint param = g_type_info_get_array_length (ti);
  if (param >= 0 && ci != NULL && param < g_callable_info_get_n_args (ci))
    {
      GIArgInfo ai;
      GITypeInfo eti;
      GIArgument *val;
      g_callable_info_load_arg (ci, param, &ai);
      g_arg_info_load_type (&ai, &eti);
      if (g_arg_info_get_direction (&ai) == GI_DIRECTION_IN)
	/* For input parameters, value is directly pointed do by args
	   table element. */
	val = (GIArgument *) args[param];
      else
	/* For output arguments, args table element points to pointer
	   to value. */
	val = *(GIArgument **) args[param];

      switch (g_type_info_get_tag (&eti))
	{
#define HANDLE_ELT(tag, field)			\
	  case GI_TYPE_TAG_ ## tag:		\
	    if (get_length != NULL)		\
	      *get_length = val->v_ ## field;	\
	    else				\
	      val->v_ ## field = set_length;	\
	  break

	  HANDLE_ELT(INT8, int8);
	  HANDLE_ELT(UINT8, uint8);
	  HANDLE_ELT(INT16, int16);
	  HANDLE_ELT(UINT16, uint16);
	  HANDLE_ELT(INT32, int32);
	  HANDLE_ELT(UINT32, uint32);
	  HANDLE_ELT(INT64, int64);
	  HANDLE_ELT(UINT64, uint64);
#undef HANDLE_ELT

	default:
	  g_assert_not_reached ();
	}
    }
}
Beispiel #12
0
Datei: marshal.c Projekt: ntd/lgi
/* Creates container (array, list, slist, hash) marshaller for
   specified container typeinfo.  Signature is:
   marshaller = marshal.container(typeinfo, transfer) */
static int
marshal_container (lua_State *L)
{
  GIBaseInfo **info = luaL_checkudata (L, 1, LGI_GI_INFO);
  GITypeTag tag = g_type_info_get_tag (*info);
  GITransfer transfer = luaL_checkoption (L, 2, transfers[0], transfers);
  if (tag == GI_TYPE_TAG_ARRAY || tag == GI_TYPE_TAG_GHASH ||
      tag == GI_TYPE_TAG_GSLIST || tag == GI_TYPE_TAG_GLIST)
    {
      lua_pushvalue (L, 1);
      lua_pushnumber (L, transfer);
      lua_pushcclosure (L, marshal_container_marshaller, 2);
    }
  else
    lua_pushnil (L);
  return 1;
}
Beispiel #13
0
Datei: marshal.c Projekt: ntd/lgi
/* Retrieves pointer to GIArgument in given array, given that array
   contains elements of type ti. */
static gssize
array_get_elt_size (GITypeInfo *ti)
{
  gssize size = sizeof (gpointer);
  if (!g_type_info_is_pointer (ti))
    {
      switch (g_type_info_get_tag (ti))
	{
#define HANDLE_ELT(nameupper, nametype)		\
	  case GI_TYPE_TAG_ ## nameupper:	\
	    return sizeof (nametype);

	  HANDLE_ELT(BOOLEAN, gboolean);
	  HANDLE_ELT(INT8, gint8);
	  HANDLE_ELT(UINT8, guint8);
	  HANDLE_ELT(INT16, gint16);
	  HANDLE_ELT(UINT16, guint16);
	  HANDLE_ELT(INT32, gint32);
	  HANDLE_ELT(UINT32, guint32);
	  HANDLE_ELT(UNICHAR, guint32);
	  HANDLE_ELT(INT64, gint64);
	  HANDLE_ELT(UINT64, guint64);
	  HANDLE_ELT(FLOAT, gfloat);
	  HANDLE_ELT(DOUBLE, gdouble);
	  HANDLE_ELT(GTYPE, GType);
#undef HANDLE_ELT

	case GI_TYPE_TAG_INTERFACE:
	  {
	    GIBaseInfo *info = g_type_info_get_interface (ti);
	    GIInfoType type = g_base_info_get_type (info);
	    if (type == GI_INFO_TYPE_STRUCT)
	      size = g_struct_info_get_size (info);
	    else if (type == GI_INFO_TYPE_UNION)
	      size = g_union_info_get_size (info);
	    g_base_info_unref (info);
	    break;
	  }

	default:
	  break;
	}
    }

  return size;
}
static void
handle_method_impl (ffi_cif  *cif,
                    gpointer  result,
                    gpointer *args,
                    gpointer  data)
{
  MethodImpl *impl = (MethodImpl *) data;
  GIArgInfo arg_info;
  GITypeInfo type_info;
  GITypeInfo return_type_info;
  gint n_args, i;
  PeasExtensionWrapper *instance;
  GIArgument *arguments;
  GIArgument return_value;
  gboolean success;

  instance = *((PeasExtensionWrapper **) args[0]);
  g_assert (PEAS_IS_EXTENSION_WRAPPER (instance));

  n_args = g_callable_info_get_n_args (impl->invoker_info);
  g_return_if_fail (n_args >= 0);
  arguments = g_newa (GIArgument, n_args);

  for (i = 0; i < n_args; i++)
    {
      g_callable_info_load_arg (impl->invoker_info, i, &arg_info);
      g_arg_info_load_type (&arg_info, &type_info);

      if (g_arg_info_get_direction (&arg_info) == GI_DIRECTION_IN)
        peas_gi_pointer_to_argument (&type_info, args[i + 1], &arguments[i]);
      else
        arguments[i].v_pointer = *((gpointer **) args[i + 1]);
    }

  success = peas_extension_wrapper_callv (instance, impl->interface_type,
                                          impl->invoker_info, impl->method_name,
                                          arguments, &return_value);

  if (!success)
    memset (&return_value, 0, sizeof (GIArgument));

  g_callable_info_load_return_type (impl->invoker_info, &return_type_info);
  if (g_type_info_get_tag (&return_type_info) != GI_TYPE_TAG_VOID)
    peas_gi_argument_to_pointer (&return_type_info, &return_value, result);
}
Beispiel #15
0
Datei: marshal.c Projekt: ntd/lgi
/* Calculates size and alignment of specified type.
   size, align = marshal.typeinfo(tiinfo) */
static int
marshal_typeinfo (lua_State *L)
{
  GIBaseInfo **info = luaL_checkudata (L, 1, LGI_GI_INFO);
  switch (g_type_info_get_tag (*info))
    {
#define HANDLE_INT(upper, type)						\
      case GI_TYPE_TAG_ ## upper:					\
	{								\
	  struct Test { char offender; type examined; };		\
	  lua_pushnumber (L, sizeof (type));				\
	  lua_pushnumber (L, G_STRUCT_OFFSET (struct Test, examined));	\
	}								\
	break

      HANDLE_INT (VOID, gpointer);
      HANDLE_INT (BOOLEAN, gboolean);
      HANDLE_INT (INT8, gint8);
      HANDLE_INT (UINT8, guint8);
      HANDLE_INT (INT16, gint16);
      HANDLE_INT (UINT16, guint16);
      HANDLE_INT (INT32, gint32);
      HANDLE_INT (UINT32, guint32);
      HANDLE_INT (INT64, gint64);
      HANDLE_INT (UINT64, guint64);
      HANDLE_INT (FLOAT, gfloat);
      HANDLE_INT (DOUBLE, gdouble);
      HANDLE_INT (GTYPE, GType);
      HANDLE_INT (UTF8, const gchar *);
      HANDLE_INT (FILENAME, const gchar *);
      HANDLE_INT (UNICHAR, gunichar);

#undef HANDLE_INT

    default:
      return luaL_argerror (L, 1, "bad typeinfo");
    }

  return 2;
}
Beispiel #16
0
void
rb_gi_in_argument_free(GIArgument *argument, GITypeInfo *type_info)
{
    GITypeTag type_tag;

    type_tag = g_type_info_get_tag(type_info);
    switch (type_tag) {
      case GI_TYPE_TAG_VOID:
      case GI_TYPE_TAG_BOOLEAN:
      case GI_TYPE_TAG_INT8:
      case GI_TYPE_TAG_UINT8:
      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:
      case GI_TYPE_TAG_UTF8:
      case GI_TYPE_TAG_FILENAME:
        break;
      case GI_TYPE_TAG_ARRAY:
        rb_gi_in_argument_free_array(argument, type_info);
        break;
      case GI_TYPE_TAG_INTERFACE:
        rb_gi_in_argument_free_interface(argument, type_info);
        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:
        break;
      default:
        g_assert_not_reached();
        break;
    }
}
Beispiel #17
0
static void
fill_metadata_array_from_callable_info(GPtrArray *args_metadata,
                                       GICallableInfo *info)
{
    GITypeInfo return_type_info;
    RBGIArgMetadata *array_length_metadata;
    gint array_length_index = -1;

    g_callable_info_load_return_type(info, &return_type_info);
    if (g_type_info_get_tag(&return_type_info) != GI_TYPE_TAG_ARRAY) {
        return;
    }

    array_length_index = g_type_info_get_array_length(&return_type_info);
    if (array_length_index == -1) {
        return;
    }

    array_length_metadata = g_ptr_array_index(args_metadata, array_length_index);
    array_length_metadata->array_length_p = TRUE;
    array_length_metadata->rb_arg_index = -1;
}
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 #19
0
static void
fill_metadata_array(GPtrArray *args_metadata)
{
    guint i;

    for (i = 0; i < args_metadata->len; i++) {
        RBGIArgMetadata *metadata;
        RBGIArgMetadata *array_length_metadata;
        GIArgInfo *arg_info;
        GITypeInfo type_info;
        gint array_length_index = -1;

        metadata = g_ptr_array_index(args_metadata, i);
        arg_info = &(metadata->arg_info);

        g_arg_info_load_type(arg_info, &type_info);
        if (g_type_info_get_tag(&type_info) != GI_TYPE_TAG_ARRAY) {
            continue;
        }
        metadata->array_p = TRUE;

        array_length_index = g_type_info_get_array_length(&type_info);
        if (array_length_index == -1) {
            continue;
        }

        array_length_metadata = g_ptr_array_index(args_metadata,
                                                  array_length_index);
        array_length_metadata->array_length_p = TRUE;
        array_length_metadata->rb_arg_index = -1;
        array_length_metadata->array_in_arg_index =
            metadata->in_arg_index;
        metadata->array_length_in_arg_index =
            array_length_metadata->in_arg_index;
        metadata->array_length_arg_index = array_length_index;
    }
}
Beispiel #20
0
/*
  We need to cast from different type for return value. (We don't
  need it for out arguments.) Because of libffi specification:

  https://github.com/libffi/libffi/blob/master/doc/libffi.texi#L190

  @var{rvalue} is a pointer to a chunk of memory that will hold the
  result of the function call.  This must be large enough to hold the
  result, no smaller than the system register size (generally 32 or 64
  bits), and must be suitably aligned; it is the caller's responsibility
  to ensure this.  If @var{cif} declares that the function returns
  @code{void} (using @code{ffi_type_void}), then @var{rvalue} is
  ignored.

  https://github.com/libffi/libffi/blob/master/doc/libffi.texi#L198

  In most situations, @samp{libffi} will handle promotion according to
  the ABI.  However, for historical reasons, there is a special case
  with return values that must be handled by your code.  In particular,
  for integral (not @code{struct}) types that are narrower than the
  system register size, the return value will be widened by
  @samp{libffi}.  @samp{libffi} provides a type, @code{ffi_arg}, that
  can be used as the return type.  For example, if the CIF was defined
  with a return type of @code{char}, @samp{libffi} will try to store a
  full @code{ffi_arg} into the return value.

  See also:
    * https://github.com/ruby-gnome2/ruby-gnome2/issues/758#issuecomment-243149237
    * https://github.com/libffi/libffi/pull/216

  This ffi_return_value case implementation is based on
  gi_type_info_extract_ffi_return_value().
*/
static void
out_argument_to_raw_data(GICallableInfo *callable_info,
                         VALUE rb_result,
                         gpointer result,
                         GITypeInfo *type_info,
                         GITransfer transfer,
                         gboolean is_return_value)
{
    GIArgument argument;
    GITypeTag type_tag;
    GIFFIReturnValue *ffi_return_value = result;

    rb_gi_value_argument_from_ruby(&argument,
                                   type_info,
                                   rb_result,
                                   rb_result);
    type_tag = g_type_info_get_tag(type_info);
    switch (type_tag) {
      case GI_TYPE_TAG_VOID:
        g_assert_not_reached();
        break;
      case GI_TYPE_TAG_BOOLEAN:
        if (is_return_value) {
            ffi_return_value->v_ulong = argument.v_boolean;
        } else {
            *((gboolean *)result) = argument.v_boolean;
        }
        break;
      case GI_TYPE_TAG_INT8:
        if (is_return_value) {
            ffi_return_value->v_long = argument.v_int8;
        } else {
            *((gint8 *)result) = argument.v_int8;
        }
        break;
      case GI_TYPE_TAG_UINT8:
        if (is_return_value) {
            ffi_return_value->v_ulong = argument.v_uint8;
        } else {
            *((guint8 *)result) = argument.v_uint8;
        }
        break;
      case GI_TYPE_TAG_INT16:
        if (is_return_value) {
            ffi_return_value->v_long = argument.v_int16;
        } else {
            *((gint16 *)result) = argument.v_int16;
        }
        break;
      case GI_TYPE_TAG_UINT16:
        if (is_return_value) {
            ffi_return_value->v_ulong = argument.v_uint16;
        } else {
            *((guint16 *)result) = argument.v_uint16;
        }
        break;
      case GI_TYPE_TAG_INT32:
        if (is_return_value) {
            ffi_return_value->v_long = argument.v_int32;
        } else {
            *((gint32 *)result) = argument.v_int32;
        }
        break;
      case GI_TYPE_TAG_UINT32:
        if (is_return_value) {
            ffi_return_value->v_ulong = argument.v_uint32;
        } else {
            *((guint32 *)result) = argument.v_uint32;
        }
        break;
      case GI_TYPE_TAG_INT64:
        *((gint64 *)result) = argument.v_int64;
        break;
      case GI_TYPE_TAG_UINT64:
        *((guint64 *)result) = argument.v_uint64;
        break;
      case GI_TYPE_TAG_FLOAT:
        *((gfloat *)result) = argument.v_float;
        break;
      case GI_TYPE_TAG_DOUBLE:
        *((gdouble *)result) = argument.v_double;
        break;
      case GI_TYPE_TAG_GTYPE:
        if (is_return_value) {
            ffi_return_value->v_ulong = argument.v_size;
        } else {
            *((gsize *)result) = argument.v_size;
        }
        break;
      case GI_TYPE_TAG_UTF8:
      case GI_TYPE_TAG_FILENAME:
        if (is_return_value) {
            ffi_return_value->v_ulong = (gulong)(argument.v_string);
        } else {
            *((gchar **)result) = argument.v_string;
        }
        break;
      case GI_TYPE_TAG_ARRAY:
        if (is_return_value) {
            ffi_return_value->v_ulong = (gulong)(argument.v_pointer);
        } else {
            *((gpointer *)result) = argument.v_pointer;
        }
        break;
      case GI_TYPE_TAG_INTERFACE:
        out_argument_to_raw_data_interface(callable_info,
                                           &argument,
                                           result,
                                           type_info,
                                           transfer,
                                           is_return_value);
        break;
      case GI_TYPE_TAG_GLIST:
      case GI_TYPE_TAG_GSLIST:
      case GI_TYPE_TAG_GHASH:
        if (is_return_value) {
            ffi_return_value->v_ulong = (gulong)(argument.v_pointer);
        } else {
            *((gpointer *)result) = argument.v_pointer;
        }
        break;
      case GI_TYPE_TAG_ERROR:
        if (is_return_value) {
            ffi_return_value->v_ulong = (gulong)(argument.v_pointer);
        } else {
            *((GError **)result) = argument.v_pointer;
        }
        break;
      case GI_TYPE_TAG_UNICHAR:
        if (is_return_value) {
            ffi_return_value->v_ulong = argument.v_uint32;
        } else {
            *((gunichar *)result) = argument.v_uint32;
        }
        break;
      default:
        g_assert_not_reached();
        break;
    }
}
Beispiel #21
0
static void
argument_from_raw_data(GICallableInfo *callable_info,
                       void **raw_args,
                       GArray *in_args,
                       GArray *out_args,
                       GPtrArray *args_metadata,
                       guint i)
{
    RBGIArgMetadata *metadata;
    GIArgument *argument;
    GITypeInfo *type_info;
    GITypeTag type_tag;

    metadata = g_ptr_array_index(args_metadata, i);

    if (metadata->direction == GI_DIRECTION_INOUT) {
        argument = &g_array_index(in_args, GIArgument, metadata->in_arg_index);
        argument->v_pointer = *((gpointer *)(raw_args[i]));
        return;
    } else if (metadata->direction == GI_DIRECTION_OUT) {
        argument = &g_array_index(out_args, GIArgument, metadata->out_arg_index);
        argument->v_pointer = *((gpointer *)(raw_args[i]));
        return;
    }

    argument = &g_array_index(in_args, GIArgument, metadata->in_arg_index);
    type_info = g_arg_info_get_type(&(metadata->arg_info));
    type_tag = g_type_info_get_tag(type_info);

    switch (type_tag) {
      case GI_TYPE_TAG_VOID:
        argument->v_pointer = *((gpointer *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_BOOLEAN:
        argument->v_boolean = *((gboolean *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_INT8:
        argument->v_int8 = *((gint8 *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_UINT8:
        argument->v_uint8 = *((guint8 *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_INT16:
        argument->v_int16 = *((gint16 *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_UINT16:
        argument->v_uint16 = *((guint16 *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_INT32:
        argument->v_int32 = *((gint32 *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_UINT32:
        argument->v_uint32 = *((guint32 *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_INT64:
        argument->v_int64 = *((gint64 *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_UINT64:
        argument->v_uint64 = *((guint64 *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_FLOAT:
        argument->v_float = *((gfloat *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_DOUBLE:
        argument->v_double = *((gdouble *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_GTYPE:
        argument->v_size = *((gsize *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_UTF8:
      case GI_TYPE_TAG_FILENAME:
        argument->v_string = *((gchar **)(raw_args[i]));
        break;
      case GI_TYPE_TAG_ARRAY:
        argument->v_pointer = *((gpointer *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_INTERFACE:
        argument_from_raw_data_interface(callable_info,
                                         raw_args[i],
                                         argument,
                                         type_info);
        break;
      case GI_TYPE_TAG_GLIST:
      case GI_TYPE_TAG_GSLIST:
      case GI_TYPE_TAG_GHASH:
        argument->v_pointer = *((gpointer *)(raw_args[i]));
        break;
      case GI_TYPE_TAG_ERROR:
        argument->v_pointer = *((GError **)(raw_args[i]));
        break;
      case GI_TYPE_TAG_UNICHAR:
        argument->v_uint32 = *((gunichar *)(raw_args[i]));
        break;
      default:
        g_assert_not_reached();
        break;
    }

    g_base_info_unref(type_info);
}
Beispiel #22
0
gboolean
pygi_g_struct_info_is_simple (GIStructInfo *struct_info)
{
    gboolean is_simple;
    gsize n_field_infos;
    gsize i;

    is_simple = TRUE;

    n_field_infos = g_struct_info_get_n_fields (struct_info);

    for (i = 0; i < n_field_infos && is_simple; i++) {
        GIFieldInfo *field_info;
        GITypeInfo *field_type_info;
		GITypeTag field_type_tag;
        field_info = g_struct_info_get_field (struct_info, i);
        field_type_info = g_field_info_get_type (field_info);

        

        field_type_tag = g_type_info_get_tag (field_type_info);

        switch (field_type_tag) {
            case GI_TYPE_TAG_BOOLEAN:
            case GI_TYPE_TAG_INT8:
            case GI_TYPE_TAG_UINT8:
            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_UNICHAR:
                if (g_type_info_is_pointer (field_type_info)) {
                    is_simple = FALSE;
                }
                break;
            case GI_TYPE_TAG_VOID:
            case GI_TYPE_TAG_GTYPE:
            case GI_TYPE_TAG_ERROR:
            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:
                is_simple = FALSE;
                break;
            case GI_TYPE_TAG_INTERFACE:
            {
                GIBaseInfo *info;
                GIInfoType info_type;

                info = g_type_info_get_interface (field_type_info);
                info_type = g_base_info_get_type (info);

                switch (info_type) {
                    case GI_INFO_TYPE_STRUCT:
                        if (g_type_info_is_pointer (field_type_info)) {
                            is_simple = FALSE;
                        } else {
                            is_simple = pygi_g_struct_info_is_simple ( (GIStructInfo *) info);
                        }
                        break;
                    case GI_INFO_TYPE_UNION:
                        /* TODO */
                        is_simple = FALSE;
                        break;
                    case GI_INFO_TYPE_ENUM:
                    case GI_INFO_TYPE_FLAGS:
                        if (g_type_info_is_pointer (field_type_info)) {
                            is_simple = FALSE;
                        }
                        break;
                    case GI_INFO_TYPE_BOXED:
                    case GI_INFO_TYPE_OBJECT:
                    case GI_INFO_TYPE_CALLBACK:
                    case GI_INFO_TYPE_INTERFACE:
                        is_simple = FALSE;
                        break;
                    case GI_INFO_TYPE_VFUNC:
                    case GI_INFO_TYPE_INVALID:
                    case GI_INFO_TYPE_FUNCTION:
                    case GI_INFO_TYPE_CONSTANT:
                    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:
                    default:
                        g_assert_not_reached();
                        break;
                }

                g_base_info_unref (info);
                break;
            }
        }

        g_base_info_unref ( (GIBaseInfo *) field_type_info);
        g_base_info_unref ( (GIBaseInfo *) field_info);
    }

    return is_simple;
}
Beispiel #23
0
static void
out_arguments_to_raw_data(GICallableInfo *callable_info,
                          VALUE rb_results,
                          void *result,
                          GArray *out_args,
                          GPtrArray *args_metadata)
{
    int i_rb_result = 0;
    guint i;
    GITypeInfo *return_type_info;
    GITypeTag return_type_tag;

    return_type_info = g_callable_info_get_return_type(callable_info);
    return_type_tag = g_type_info_get_tag(return_type_info);
    if (return_type_tag != GI_TYPE_TAG_VOID) {
        GITransfer transfer;
        transfer = g_callable_info_get_caller_owns(callable_info);
        if (out_args->len == 0) {
            VALUE rb_return_value = rb_results;
            out_argument_to_raw_data(callable_info,
                                     rb_return_value,
                                     result,
                                     return_type_info,
                                     transfer,
                                     TRUE);
        } else {
            out_argument_to_raw_data(callable_info,
                                     RARRAY_AREF(rb_results, i_rb_result),
                                     result,
                                     return_type_info,
                                     transfer,
                                     TRUE);
            i_rb_result++;
        }
    }
    g_base_info_unref(return_type_info);

    for (i = 0; i < args_metadata->len; i++) {
        RBGIArgMetadata *metadata;
        GIArgument *argument;
        GITypeInfo *type_info;
        GITransfer transfer;

        metadata = g_ptr_array_index(args_metadata, i);

        /* TODO: support GI_DIRECTION_INOUT */
        if (metadata->direction != GI_DIRECTION_OUT) {
            continue;
        }

        argument = &g_array_index(out_args, GIArgument, metadata->out_arg_index);
        type_info = g_arg_info_get_type(&(metadata->arg_info));
        transfer = g_arg_info_get_ownership_transfer(&(metadata->arg_info));
        out_argument_to_raw_data(callable_info,
                                 RARRAY_AREF(rb_results, i_rb_result),
                                 argument->v_pointer,
                                 type_info,
                                 transfer,
                                 FALSE);
        i_rb_result++;
        g_base_info_unref(type_info);
    }
}
Beispiel #24
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");
}
/* transfer and may_be_null can be gotten from arg_info, but sv_to_arg is also
 * called from places which don't have access to a GIArgInfo. */
static void
sv_to_arg (SV * sv,
           GIArgument * arg,
           GIArgInfo * arg_info,
           GITypeInfo * type_info,
           GITransfer transfer,
           gboolean may_be_null,
           GPerlI11nInvocationInfo * invocation_info)
{
	GITypeTag tag = g_type_info_get_tag (type_info);

	if (!gperl_sv_is_defined (sv))
		/* Interfaces and void types need to be able to handle undef
		 * separately. */
		if (!may_be_null && tag != GI_TYPE_TAG_INTERFACE
		                 && tag != GI_TYPE_TAG_VOID) {
			if (arg_info) {
				ccroak ("undefined value for mandatory argument '%s' encountered",
				        g_base_info_get_name ((GIBaseInfo *) arg_info));
			} else {
				ccroak ("undefined value encountered");
			}
		}

	switch (tag) {
	    case GI_TYPE_TAG_VOID:
		/* returns NULL if no match is found */
		arg->v_pointer = sv_to_callback_data (sv, invocation_info);
		break;

	    case GI_TYPE_TAG_BOOLEAN:
		arg->v_boolean = SvTRUE (sv);
		break;

	    case GI_TYPE_TAG_INT8:
		arg->v_int8 = (gint8) SvIV (sv);
		break;

	    case GI_TYPE_TAG_UINT8:
		arg->v_uint8 = (guint8) SvUV (sv);
		break;

	    case GI_TYPE_TAG_INT16:
		arg->v_int16 = (gint16) SvIV (sv);
		break;

	    case GI_TYPE_TAG_UINT16:
		arg->v_uint16 = (guint16) SvUV (sv);
		break;

	    case GI_TYPE_TAG_INT32:
		arg->v_int32 = (gint32) SvIV (sv);
		break;

	    case GI_TYPE_TAG_UINT32:
		arg->v_uint32 = (guint32) SvUV (sv);
		break;

	    case GI_TYPE_TAG_INT64:
		arg->v_int64 = SvGInt64 (sv);
		break;

	    case GI_TYPE_TAG_UINT64:
		arg->v_uint64 = SvGUInt64 (sv);
		break;

	    case GI_TYPE_TAG_FLOAT:
		arg->v_float = (gfloat) SvNV (sv);
		break;

	    case GI_TYPE_TAG_DOUBLE:
		arg->v_double = SvNV (sv);
		break;

	    case GI_TYPE_TAG_UNICHAR:
		arg->v_uint32 = g_utf8_get_char (SvGChar (sv));
		break;

	    case GI_TYPE_TAG_GTYPE:
		/* GType == gsize */
		arg->v_size = gperl_type_from_package (SvPV_nolen (sv));
		if (!arg->v_size)
			arg->v_size = g_type_from_name (SvPV_nolen (sv));
		break;

	    case GI_TYPE_TAG_ARRAY:
                arg->v_pointer = sv_to_array (transfer, type_info, sv, invocation_info);
		break;

	    case GI_TYPE_TAG_INTERFACE:
		dwarn ("    type %p -> interface\n", type_info);
		sv_to_interface (arg_info, type_info, transfer, may_be_null,
		                 sv, arg, invocation_info);
		break;

	    case GI_TYPE_TAG_GLIST:
	    case GI_TYPE_TAG_GSLIST:
		arg->v_pointer = sv_to_glist (transfer, type_info, sv);
		break;

	    case GI_TYPE_TAG_GHASH:
                arg->v_pointer = sv_to_ghash (transfer, type_info, sv);
		break;

	    case GI_TYPE_TAG_ERROR:
		ccroak ("FIXME - A GError as an in/inout arg?  Should never happen!");
		break;

	    case GI_TYPE_TAG_UTF8:
		arg->v_string = gperl_sv_is_defined (sv) ? SvGChar (sv) : NULL;
		if (transfer >= GI_TRANSFER_CONTAINER)
			arg->v_string = g_strdup (arg->v_string);
		break;

	    case GI_TYPE_TAG_FILENAME:
		/* FIXME: Should we use SvPVbyte_nolen here? */
		arg->v_string = gperl_sv_is_defined (sv) ? SvPV_nolen (sv) : NULL;
		if (transfer >= GI_TRANSFER_CONTAINER)
			arg->v_string = g_strdup (arg->v_string);
		break;

	    default:
		ccroak ("Unhandled info tag %d in sv_to_arg", tag);
	}
}
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;
}
static void
create_native_closure (GType            interface_type,
                       GIInterfaceInfo *iface_info,
                       GIVFuncInfo     *vfunc_info,
                       MethodImpl      *impl)
{
  GIFunctionInfo *invoker_info;
  GIStructInfo *struct_info;
  GIFieldInfo *field_info;
  GITypeInfo *type_info;
  GICallbackInfo *callback_info;
  guint n_fields, i;
  gboolean found_field_info;

  invoker_info = g_vfunc_info_get_invoker (vfunc_info);
  if (invoker_info == NULL)
    {
      g_debug ("No invoker for VFunc '%s.%s'",
               g_base_info_get_name (iface_info),
               g_base_info_get_name (vfunc_info));
      return;
    }

  struct_info = g_interface_info_get_iface_struct (iface_info);
  n_fields = g_struct_info_get_n_fields (struct_info);

  found_field_info = FALSE;
  for (i = 0; i < n_fields; i++)
    {
      field_info = g_struct_info_get_field (struct_info, i);

      if (strcmp (g_base_info_get_name (field_info),
                  g_base_info_get_name (vfunc_info)) == 0)
        {
          found_field_info = TRUE;
          break;
        }

      g_base_info_unref (field_info);
    }

  if (!found_field_info)
    {
      g_debug ("No struct field for VFunc '%s.%s'",
               g_base_info_get_name (iface_info),
               g_base_info_get_name (vfunc_info));
      g_base_info_unref (struct_info);
      g_base_info_unref (invoker_info);
      return;
    }

  type_info = g_field_info_get_type (field_info);
  g_assert (g_type_info_get_tag (type_info) == GI_TYPE_TAG_INTERFACE);

  callback_info = g_type_info_get_interface (type_info);
  g_assert (g_base_info_get_type (callback_info) == GI_INFO_TYPE_CALLBACK);

  impl->interface_type = interface_type;
  impl->invoker_info = invoker_info;
  impl->method_name = g_base_info_get_name (invoker_info);
  impl->closure = g_callable_info_prepare_closure (callback_info, &impl->cif,
                                                   handle_method_impl, impl);
  impl->struct_offset = g_field_info_get_offset (field_info);

  g_base_info_unref (callback_info);
  g_base_info_unref (type_info);
  g_base_info_unref (field_info);
  g_base_info_unref (struct_info);
}
Beispiel #28
0
void
gy_value_set_iarg(GValue* pval, GITypeInfo * info, int iarg)
{
  GY_DEBUG("in gy_value_set_iarg\n");
  GITypeTag type = g_type_info_get_tag(info);
  GIBaseInfo * itrf;
  switch (type) {
  case GI_TYPE_TAG_BOOLEAN:
    g_value_set_boolean(pval, ygets_c(iarg));
    break;
  case GI_TYPE_TAG_INT8:
    g_value_set_schar(pval, ygets_c(iarg));
    break;
  case GI_TYPE_TAG_UINT8:
    g_value_set_uchar(pval, ygets_c(iarg));
    break;
  case GI_TYPE_TAG_INT16:
  case GI_TYPE_TAG_INT32:
    g_value_set_int(pval, ygets_i(iarg));
    break;
  case GI_TYPE_TAG_UINT16:
  case GI_TYPE_TAG_UINT32:
    g_value_set_uint(pval, ygets_i(iarg));
    break;
  case GI_TYPE_TAG_INT64:
    g_value_set_int64(pval, ygets_l(iarg));
    break;
  case GI_TYPE_TAG_UINT64:
    g_value_set_uint64(pval, ygets_l(iarg));
    break;
  case GI_TYPE_TAG_FLOAT:
    g_value_set_float(pval, ygets_f(iarg));
    break;
  case GI_TYPE_TAG_DOUBLE:
    g_value_set_double(pval, ygets_d(iarg));
    break;
  case GI_TYPE_TAG_GTYPE:
    g_value_set_gtype(pval, ygets_l(iarg));
    break;
  case GI_TYPE_TAG_UTF8:
  case GI_TYPE_TAG_FILENAME:
    g_value_set_static_string (pval, ygets_q(iarg));
    GY_DEBUG("GValue is string: \"%s\"\n", ygets_q(iarg));
    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_ENUM:
      g_value_set_enum (pval, ygets_l(iarg));
      break;
    case GI_INFO_TYPE_OBJECT:
      g_value_set_object(pval, yget_gy_Object(iarg)->object);
      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_iarg2gvalue\n");
}
Beispiel #29
0
static gboolean
peas_extension_gjs_call (PeasExtensionWrapper *exten,
                         GType                 exten_type,
                         GICallableInfo       *func_info,
                         const gchar          *method_name,
                         GIArgument           *args,
                         GIArgument           *retval)
{
  PeasExtensionGjs *gexten = PEAS_EXTENSION_GJS (exten);
  gboolean success = FALSE;
  jsval js_method, js_retval;
  jsval *js_args;
  CachedArg *arg_cache;
  gint i, n_args, nth_out_arg;
  gint n_in_args = 0;
  gint n_out_args = 0;
  gint cached_args = 0;

  /* Fetch the JS method we want to call */
  if (!JS_GetProperty (gexten->js_context, gexten->js_object,
                       method_name, &js_method) ||
      JSVAL_IS_VOID (js_method))
    {
      g_warning ("Method '%s.%s' was not found",
                 g_type_name (exten_type), method_name);
      return FALSE;
    }

  if (JSVAL_IS_NULL (js_method) || !JSVAL_IS_OBJECT (js_method) ||
      !JS_ObjectIsFunction (gexten->js_context, JSVAL_TO_OBJECT (js_method)))
    {
      g_warning ("Method '%s.%s' in not a function",
                 g_type_name (exten_type), method_name);
      return FALSE;
    }

  n_args = g_callable_info_get_n_args (func_info);
  if (n_args < 0)
    {
      g_warn_if_fail (n_args >= 0);
      return FALSE;
    }

  js_args = g_newa (jsval, n_args);
  arg_cache = g_newa (CachedArg, n_args + 1);

  /* Return value is an out arg */
  g_callable_info_load_return_type (func_info, &arg_cache[0].type_info);
  if (g_type_info_get_tag (&arg_cache[0].type_info) != GI_TYPE_TAG_VOID)
    {
      ++n_out_args;
      arg_cache[cached_args++].ptr = &retval->v_pointer;
    }

  /* Handle the arguments */
  for (i = 0; i < n_args; ++i, ++cached_args)
    {
      GIDirection direction;

      g_callable_info_load_arg (func_info, i, &arg_cache[cached_args].arg_info);
      direction = g_arg_info_get_direction (&arg_cache[cached_args].arg_info);
      g_arg_info_load_type (&arg_cache[cached_args].arg_info,
                            &arg_cache[cached_args].type_info);

      if (direction == GI_DIRECTION_IN &&
          !gjs_value_from_g_argument (gexten->js_context, &js_args[n_in_args++],
                                      &arg_cache[cached_args].type_info,
                                      &args[i], TRUE))
        {
          g_warning ("Error failed to convert argument '%s'",
                     g_base_info_get_name (&arg_cache[cached_args].arg_info));
          return FALSE;
        }

      if (direction == GI_DIRECTION_INOUT)
        {
          GIArgument arg;

          peas_gi_pointer_to_argument (&arg_cache[cached_args].type_info,
                                       args[i].v_pointer, &arg);

          if (!gjs_value_from_g_argument (gexten->js_context, &js_args[n_in_args++],
                                          &arg_cache[cached_args].type_info, &arg, TRUE))
            {
              g_warning ("Error failed to convert argument '%s'",
                         g_base_info_get_name (&arg_cache[cached_args].arg_info));
              return FALSE;
            }
        }

      if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
        {
          ++n_out_args;
          arg_cache[cached_args].ptr = args[i].v_pointer;
        }
    }

  success = JS_CallFunctionValue (gexten->js_context, gexten->js_object,
                                  js_method, n_in_args, js_args, &js_retval);

  if (!success)
    {
      if (!gjs_log_exception (gexten->js_context, NULL))
        {
          g_warning ("Error while calling '%s.%s'",
                     g_type_name (exten_type), method_name);
        }

      return FALSE;
    }

  /* First we need to release in argument */
  for (i = 0; i < cached_args; ++i)
    {
      GIDirection direction;

      /* First cached argument may be the return value */
      if (i == 0 && cached_args > n_args)
        continue;

      direction = g_arg_info_get_direction (&arg_cache[i].arg_info);

      if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
        {
          GITransfer transfer;

          transfer = g_arg_info_get_ownership_transfer (&arg_cache[i].arg_info);

          if (!gjs_g_argument_release_in_arg (gexten->js_context, transfer,
                                              &arg_cache[i].type_info,
                                              &args[i]))
            {
              g_warning ("Error failed to release IN argument '%s'",
                         g_base_info_get_name (&arg_cache[i].arg_info));
            }
        }
    }

  /* Check that we have a valid return value */
  if (n_out_args > 1)
    {
      if (!JSVAL_IS_OBJECT (js_retval) ||
          !JS_IsArrayObject (gexten->js_context, JSVAL_TO_OBJECT (js_retval)))
        {
          g_warning ("Error return value is not an array");
          return FALSE;
        }
    }

  /* Set out arguments */
  for (i = 0, nth_out_arg = 0; i < cached_args && success; ++i)
    {
      gboolean is_return_value;

      is_return_value = i == 0 && cached_args > n_args;

      /* Return value does not have a GIArgInfo and is always out */
      if (!is_return_value)
        {
          GIDirection direction;

          direction = g_arg_info_get_direction (&arg_cache[i].arg_info);

          if (direction == GI_DIRECTION_IN)
            continue;
        }

      if (n_out_args == 1)
        {
          success = set_out_arg (gexten->js_context, func_info, is_return_value,
                                 &arg_cache[i].arg_info, &arg_cache[i].type_info,
                                 arg_cache[i].ptr, js_retval);
          break;
        }
      else if (n_out_args > 1)
        {
          jsval js_value;

          if (!JS_GetElement (gexten->js_context, JSVAL_TO_OBJECT (js_retval),
                              nth_out_arg++, &js_value) ||
              js_value == JSVAL_VOID)
            {
              g_warning ("Error failed to get out argument %i", nth_out_arg);
              return FALSE;
            }
          else
            {
              success = set_out_arg (gexten->js_context, func_info,
                                     is_return_value, &arg_cache[i].arg_info,
                                     &arg_cache[i].type_info, arg_cache[i].ptr,
                                     js_value);
            }
        }
    }

  return success;
}
Beispiel #30
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");
  }


}