On Jan 19, 2011, at 17:47 , Konovalov, Vadim (Vadim)** CTR ** wrote:

> First, I did not liked the name bind_... either.
> create_commands obviously better.
> (or maybe create_tcl_commands?)
> 
> However I think the idea could be extended to variables as well, how do
> you think, is it possible to leave this name but add functionality to
> variables also?

Perhaps?

$interp->export_to_tcl(
    namespace => "perl",
    subs => { ... },
    vars => { ... },
    subs_from => $ns,
    vars_from => $ns,
);

I think you should say it explicitly if you want to export vars from a 
namespace as well.  You might for instance have some vars in that namespace 
that is shared between the perl subs without the intention to access it from 
Tcl.

> And having default namespace to be 'perl'  also seems reasonable to me.

Fine with me as long as it's possible to pass "" or "::" to signal the root 
namespace.

> Please see below the code I suggest, it is not finished, but all ideas are 
> expressed.
> 
> Opinions welcome.
> 
> Best regards,
> Vadim.
> 
> 
> =comment
> An interpreter method, bind_perl_to_tcl_commands, takes two optional
> arguments - tcl package name (defaults to 'tcl') and perl package name
> (defaults to 'tcl')
> 
> Given a number of Perl sub's in said package, which is passed as the
> second parameter, binds all of them into tcl, in the said package, which
> is passed as the first parameter to the bind_perl_to_tcl_commands method.
> 
> An example:
> 
> use strict;
> use Tcl;
> 
> my $int = new Tcl;
> 
> $tcl::foo = 'qwerty';
> $int->create_tcl_commands(subs_from=>'tcl');
> 
> $int->Eval(<<'EOS');
> 
> package require Tk
> 
> button .b1 -text {a fluffy button} -command perl::fluffy_sub
> button .b2 -text {a foo button} -command perl::foo
> entry .e -textvariable perl::foo
> pack .b1 .b2 .e
> focus .b2
> 
> tkwait window .
> EOS
> 
> sub tcl::fluffy_sub {
>    print "Hi, I am a fluffy sub\n";
> }
> sub tcl::foo {
>    print "Hi, I am foo\n";
>    $tcl::foo++;
> }
> =cut
> 
> sub create_tcl_commands {
>    my $int = shift;
>    my %args = @_;
> 
>    # name of Tcl package to hold tcl commands bound to perl subroutines
>    my $tcl_namespace = $args{namespace} || 'perl';
> 
>    # a batch of perl subroutines which tcl counterparts should be created
>    my $subs = $args{subs} || {};
> 
>    # name of Perl package, which subroutines would be bound to tcl commands
>    my $subs_from = $args{subs_from};
> 
>    if ($subs_from) {
>       for my $name (keys %{"$subs_from\::"}) {
>           print STDERR "$name;\n";
>           if (defined &{"$subs_from\::$name"}) {
>               if (exists $sub->{$name}) {
>                   next;
>               }
>               # print STDERR "binding sub '$name'\n";
>               
> $int->CreateCommand("$tcl_namespace\::$name",\&{"$subs_from\::$name"});

Call CreateCommand($tclname, \&sub, undef, undef, 1) to get avoid getting 
passed (undef, $int, $name) as the first 3 arguments to the callback.

>           }
>           if (defined ${"$subs_from\::$name"}) {
>               # print STDERR "binding var '$name'\n";
>               local $_ = ${"$subs_from\::$name"};
>               tie ${"$subs_from\::$name"}, 'Tcl::Var', $int, 
> "$tcl_namespace\::$name";
>               ${"$subs_from\::$name"} = $_;
>           } 
>           {
>               # array, hash - no need to.
>           }
>       }
>    }
> 
>    for my $subname (keys %$subs) {
>        $int->CreateCommand("$tcl_namespace\::$subname",$subs{$subname});
>    }
> }

--Gisle

> 
> 
> 
>> -----Original Message-----
>> From: Gisle Aas [mailto:[email protected]] 
>> Sent: Tuesday, January 18, 2011 10:08 PM
>> To: Konovalov, Vadim (Vadim)** CTR **
>> Cc: Jeff Hobbs; [email protected]
>> Subject: Re: bind some said tcl to perl - all at once
>> 
>> I don't like to use the name 'bind_...' for this.  To me it 
>> sounds like this would bind the namespace together so that 
>> subs created after the call also become visible to Tcl and 
>> perhaps even that commands created on the Tcl side become 
>> visible to Perl.
>> 
>> My suggestion would be to make a convenience method like this one:
>> 
>> $interp->create_commands(
>>    namespace => "perl",
>>    subs => {
>>        foo => sub { .... },
>>        bar => sub { .... },
>>    }
>> );
>> 
>> where the "namespace" argument is optional.  It's the Tcl 
>> namespace where the commands will be created. If not provided 
>> the names will be registered in the root namespace.  This 
>> would also always call the underlying $interp->CreateCommand 
>> with FLAGS=1 in order to suppress the confusing initial 
>> legacy arguments.  The keys of the subs hash could also use 
>> "::ns::foo" style names in which case the namespace argument 
>> is ignored for that particular key.
>> 
>> Your use case would then be covered by:
>> 
>> $interp->create_commands(
>>    namespace => "perl",
>>    subs => \%{"tcl\::"},
>> );
>> 
>> which is a bit ugly to write so you might be able to provide 
>> some sugar like:
>> 
>> $interp->create_commands(
>>    namespace => "perl",
>>    subs_from => "tcl",
>> );
>> 
>> if 'subs' and 'subs_from' are provided together they both 
>> contribute; with 'subs' taking preference in case there are 
>> conflicting names.  Alternatively croak on conflicting names.
>> 
>> I would also suggest a 'only => \@list_of_names' argument to 
>> be able to limit the names to export to Tcl.
>> 
>> Regards,
>> Gisle
>> 
>> 
>> 
>> On Jan 18, 2011, at 17:20 , Konovalov, Vadim (Vadim)** CTR ** wrote:
>> 
>>>> From: Jeff Hobbs [mailto:[email protected]] 
>>>> On 15/01/2011 1:35 PM, Konovalov, Vadim (Vadim)** CTR ** wrote:
>>>>> I wonder, is it reasonable for this approach to be 
>>>> "standartized" and included to, say, Tcl.pm module?
>>>>> 
>>>>> For example - all Tcl names from some predefined Tcl 
>>>> namespace could be bound to perl subroutines all at once.
>>>> 
>>>> I think it would be good to provide this as a standard convenience 
>>>> function, that would tie either a Perl or Tcl namespace to 
>> the other 
>>>> language.  I don't think we'd want to pre-define the 
>> namespace (note 
>>>> that Tcl.pm already uses ::perl:: on the Tcl side), but 
>> let the user 
>>>> pick it with a single command invocation.
>>> 
>>> Indeed, Tcl.pm uses ::perl:: in Tcl::call.
>>> 
>>> All refs in this namespace have names like 
>> "SCALAR(0xXXXXXX)" or "CODE(0x######)", and it is very 
>> unlikely to have a collision. IOW, the collision could happen 
>> if a user have an intention to create a collision, but he/she 
>> could just create such a collision anyway, by creating 
>> conflicting names using another existing mechanisms.
>>> 
>>> Ok, below is my suggestion to include to Tcl.pm,
>>> 
>>> 
>>> =comment
>>> An interpreter method, bind_perl_to_tcl_commands, takes two optional
>>> arguments - tcl package name (defaults to 'tcl' and perl 
>> package name
>>> (defaults to 'tcl')
>>> 
>>> Given a number of Perl sub's in said package, which is passed as the
>>> second parameter, binds all of them into tcl, in the said 
>> package, which
>>> is passed as the first parameter to the 
>> bind_perl_to_tcl_commands method.
>>> 
>>> An example:
>>> 
>>> use Tcl;
>>> 
>>> my $int = new Tcl;
>>> 
>>> $int->bind_perl_to_tcl_commands;
>>> 
>>> $int->Eval(<<'EOS');
>>> 
>>> package require Tk
>>> 
>>> button .b1 -text {a fluffy button} -command perl::fluffy_sub
>>> button .b2 -text {a foo button} -command perl::foo
>>> pack .b1 .b2
>>> 
>>> tkwait window .
>>> EOS
>>> 
>>> sub tcl::fluffy_sub {
>>>   print "Hi, I am a fluffy sub\n";
>>> }
>>> sub tcl::foo {
>>>   print "Hi, I am foo\n";
>>> }
>>> 
>>> =cut
>>> 
>>> sub bind_perl_to_tcl_commands {
>>>   my $int = shift;
>>> 
>>>   # name of Tcl package to hold tcl commands bound to perl 
>> subroutines
>>>   my $tcl_namespace = shift || 'perl';
>>> 
>>>   # name of Perl package, which subroutines would be bound 
>> to tcl commands
>>>   my $perl_namespace = shift || 'tcl';
>>> 
>>>   die "Shouldn't bind to main package"
>>>       if $perl_namespace eq "" || $perl_namespace eq "main";
>>> 
>>>   for my $subname (keys %{"$perl_namespace\::"}) {
>>>     # have no need to check if this is a sub name or a var 
>> name, as long
>>>     # as we're binding to CODE, \&{"..."}
>>>     
>> $int->CreateCommand("$tcl_namespace\::$subname",\&{"$perl_name
>> space\::$subname"});
>>>   }
>>> }
>>> 
>>> 
>>> Similar binding of variables could also be added.
>>> 
>>> Best regards,
>>> Vadim.
>> 
>> 

Reply via email to