Audio
view release on metacpan or search on metacpan
Data/mkVFunc view on Meta::CPAN
elsif (/\b(EXTERN|extern)\b/)
{
die "$hfile:$.: $_" unless (/^\s*#\s*define/);
}
}
close(H);
if (keys %VFunc || keys %VVar)
{
my $gard = "\U$hfile";
$gard =~ s/\..*$//;
$gard =~ s#/#_#g;
my $name = "\u\L${gard}\UV";
$fdef = $hfile;
$fdef =~ s/\..*$/.t/;
$mdef = $hfile;
$mdef =~ s/\..*$/.m/;
my $htfile = $hfile;
$htfile =~ s/\..*$/_f.h/;
unless (-r $htfile)
{
open(C,">$htfile") || die "Cannot open $htfile:$!";
print C "#ifndef ${gard}_VT\n";
print C "#define ${gard}_VT\n";
print C "#include \"$hfile\"\n";
print C "typedef struct ${name}tab\n{\n";
print C "#define VFUNC(type,name,mem,args) type (*mem) args;\n";
print C "#define VVAR(type,name,mem) type (*mem);\n";
print C "#include \"$fdef\"\n";
print C "#undef VFUNC\n";
print C "#undef VVAR\n";
print C "} ${name}tab;\n";
print C "extern ${name}tab *${name}ptr;\n";
print C "extern ${name}tab *${name}Get _((void));\n";
print C "#endif /* ${gard}_VT */\n";
close(C);
}
my $cfile = $hfile;
$cfile =~ s/\..*$/_f.c/;
unless (-r $cfile)
{
open(C,">$cfile") || die "Cannot open $cfile:$!";
print C "#include \"$hfile\"\n";
print C "#include \"$htfile\"\n";
print C "static ${name}tab ${name}table =\n{\n";
print C "#define VFUNC(type,name,mem,args) name,\n";
print C "#define VVAR(type,name,mem) &name,\n";
print C "#include \"$fdef\"\n";
print C "#undef VFUNC\n";
print C "#undef VVAR\n";
print C "};\n";
print C "${name}tab *${name}ptr;\n";
print C "${name}tab *${name}Get() { return ${name}ptr = &${name}table;}\n";
close(C);
}
print STDERR "$gard\n";
chmod(0666,$fdef) unless -w $fdef;
open(VFUNC,">$fdef") || die "Cannot open $fdef:$!";
chmod(0666,$mdef) unless -w $mdef;
open(VMACRO,">$mdef") || die "Cannot open $mdef:$!";
print VFUNC "#ifdef _$gard\n";
print VMACRO "#ifndef _${gard}_VM\n";
print VMACRO "#define _${gard}_VM\n";
print VMACRO "#include \"$htfile\"\n";
foreach $func (sort keys %VVar)
{
if (!exists $Exclude{$func})
{
print VFUNC $VVar{$func};
print VMACRO "#define $func (*${name}ptr->V_$func)\n"
}
}
foreach $func (sort keys %VFunc)
{
if (!exists $Exclude{$func})
{
print VFUNC $VFunc{$func};
print VMACRO "#define $func (*${name}ptr->V_$func)\n"
}
}
print VMACRO "#endif /* _${gard}_VM */\n";
close(VMACRO);
print VFUNC "#endif /* _$gard */\n";
close(VFUNC); # Close this last - Makefile dependancy
}
}
foreach (<tk*Tab.c>)
{
Exclude($_);
}
foreach (@ARGV)
{
Vfunc($_);
}
__END__
=head1 NAME
mkVFunc - Support for "nested" dynamic loading
=head1 SYNOPSIS
mkVFunc xxx.h
=head1 DESCRIPTION
B<perl/Tk> is designed so that B<Tk> can be dynamically loaded 'on top of'
perl. That is the easy bit. What it also does is allow Tk::Xxxx to be
dynamically loaded 'on top of' the B<perl/Tk> composite. Thus when
you 'require Tk::HList' the shared object F<.../HList.so> needs to be
able to call functions defined in perl I<and> functions defined in loadable
.../Tk.so . Now functions in 'base executable' are a well known problem,
and are solved by DynaLoader. However most of dynamic loading schemes
cannot handle one loadable calling another loadable.
Thus what Tk does is build a table of functions that should be callable.
( run in 2.018 seconds using v1.01-cache-2.11-cpan-cdf2f3d4e48 )