[perl-Glib/gio-support: 11/12] [gio] Ditch AUTOLOAD in favor of pre-installing sub stubs
- From: Torsten Schönfeld <tsch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [perl-Glib/gio-support: 11/12] [gio] Ditch AUTOLOAD in favor of pre-installing sub stubs
- Date: Mon, 12 Apr 2010 21:12:50 +0000 (UTC)
commit 410aea22039a67ce164bdbb327b65910218130c2
Author: Torsten Schönfeld <kaffeetisch gmx de>
Date: Mon Apr 12 22:05:08 2010 +0200
[gio] Ditch AUTOLOAD in favor of pre-installing sub stubs
GObjectIntrospection.xs | 103 +++++++++++++++++++++++++++++++++------------
lib/Glib.pm | 105 ++++++++++++----------------------------------
2 files changed, 103 insertions(+), 105 deletions(-)
---
diff --git a/GObjectIntrospection.xs b/GObjectIntrospection.xs
index f18552a..d17e1bb 100644
--- a/GObjectIntrospection.xs
+++ b/GObjectIntrospection.xs
@@ -1087,31 +1087,65 @@ release_callback (gpointer data)
/* ------------------------------------------------------------------------- */
static void
-clone_autoload (const gchar *base_package, const gchar *package)
+store_methods (HV *namespaced_functions, GIBaseInfo *info, GIInfoType info_type)
{
- gchar *autoload_name;
- GV *autoload_glob;
- CV *autoload_code;
- gchar *package_autoload;
- GV *gv;
-
- /* FIXME: This would only need to be done once per register_types()
- call */
- autoload_name = g_strconcat (base_package, "::AUTOLOAD", NULL);
- autoload_glob = gv_fetchpv (autoload_name, GV_NOADD_NOINIT, SVt_PVCV);
- autoload_code = GvCV (autoload_glob);
- g_free (autoload_name);
-
- package_autoload = g_strconcat (package, "::AUTOLOAD", NULL);
- gv = gv_fetchpv (package_autoload, GV_ADDMULTI, SVt_PVCV);
- g_free (package_autoload);
-
- /* FIXME: Shouldn't we have to increase the CV's ref count? Valgrind
- doesn't complain, though.
- SvREFCNT_inc (autoload_code); */
- GvCV (gv) = autoload_code;
- GvCVGEN (gv) = 0;
- mro_method_changed_in (GvSTASH (gv)); /* FIXME: version checks */
+ const gchar *namespace;
+ AV *av;
+ gint i;
+
+ namespace = g_base_info_get_name (info);
+ av = newAV ();
+
+ switch (info_type) {
+ case GI_INFO_TYPE_OBJECT:
+ {
+ gint n_methods = g_object_info_get_n_methods (
+ (GIObjectInfo *) info);
+ for (i = 0; i < n_methods; i++) {
+ GIFunctionInfo *function_info =
+ g_object_info_get_method (
+ (GIObjectInfo *) info, i);
+ const gchar *function_name =
+ g_base_info_get_name (
+ (GIBaseInfo *) function_info);
+ av_push (av, newSVpv (function_name, PL_na));
+ g_base_info_unref ((GIBaseInfo *) function_info);
+ }
+ break;
+ }
+
+ case GI_INFO_TYPE_INTERFACE:
+ {
+ gint n_methods = g_interface_info_get_n_methods (
+ (GIInterfaceInfo *) info);
+ for (i = 0; i < n_methods; i++) {
+ GIFunctionInfo *function_info =
+ g_interface_info_get_method (
+ (GIInterfaceInfo *) info, i);
+ const gchar *function_name =
+ g_base_info_get_name (
+ (GIBaseInfo *) function_info);
+ av_push (av, newSVpv (function_name, PL_na));
+ g_base_info_unref ((GIBaseInfo *) function_info);
+ }
+ break;
+ break;
+ }
+
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_STRUCT:
+ {
+ /* FIXME */
+ break;
+ }
+
+ case GI_INFO_TYPE_UNION:
+ default:
+ croak ("store_methods: unsupported info type %d", info_type);
+ }
+
+ gperl_hv_take_sv (namespaced_functions, namespace, strlen (namespace),
+ newRV_noinc ((SV *) av));
}
/* ------------------------------------------------------------------------- */
@@ -1129,13 +1163,18 @@ register_types (class, namespace, version, package)
GIRepository *repository;
GError *error = NULL;
gint number, i;
- CODE:
+ AV *global_functions;
+ HV *namespaced_functions;
+ PPCODE:
repository = g_irepository_get_default ();
g_irepository_require (repository, namespace, version, 0, &error);
if (error) {
gperl_croak_gerror (NULL, error);
}
+ global_functions = newAV ();
+ namespaced_functions = newHV ();
+
number = g_irepository_get_n_infos (repository, namespace);
for (i = 0; i < number; i++) {
GIBaseInfo *info;
@@ -1148,6 +1187,10 @@ register_types (class, namespace, version, package)
info_type = g_base_info_get_type (info);
name = g_base_info_get_name (info);
+ if (info_type == GI_INFO_TYPE_FUNCTION) {
+ av_push (global_functions, newSVpv (name, PL_na));
+ }
+
if (info_type != GI_INFO_TYPE_OBJECT &&
info_type != GI_INFO_TYPE_INTERFACE &&
info_type != GI_INFO_TYPE_BOXED &&
@@ -1160,7 +1203,6 @@ register_types (class, namespace, version, package)
type = g_registered_type_info_get_g_type (
(GIRegisteredTypeInfo *) info);
- g_base_info_unref ((GIBaseInfo *) info);
if (!type) {
croak ("Could not find GType for type %s::%s",
namespace, name);
@@ -1180,7 +1222,7 @@ register_types (class, namespace, version, package)
info_type == GI_INFO_TYPE_STRUCT ||
info_type == GI_INFO_TYPE_UNION)
{
- clone_autoload (package, full_package);
+ store_methods (namespaced_functions, info, info_type);
}
switch (info_type) {
@@ -1205,8 +1247,13 @@ register_types (class, namespace, version, package)
}
g_free (full_package);
+ g_base_info_unref ((GIBaseInfo *) info);
}
+ EXTEND (SP, 2);
+ PUSHs (sv_2mortal (newRV_noinc ((SV *) global_functions)));
+ PUSHs (sv_2mortal (newRV_noinc ((SV *) namespaced_functions)));
+
=for apidoc __hide__
=cut
void
@@ -1370,7 +1417,7 @@ PPCODE:
/* prepare and call the function */
if (FFI_OK != ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_invoke_args,
- return_type_ffi, arg_types))
+ return_type_ffi, arg_types))
{
g_base_info_unref ((GIBaseInfo *) return_type_info);
croak ("Could not prepare a call interface for %s", symbol);
diff --git a/lib/Glib.pm b/lib/Glib.pm
index 047d57f..349cc09 100644
--- a/lib/Glib.pm
+++ b/lib/Glib.pm
@@ -219,96 +219,47 @@ package Glib::Object::_Introspection;
use strict;
-sub find_registered_ancestors {
- my ($class, $namespace) = @_;
-
- my @ancestors = ($namespace);
- {
- no strict 'refs';
- my @parents = @{$namespace . '::ISA'};
- foreach my $parent (@parents) {
- push @ancestors, __PACKAGE__->find_registered_ancestors($parent);
- }
- }
+sub setup {
+ my ($class, %params) = @_;
+ my $basename = $params{basename};
+ my $version = $params{version};
+ my $package = $params{package};
+
+ my ($global_functions, $namespaced_functions) =
+ __PACKAGE__->register_types($basename, $version, $package);
- my @registered_ancestors =
- grep { !m/^Glib::Object::_Unregistered::/ } @ancestors;
+ no strict 'refs';
- return @registered_ancestors;
+ foreach my $name (@{$global_functions}) {
+ # warn "${package}::$name => $name\n";
+ *{$package . '::' . $name} = sub {
+ __PACKAGE__->invoke($basename, undef, $name, @_);
+ };
+ }
+
+ foreach my $namespace (keys %{$namespaced_functions}) {
+ foreach my $name (@{$namespaced_functions->{$namespace}}) {
+ # warn "${package}::${namespace}::$name => $name\n";
+ *{$package . '::' . $namespace . '::' . $name} = sub {
+ __PACKAGE__->invoke($basename, $namespace, $name, @_);
+ };
+ }
+ }
}
package Glib::IO;
use strict;
-use Carp;
our $BASENAME = 'Gio';
our $VERSION = '2.0';
our $PACKAGE = 'Glib::IO';
-our $AUTOLOAD;
-
-sub AUTOLOAD {
- my $symbol = $AUTOLOAD;
- my (@args) = @_;
-
- # 'namespace::method' or just 'method'
- if ($symbol =~ m/(?:(.+)::)?(.+)/) {
- my $symbol_namespace = $1;
- my $symbol_method = $2;
-
- # FIXME: we are effectively reimplementing method resolution here.
- # consider ditching the AUTOLOAD clutch in favor of just installing sub
- # stubs in the correct places for all methods and functions.
- my @namespace_candidates = ();
- if (defined $symbol_namespace) {
- @namespace_candidates =
- Glib::Object::_Introspection->find_registered_ancestors (
- $symbol_namespace);
-
- # strip off the normal prefix
- foreach my $namespace (@namespace_candidates) {
- # alter the array in-place
- $namespace =~ s/^${PACKAGE}(?:::)?//;
- $namespace = undef if $namespace eq '';
- }
- }
-
- if (! namespace_candidates) {
- @namespace_candidates = (undef);
- }
-
- # warn "namespace candidates for $symbol: (@namespace_candidates)\n";
-
- my @errors;
- my @results;
- foreach my $namespace (@namespace_candidates) {
- @results = eval {
- Glib::Object::_Introspection->invoke(
- $BASENAME, $namespace, $symbol_method, @args); };
- if ($@) {
- if ($ ->isa ('Glib::Error')) {
- croak $@;
- }
- push @errors, $@;
- } else {
- @errors = ();
- last;
- }
- }
-
- if (! results && @errors) {
- croak "Invalid invocation of $symbol:\n ", join "\n ", @errors;
- }
-
- return wantarray ? @results : $results[0];
- }
-
- croak "Invalid invocation: Cannot handle $symbol";
-}
-
sub setup {
- Glib::Object::_Introspection->register_types($BASENAME, $VERSION, $PACKAGE);
+ Glib::Object::_Introspection->setup(basename => $BASENAME,
+ version => $VERSION,
+ package => $PACKAGE);
+
}
package Glib;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]