1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */
static gpointer
sv_to_callback (GIArgInfo * arg_info,
GITypeInfo * type_info,
SV * sv,
GPerlI11nInvocationInfo * invocation_info)
{
GPerlI11nPerlCallbackInfo *callback_info;
GIScopeType scope;
/* the destroy notify func is handled by handle_automatic_arg */
dwarn (" Perl callback at %d (%s)\n",
invocation_info->current_pos,
g_base_info_get_name (arg_info));
callback_info = create_perl_callback_closure (type_info, sv);
callback_info->data_pos = g_arg_info_get_closure (arg_info);
callback_info->destroy_pos = g_arg_info_get_destroy (arg_info);
callback_info->free_after_use = FALSE;
dwarn (" Perl callback data at %d, destroy at %d\n",
callback_info->data_pos, callback_info->destroy_pos);
scope = (!gperl_sv_is_defined (sv))
? GI_SCOPE_TYPE_CALL
: g_arg_info_get_scope (arg_info);
switch (scope) {
case GI_SCOPE_TYPE_CALL:
dwarn (" Perl callback has scope 'call'\n");
invocation_info->free_after_call
= g_slist_prepend (invocation_info->free_after_call,
callback_info);
break;
case GI_SCOPE_TYPE_NOTIFIED:
dwarn (" Perl callback has scope 'notified'\n");
/* This case is already taken care of by the notify
* stuff above */
break;
case GI_SCOPE_TYPE_ASYNC:
dwarn (" Perl callback has scope 'async'\n");
/* FIXME: callback_info->free_after_use = TRUE; */
break;
default:
ccroak ("unhandled scope type %d encountered",
g_arg_info_get_scope (arg_info));
}
invocation_info->callback_infos =
g_slist_prepend (invocation_info->callback_infos,
callback_info);
dwarn (" returning Perl closure %p from info %p\n",
callback_info->closure, callback_info);
return callback_info->closure;
}
static gpointer
sv_to_callback_data (SV * sv,
GPerlI11nInvocationInfo * invocation_info)
{
GSList *l;
if (!invocation_info)
return NULL;
for (l = invocation_info->callback_infos; l != NULL; l = l->next) {
GPerlI11nPerlCallbackInfo *callback_info = l->data;
if (callback_info->data_pos == invocation_info->current_pos) {
dwarn (" user data for Perl callback %p\n",
callback_info);
attach_perl_callback_data (callback_info, sv);
return callback_info;
}
}
if (invocation_info->is_callback) {
GPerlI11nCCallbackInfo *wrapper = INT2PTR (GPerlI11nCCallbackInfo*, SvIV (sv));
dwarn (" user data for C callback %p\n", wrapper);
return wrapper->data;
}
return NULL;
}
static SV *
callback_to_sv (GICallableInfo *interface, gpointer func, GPerlI11nInvocationInfo *invocation_info)
{
GIArgInfo *arg_info;
GPerlI11nCCallbackInfo *callback_info;
HV *stash;
SV *code_sv, *data_sv;
GSList *l;
for (l = invocation_info->callback_infos; l != NULL; l = l->next) {
GPerlI11nCCallbackInfo *callback_info = l->data;
if (invocation_info->current_pos == callback_info->destroy_pos) {
dwarn (" destroy notify for C callback %p\n",
callback_info);
callback_info->destroy = func;
/* release_c_callback is called from
* Glib::Object::Introspection::_FuncWrapper::DESTROY */
return NULL;
}
}
arg_info = g_callable_info_get_arg (invocation_info->interface,
invocation_info->current_pos);
dwarn (" C callback at %d (%s)\n",
invocation_info->current_pos,
g_base_info_get_name (arg_info));
callback_info = create_c_callback_closure (interface, func);
callback_info->data_pos = g_arg_info_get_closure (arg_info);
callback_info->destroy_pos = g_arg_info_get_destroy (arg_info);
g_base_info_unref (arg_info);
if (func) {
data_sv = newSViv (PTR2IV (callback_info));
stash = gv_stashpv ("Glib::Object::Introspection::_FuncWrapper", TRUE);
code_sv = sv_bless (newRV_noinc (data_sv), stash);
} else {
data_sv = code_sv = &PL_sv_undef;
}
callback_info->data_sv = data_sv;
dwarn (" C callback data at %d, destroy at %d\n",
callback_info->data_pos, callback_info->destroy_pos);
invocation_info->callback_infos =
g_slist_prepend (invocation_info->callback_infos,
callback_info);
dwarn (" returning C closure %p from info %p\n",
code_sv, callback_info);
return code_sv;
}
static SV *
callback_data_to_sv (gpointer data,
GPerlI11nInvocationInfo * invocation_info)
{
GSList *l;
if (!invocation_info)
return NULL;
for (l = invocation_info->callback_infos; l != NULL; l = l->next) {
GPerlI11nCCallbackInfo *callback_info = l->data;
if (callback_info->data_pos == invocation_info->current_pos) {
dwarn (" user data for C callback %p\n",
callback_info);
attach_c_callback_data (callback_info, data);
return callback_info->data_sv;
}
}
if (data && invocation_info->is_callback) {
GPerlI11nPerlCallbackInfo *wrapper = data;
dwarn (" user data for Perl callback %p\n", wrapper);
return wrapper->data;
}
return NULL;
}
|