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;
}
Exemplo n.º 2
0
static gboolean
set_out_arg (JSContext      *js_context,
             GIFunctionInfo *func_info,
             gboolean        is_return_value,
             GIArgInfo      *arg_info,
             GITypeInfo     *type_info,
             gpointer        ptr,
             jsval           js_value)
{
  gboolean nullable;
  GITransfer transfer;
  GIArgument argument;
  GjsArgumentType arg_type;

  if (is_return_value)
    {
      arg_type = GJS_ARGUMENT_RETURN_VALUE;
      nullable = g_callable_info_may_return_null (func_info);
      transfer = g_callable_info_get_caller_owns (func_info);
    }
  else
    {
      arg_type = GJS_ARGUMENT_ARGUMENT;
      nullable = g_arg_info_may_be_null (arg_info);
      transfer = g_arg_info_get_ownership_transfer (arg_info);
    }

  if (!gjs_value_to_g_argument (js_context, js_value, type_info, NULL,
                                arg_type, transfer, nullable, &argument))
    {
      if (is_return_value)
        {
          g_warning ("Error failed to convert return value to GIArgument");
        }
      else
        {
          g_warning ("Error failed to convert OUT argument '%s' from "
                     "jsval to GIArgument", g_base_info_get_name (arg_info));
        }

      return FALSE;
    }

  peas_gi_argument_to_pointer (type_info, &argument, ptr);

  return TRUE;
}
Exemplo n.º 3
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);
    }
}
Exemplo n.º 4
0
void
_pygi_closure_handle (ffi_cif *cif,
                      void    *result,
                      void   **args,
                      void    *data)
{
    PyGILState_STATE state;
    PyGICClosure *closure = data;
    gint n_args, i;
    GIArgInfo  *arg_info;
    GIDirection arg_direction;
    GITypeInfo *arg_type;
    GITransfer arg_transfer;
    GITypeTag  arg_tag;
    GITypeTag  return_tag;
    GITransfer return_transfer;
    GITypeInfo *return_type;
    PyObject *retval;
    PyObject *py_args;
    PyObject *pyarg;
    gint n_in_args, n_out_args;


    /* Lock the GIL as we are coming into this code without the lock and we
      may be executing python code */
    state = PyGILState_Ensure();

    return_type = g_callable_info_get_return_type(closure->info);
    return_tag = g_type_info_get_tag(return_type);
    return_transfer = g_callable_info_get_caller_owns(closure->info);

    n_args = g_callable_info_get_n_args (closure->info);

    py_args = PyTuple_New(n_args);
    if (py_args == NULL) {
        PyErr_Clear();
        goto end;
    }

    n_in_args = 0;

    for (i = 0; i < n_args; i++) {
        arg_info = g_callable_info_get_arg (closure->info, i);
        arg_type = g_arg_info_get_type (arg_info);
        arg_transfer = g_arg_info_get_ownership_transfer(arg_info);
        arg_tag = g_type_info_get_tag(arg_type);
        arg_direction = g_arg_info_get_direction(arg_info);
        switch (arg_tag) {
        case GI_TYPE_TAG_VOID:
        {
            if (g_type_info_is_pointer(arg_type)) {
                if (PyTuple_SetItem(py_args, n_in_args, closure->user_data) != 0) {
                    PyErr_Clear();
                    goto end;
                }
                n_in_args++;
                continue;
            }
        }
        case GI_TYPE_TAG_ERROR:
        {
            continue;
        }
        default:
        {
            pyarg = _pygi_argument_to_object (args[i],
                                              arg_type,
                                              arg_transfer);

            if(PyTuple_SetItem(py_args, n_in_args, pyarg) != 0) {
                PyErr_Clear();
                goto end;
            }
            n_in_args++;
            g_base_info_unref((GIBaseInfo*)arg_info);
            g_base_info_unref((GIBaseInfo*)arg_type);
        }
        }

    }

    if(_PyTuple_Resize (&py_args, n_in_args) != 0) {
        PyErr_Clear();
        goto end;
    }

    retval = PyObject_CallObject((PyObject *)closure->function, py_args);

    Py_DECREF(py_args);

    if (retval == NULL) {
        goto end;
    }

    *(GArgument*)result = _pygi_argument_from_object(retval, return_type, return_transfer);

end:
    g_base_info_unref((GIBaseInfo*)return_type);

    PyGILState_Release(state);

    if (closure->user_data)
        Py_XDECREF(closure->user_data);

    /* Now that the closure has finished we can make a decision about how
       to free it.  Scope call gets free'd now, scope notified will be freed
       when the notify is called and we can free async anytime we want
       once we return from this function */
    switch (closure->scope) {
    case GI_SCOPE_TYPE_CALL:
        _pygi_invoke_closure_free(closure);
        break;
    case GI_SCOPE_TYPE_NOTIFIED:
        break;
    case GI_SCOPE_TYPE_ASYNC:
        /* Append this PyGICClosure to a list of closure that we will free
           after we're done with this function invokation */
        async_free_list = g_slist_prepend(async_free_list, closure);
        break;
    default:
        g_assert_not_reached();
    }
}