Commit 0586a832 authored by John (J5) Palmieri's avatar John (J5) Palmieri
Browse files

support callbacks

parent 9be0f1f2
......@@ -2892,9 +2892,71 @@ _pygi_marshal_in_interface_callback (PyGIInvokeState *state,
PyObject *py_arg,
GIArgument *arg)
{
PyErr_Format(PyExc_NotImplementedError,
"Marshalling for this type is not implemented yet");
return FALSE;
GICallableInfo *callable_info;
GITypeInfo *type_info;
PyGICClosure *closure;
PyGIArgCache *user_data_cache = NULL;
PyGIArgCache *destroy_cache = NULL;
PyGICallbackCache *callback_cache;
PyObject *py_user_data = NULL;
callback_cache =(PyGICallbackCache *)arg_cache;
if (callback_cache->user_data_index > 0) {
user_data_cache = function_cache->args_cache[callback_cache->user_data_index];
if (user_data_cache->py_arg_index < state->n_py_in_args) {
py_user_data = PyTuple_GetItem(state->py_in_args, user_data_cache->py_arg_index);
if (!py_user_data)
return FALSE;
} else {
py_user_data = Py_None;
Py_INCREF(Py_None);
}
}
if (py_arg == Py_None && py_user_data != Py_None) {
Py_DECREF(py_user_data);
PyErr_Format(PyExc_TypeError,
"When passing None for a callback userdata must also be None");
return FALSE;
}
if (py_arg == Py_None) {
Py_XDECREF(py_user_data);
return TRUE;
}
if (!PyCallable_Check(py_arg)) {
Py_XDECREF(py_user_data);
PyErr_Format(PyExc_TypeError,
"Callback needs to be a function or method not %s",
py_arg->ob_type->tp_name);
return FALSE;
}
if (callback_cache->destroy_notify_index > 0)
destroy_cache = function_cache->args_cache[callback_cache->destroy_notify_index];
type_info = g_arg_info_get_type(arg_cache->arg_info);
callable_info = (GICallableInfo *)g_type_info_get_interface(type_info);
closure = _pygi_make_native_closure (callable_info, callback_cache->scope, py_arg, py_user_data);
g_base_info_unref((GIBaseInfo *)callable_info);
g_base_info_unref((GIBaseInfo *)type_info);
arg->v_pointer = closure->closure;
if (user_data_cache != NULL) {
state->in_args[user_data_cache->c_arg_index].v_pointer = closure;
}
if (destroy_cache) {
PyGICClosure *destroy_notify = _pygi_destroy_notify_create();
state->in_args[destroy_cache->c_arg_index].v_pointer = destroy_notify->closure;
}
return TRUE;
}
gboolean
......
......@@ -26,12 +26,13 @@
#include <girepository.h>
PyGIArgCache * _arg_cache_in_new_from_type_info (GITypeInfo *type_info,
PyGIFunctionCache *function_cache,
GITypeTag type_tag,
GITransfer transfer,
GIDirection direction,
gint c_arg_index,
gint py_arg_index);
GIArgInfo *arg_info,
PyGIFunctionCache *function_cache,
GITypeTag type_tag,
GITransfer transfer,
GIDirection direction,
gint c_arg_index,
gint py_arg_index);
/* cleanup */
void
_pygi_arg_cache_free(PyGIArgCache *cache)
......@@ -168,6 +169,7 @@ _sequence_cache_new_from_type_info(GITypeInfo *type_info)
/* FIXME: support out also */
sc->item_cache = _arg_cache_in_new_from_type_info(item_type_info,
NULL,
NULL,
item_type_tag,
GI_TRANSFER_EVERYTHING,
......@@ -202,6 +204,7 @@ _hash_cache_new_from_type_info(GITypeInfo *type_info)
value_type_tag = g_type_info_get_tag (value_type_info);
hc->key_cache = _arg_cache_in_new_from_type_info(key_type_info,
NULL,
NULL,
key_type_tag,
GI_TRANSFER_EVERYTHING,
......@@ -214,6 +217,7 @@ _hash_cache_new_from_type_info(GITypeInfo *type_info)
}
hc->value_cache = _arg_cache_in_new_from_type_info(value_type_info,
NULL,
NULL,
value_type_tag,
GI_TRANSFER_EVERYTHING,
......@@ -234,6 +238,19 @@ _hash_cache_new_from_type_info(GITypeInfo *type_info)
return hc;
}
static inline PyGICallbackCache *
_callback_cache_new_from_arg_info(GIArgInfo *arg_info)
{
PyGICallbackCache *cc;
cc = g_slice_new0(PyGICallbackCache);
cc->user_data_index = g_arg_info_get_closure(arg_info);
cc->destroy_notify_index = g_arg_info_get_destroy(arg_info);
cc->scope = g_arg_info_get_scope(arg_info);
return cc;
}
static inline PyGIArgCache *
_arg_cache_new(void)
{
......@@ -387,7 +404,7 @@ _arg_cache_new_for_in_array(PyGIFunctionCache *function_cache,
seq_cache->len_arg_index = g_type_info_get_array_length(type_info);
if (seq_cache->len_arg_index >= 0) {
PyGIArgCache *aux_cache = _arg_cache_new();
aux_cache->is_aux = TRUE;
aux_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
if (function_cache->args_cache[seq_cache->len_arg_index] != NULL) {
PyGIArgCache *invalid_cache = function_cache->args_cache[seq_cache->len_arg_index];
arg_cache->c_arg_index = invalid_cache->c_arg_index;
......@@ -438,7 +455,7 @@ _arg_cache_new_for_in_gerror(void)
{
PyGIArgCache *arg_cache = _arg_cache_new();
arg_cache->in_marshaller = _pygi_marshal_in_gerror;
arg_cache->is_aux = TRUE;
arg_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
return arg_cache;
}
......@@ -496,12 +513,23 @@ _arg_cache_new_for_in_interface_boxed(GIInterfaceInfo *iface_info,
}
static inline PyGIArgCache *
_arg_cache_new_for_in_interface_callback(void)
{
PyGIArgCache *arg_cache = NULL;
/*arg_cache->in_marshaller = _pygi_marshal_in_callback;*/
PyErr_Format(PyExc_NotImplementedError,
"Caching for this type is not fully implemented yet");
_arg_cache_new_for_in_interface_callback(PyGIFunctionCache *function_cache,
GIArgInfo *arg_info)
{
PyGICallbackCache *callback_cache = _callback_cache_new_from_arg_info(arg_info);
PyGIArgCache *arg_cache = (PyGIArgCache *)callback_cache;
if (callback_cache->user_data_index >= 0) {
PyGIArgCache *user_data_arg_cache = _arg_cache_new();
user_data_arg_cache->aux_type = PYGI_AUX_TYPE_HAS_PYARG;
function_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
}
if (callback_cache->destroy_notify_index) {
PyGIArgCache *destroy_arg_cache = _arg_cache_new();
destroy_arg_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
function_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
}
arg_cache->in_marshaller = _pygi_marshal_in_interface_callback;
return arg_cache;
}
......@@ -527,6 +555,7 @@ _arg_cache_new_for_in_interface_flags(void)
PyGIArgCache *
_arg_cache_in_new_from_interface_info (GIInterfaceInfo *iface_info,
GIArgInfo *arg_info,
PyGIFunctionCache *function_cache,
GIInfoType info_type,
GITransfer transfer,
......@@ -554,7 +583,8 @@ _arg_cache_in_new_from_interface_info (GIInterfaceInfo *iface_info,
transfer);
break;
case GI_INFO_TYPE_CALLBACK:
arg_cache = _arg_cache_new_for_in_interface_callback();
arg_cache = _arg_cache_new_for_in_interface_callback(function_cache,
arg_info);
break;
case GI_INFO_TYPE_ENUM:
arg_cache = _arg_cache_new_for_in_interface_enum();
......@@ -758,7 +788,7 @@ _arg_cache_new_for_out_gerror(void)
{
PyGIArgCache *arg_cache = _arg_cache_new();
arg_cache->out_marshaller = _pygi_marshal_out_gerror;
arg_cache->is_aux = TRUE;
arg_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
return arg_cache;
}
......@@ -871,6 +901,7 @@ _arg_cache_out_new_from_type_info (GITypeInfo *type_info,
PyGIArgCache *
_arg_cache_in_new_from_type_info (GITypeInfo *type_info,
GIArgInfo *arg_info,
PyGIFunctionCache *function_cache,
GITypeTag type_tag,
GITransfer transfer,
......@@ -939,6 +970,7 @@ _arg_cache_in_new_from_type_info (GITypeInfo *type_info,
GIInterfaceInfo *interface_info = g_type_info_get_interface(type_info);
GIInfoType info_type = g_base_info_get_type( (GIBaseInfo *) interface_info);
arg_cache = _arg_cache_in_new_from_interface_info(interface_info,
arg_info,
function_cache,
info_type,
transfer,
......@@ -1010,6 +1042,7 @@ _args_cache_generate(GIFunctionInfo *function_info,
instance_cache =
_arg_cache_in_new_from_interface_info(interface_info,
NULL,
function_cache,
info_type,
GI_TRANSFER_NOTHING,
......@@ -1026,6 +1059,7 @@ _args_cache_generate(GIFunctionInfo *function_info,
arg_index++;
function_cache->n_in_args++;
function_cache->n_py_args++;
}
......@@ -1043,7 +1077,12 @@ _args_cache_generate(GIFunctionInfo *function_info,
* and continue
*/
if (function_cache->args_cache[arg_index] != NULL) {
function_cache->args_cache[arg_index]->c_arg_index = function_cache->n_in_args;
arg_cache = function_cache->args_cache[arg_index];
if (arg_cache->aux_type == PYGI_AUX_TYPE_HAS_PYARG) {
arg_cache->py_arg_index = function_cache->n_py_args;
function_cache->n_py_args++;
}
arg_cache->c_arg_index = function_cache->n_in_args;
function_cache->n_in_args++;
continue;
}
......@@ -1058,11 +1097,13 @@ _args_cache_generate(GIFunctionInfo *function_info,
switch(direction) {
case GI_DIRECTION_IN:
py_arg_index = function_cache->n_in_args;
py_arg_index = function_cache->n_py_args;
function_cache->n_in_args++;
function_cache->n_py_args++;
arg_cache =
_arg_cache_in_new_from_type_info(type_info,
arg_info,
function_cache,
type_tag,
transfer,
......@@ -1079,7 +1120,7 @@ _args_cache_generate(GIFunctionInfo *function_info,
case GI_DIRECTION_OUT:
function_cache->n_out_args++;
arg_cache =
_arg_cache_out_new_from_type_info(return_info,
_arg_cache_out_new_from_type_info(type_info,
function_cache,
type_tag,
transfer,
......@@ -1101,6 +1142,7 @@ _args_cache_generate(GIFunctionInfo *function_info,
}
arg_cache->arg_info = arg_info;
function_cache->args_cache[arg_index] = arg_cache;
g_base_info_unref( (GIBaseInfo *) type_info);
continue;
......
......@@ -43,9 +43,18 @@ typedef PyObject *(*PyGIMarshalOutFunc) (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
GIArgument *arg);
typedef enum {
/* Not an AUX type */
PYGI_AUX_TYPE_NONE = 0,
/* AUX type handled by parent */
PYGI_AUX_TYPE_IGNORE = 1,
/* AUX type has an associated pyarg which is modified by parent */
PYGI_AUX_TYPE_HAS_PYARG = 2
} PyGIAuxType;
struct _PyGIArgCache
{
gboolean is_aux;
PyGIAuxType aux_type;
gboolean is_pointer;
gboolean is_caller_allocates;
gboolean allow_none;
......@@ -95,7 +104,6 @@ typedef struct _PyGIHashCache
typedef struct _PyGICallbackCache
{
PyGIArgCache arg_cache;
gint py_user_data_index;
gint user_data_index;
gint destroy_notify_index;
GIScopeType scope;
......@@ -114,6 +122,7 @@ struct _PyGIFunctionCache
guint n_in_args;
guint n_out_args;
guint n_args;
guint n_py_args;
};
void _pygi_arg_cache_clear (PyGIArgCache *cache);
......
......@@ -972,7 +972,7 @@ _invoke_marshal_in_args(PyGIInvokeState *state, PyGIFunctionCache *cache)
state->args[i] = &(state->in_args[in_count]);
in_count++;
if (arg_cache->is_aux)
if (arg_cache->aux_type > 0)
continue;
/* FIXME: get default or throw error if there aren't enough pyargs */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment