[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

tcltklib and not init'ing tk

aakhter

10/1/2003 6:00:00 AM

Hello,

I'm using the tcltklib extension in ruby 1.8. It seems to be working
well for my transition from tcl. There are a couple of stumbling
blocks I'm running into:

1) is there a way to _not_ start tk? When I create a new interpreter
(let's say from a non X-fwded ssh session) it may cause a failure. I'm
only interested in Tcl.

2) Is there a japanese to english translation of
ext/tcltklib/MANUAL.euc? Or can somebody point to a tool that I may
use to do the translation? babelfish.altavista does not appear to
work.

3). Are there any examples of ruby methods being called from the tcl
code running inside the interpreter?

Thank-you,

Aamer Akhter,
cisco Systems
13 Answers

Brett H. Williams

10/1/2003 2:07:00 PM

0

On Oct 1, Aamer Akhter wrote:
> Hello,
>
> I'm using the tcltklib extension in ruby 1.8. It seems to be working
> well for my transition from tcl. There are a couple of stumbling
> blocks I'm running into:
>
> 1) is there a way to _not_ start tk? When I create a new interpreter
> (let's say from a non X-fwded ssh session) it may cause a failure. I'm
> only interested in Tcl.

This is a big pain for me as well. I would really like to have this fixed,
as Ruby/Tcl interaction is important to me. But it hasn't been a big
enough pain to try and hack around in the C code :) (yet)

> 2) Is there a japanese to english translation of
> ext/tcltklib/MANUAL.euc? Or can somebody point to a tool that I may
> use to do the translation? babelfish.altavista does not appear to
> work.

I've done all of my work without any kind of documentation in English.
There just doesn't seem to be that strong an interest in mixing Ruby and
Tcl (we are some of the exceptions). The tcltklib extension was written
for Ruby/Tk. Access to the Tcl interpreter through it is a side effect--a
highly useful side effect for me and you, but nevertheless not really
what was intended by the developers. So using the Tcl interpreter from
Ruby, and vice versa, is probably not even well documented in Japanese
(someone please correct me if I am wrong).

> 3). Are there any examples of ruby methods being called from the tcl
> code running inside the interpreter?

This is how I do it:

set somevar [ruby "some_method()"]

You can put any ruby code as the argument to the 'ruby' proc. You _must_,
however, make sure that the return value of the ruby code is a string, or
things will crash.

You likely will have to do some creative things to get the scope that you
want--Tcl can only communicate directly with class or global variables.
This means if you call out to Tcl from Ruby, you will not have access to
instance or local variables. It makes perfect sense, but typically
requires doing some non-rubyish things to get access to what you need in
Tcl.

--
---------------------------------------------- | --------------------------
Brett Williams | (970) 288-0475
Agilent Technologies | brett_williams@agilent.com
---------------------------------------------- | --------------------------

Ferenc Engard

10/1/2003 7:32:00 PM

0

"Brett H. Williams" wrote:
>
> On Oct 1, Aamer Akhter wrote:
[...]
> > 2) Is there a japanese to english translation of
> > ext/tcltklib/MANUAL.euc? Or can somebody point to a tool that I may
> > use to do the translation? babelfish.altavista does not appear to
> > work.

I have some hungarian notes about its work... :)) Sorry. :-/

> for Ruby/Tk. Access to the Tcl interpreter through it is a side effect--a
> highly useful side effect for me and you, but nevertheless not really

And me :)

> > 3). Are there any examples of ruby methods being called from the tcl
> > code running inside the interpreter?

You can register ruby proc objects into tcl and use it. However, it is a
bit though to understand.

Actually, there is a ruby_fmt proc which is buggy, but it is extensively
used by tcltklib. Here is a patch for 1.6.7, but I do not think that it
has changed since then...

--------------------------------------------------------------------
--- tcltk.old.rb 2002-02-07 02:53:30.000000000 +0100
+++ tcltk_jav.rb 2003-01-07 02:36:04.000000000 +0100
@@ -93,9 +93,9 @@
# ruby_fmt command format arguments by `format' and call `ruby'
command
# (notice ruby command receives only one argument)
if $DEBUG
- @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt
$args\" ; ruby [format $fmt $args] }")
+ @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt
$args\" ; set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }")
else
- @ip._eval("proc ruby_fmt {fmt args} { ruby [format $fmt $args]
}")
+ @ip._eval("proc ruby_fmt {fmt args} { set cmd [list ruby [format
$fmt $args]] ; uplevel $cmd }")
end

# @ip._get_eval_string(*args): generate string to evaluate in tcl
interpreter
--------------------------------------------------------------------

Here I post a testprog of mine, ask if you cannot figure out what is
going on...

--------------------------------------------------------------------
require "tcltk"

$DEBUG=1

ip=TclTkInterpreter.new
pr=proc { |*args|
puts "args: #{args}"
puts "valami"
}
# megoldás paraméterátadásra
# cb.to_eval: {ruby_fmt {TclTk._callcallback("c_1", "%%s")} %s}
cb=TclTkCallback.new(ip,pr,"%s")
puts "cb to_eval: #{cb.to_eval}"

# a [format] a %%s helyére %s-t, %s helyére pedig param1-et helyettesít,
azaz:
# ... -command {ruby_fmt {TclTk._callcallback("c_1", "%s")} param1}
btn1=TclTkWidget.new(ip,".","button","-text valami","-command [format ",
cb,"param1]")
ip.pack(btn1)

TclTk.mainloop
--------------------------------------------------------------------

Aamer Akhter

10/1/2003 7:45:00 PM

0


Nice to see a fellow industry member dealing with the same problem ;-)

On 10/1/03 10:06 AM, in article
20031001140652.GA29212@vor-lord.ftc.agilent.com, "Brett H. Williams"
<brett_williams@agilent.com> wrote:

> On Oct 1, Aamer Akhter wrote:
>> Hello,
>>
>> I'm using the tcltklib extension in ruby 1.8. It seems to be working
>> well for my transition from tcl. There are a couple of stumbling
>> blocks I'm running into:
>>
>> 1) is there a way to _not_ start tk? When I create a new interpreter
>> (let's say from a non X-fwded ssh session) it may cause a failure. I'm
>> only interested in Tcl.
>
> This is a big pain for me as well. I would really like to have this fixed,
> as Ruby/Tcl interaction is important to me. But it hasn't been a big
> enough pain to try and hack around in the C code :) (yet)

I'm more than willing to spend some time on this. But I'm new to ruby, and
to the tcl-C portions.

It seems like the thing to do is be able to pass the desire for no tk in via
the new call:

TclTkIp.new(notk => 1),

It looks like tcltklib.c:ip_init() gets called. The current parameters wind
up being plugged into Tcl's argv0 and args. So, in keeping with the current
implementation perhaps something like:

TclTkIp.new($argv0, $args, 1) would be "better"

Where 1 represents the non-desire to load Tk.

One would need to skip over when 1 is set.:

/* from Tcl_AppInit() */
DUMP1("Tk_Init");
if (Tk_Init(ptr->ip) == TCL_ERROR) {
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}
DUMP1("Tcl_StaticPackage(\"Tk\")");
#if TCL_MAJOR_VERSION >= 8
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit);
#else
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
(Tcl_PackageInitProc *) NULL);
#endif


>> 2) Is there a japanese to english translation of
>> ext/tcltklib/MANUAL.euc? Or can somebody point to a tool that I may
>> use to do the translation? babelfish.altavista does not appear to
>> work.
>
> I've done all of my work without any kind of documentation in English.
> There just doesn't seem to be that strong an interest in mixing Ruby and
> Tcl (we are some of the exceptions). The tcltklib extension was written
> for Ruby/Tk. Access to the Tcl interpreter through it is a side effect--a
> highly useful side effect for me and you, but nevertheless not really
> what was intended by the developers. So using the Tcl interpreter from
> Ruby, and vice versa, is probably not even well documented in Japanese
> (someone please correct me if I am wrong).
>
>> 3). Are there any examples of ruby methods being called from the tcl
>> code running inside the interpreter?
>
> This is how I do it:
>
> set somevar [ruby "some_method()"]
>
> You can put any ruby code as the argument to the 'ruby' proc. You _must_,
> however, make sure that the return value of the ruby code is a string, or
> things will crash.

;-) yeah. I already ran into that. I've been using the ruby_fmt proc that
tcltk creates on init. That's just a wrapper for calling the ruby tcl
command.

>
> You likely will have to do some creative things to get the scope that you
> want--Tcl can only communicate directly with class or global variables.
> This means if you call out to Tcl from Ruby, you will not have access to
> instance or local variables. It makes perfect sense, but typically
> requires doing some non-rubyish things to get access to what you need in
> Tcl.

I don't think the importance of the above has sunk in yet. Do you mean to
say that in a class, I won't be able to do something like:

Ip._eval("puts #{var}")


Brett H. Williams

10/1/2003 8:34:00 PM

0

On Oct 2, Aamer Akhter wrote:
>
> Nice to see a fellow industry member dealing with the same problem ;-)
>
> On 10/1/03 10:06 AM, in article
> 20031001140652.GA29212@vor-lord.ftc.agilent.com, "Brett H. Williams"
> <brett_williams@agilent.com> wrote:
>
> > On Oct 1, Aamer Akhter wrote:
> >> Hello,
> >>
> >> I'm using the tcltklib extension in ruby 1.8. It seems to be working
> >> well for my transition from tcl. There are a couple of stumbling
> >> blocks I'm running into:
> >>
> >> 1) is there a way to _not_ start tk? When I create a new interpreter
> >> (let's say from a non X-fwded ssh session) it may cause a failure. I'm
> >> only interested in Tcl.
> >
> > This is a big pain for me as well. I would really like to have this fixed,
> > as Ruby/Tcl interaction is important to me. But it hasn't been a big
> > enough pain to try and hack around in the C code :) (yet)
>
> I'm more than willing to spend some time on this. But I'm new to ruby, and
> to the tcl-C portions.
>
> It seems like the thing to do is be able to pass the desire for no tk in via
> the new call:
>
> TclTkIp.new(notk => 1),
>
> It looks like tcltklib.c:ip_init() gets called. The current parameters wind
> up being plugged into Tcl's argv0 and args. So, in keeping with the current
> implementation perhaps something like:
>
> TclTkIp.new($argv0, $args, 1) would be "better"
>
> Where 1 represents the non-desire to load Tk.
>
> One would need to skip over when 1 is set.:
>
> /* from Tcl_AppInit() */
> DUMP1("Tk_Init");
> if (Tk_Init(ptr->ip) == TCL_ERROR) {
> rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
> }
> DUMP1("Tcl_StaticPackage(\"Tk\")");
> #if TCL_MAJOR_VERSION >= 8
> Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit);
> #else
> Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
> (Tcl_PackageInitProc *) NULL);
> #endif

This kind of approach has merit... however, in the current setup, simply
doing:

require 'tk'

dies if the DISPLAY is not set. It seems a reorganization of how the
tcltklib module is presented would be needed as well.

Am I missing a better way to get access to the Tcl interpreter?

> ;-) yeah. I already ran into that. I've been using the ruby_fmt proc that
> tcltk creates on init. That's just a wrapper for calling the ruby tcl
> command.

I have not been using this, but perhaps I should. The way I've been doing
it usually leads to naming differences and confusion, like:

TclFuncs = <<-EOTCL
proc foo {args} {
ruby {bar('$args')}
}
EOTCL

#TclFuncs is evaled into the tcl interpreter...

def bar(args)
...
end


> > You likely will have to do some creative things to get the scope that you
> > want--Tcl can only communicate directly with class or global variables.
> > This means if you call out to Tcl from Ruby, you will not have access to
> > instance or local variables. It makes perfect sense, but typically
> > requires doing some non-rubyish things to get access to what you need in
> > Tcl.
>
> I don't think the importance of the above has sunk in yet. Do you mean to
> say that in a class, I won't be able to do something like:
>
> Ip._eval("puts #{var}")

No, because #{var} will be interpolated before the call to Tcl's eval.

What I mean is that the following will not work (note that TclUtils
provides some wrapper functionality that ultimately results in a call to
Tk.tk_call("eval", cmd)... I didn't know about _eval which is probably what
I should be using):

#tcl function defined as follows...
proc some_proc {} {
set somevar [ruby {do_something()}]
}

#and a ruby methods defined as...
class SomeClass
def do_something()
...
return some_str
end

def some_instance_method()
TclUtils.eval("some_proc")
end
end

When you call some_instance_method(), and it runs the tcl proc 'some_proc',
the Tcl interpreter is calling things at the basest level of Ruby scoping,
so there will be no such method 'do_something' at that level.


If this seemed obvious to you that such a thing wouldn't work, perhaps it
is. But it is an ugliness you have to deal with when spanning the two
worlds.

I end up having a current_obj variable or something which can be gotten at
with a class method at the Tcl level, i.e.:

proc some_proc {} {
set somevar [ruby {SomeClass.current_obj.do_something()}]
}

#and...
class SomeClass
def SomeClass.current_obj
return @@current_obj
end

...

def some_instance_method()
@@current_obj = self
TclUtils.eval("some_proc")
end
end

Ugly. Sinfully ugly. Luckily, I try to keep Ruby in control of most
everything, and the Tcl is a configuration file, so I don't need to do this
that often.

--
---------------------------------------------- | --------------------------
Brett Williams | (970) 288-0475
Agilent Technologies | brett_williams@agilent.com
---------------------------------------------- | --------------------------

Aamer Akhter

10/2/2003 12:45:00 AM

0

On 10/1/03 4:34 PM, in article
20031001203415.GB2632@vor-lord.ftc.agilent.com, "Brett H. Williams"
<brett_williams@agilent.com> wrote:

> On Oct 2, Aamer Akhter wrote:
>>
>> Nice to see a fellow industry member dealing with the same problem ;-)
>>
>> On 10/1/03 10:06 AM, in article
>> 20031001140652.GA29212@vor-lord.ftc.agilent.com, "Brett H. Williams"
>> <brett_williams@agilent.com> wrote:
>>
>>> On Oct 1, Aamer Akhter wrote:
>>>> Hello,
>>>>
>>>> I'm using the tcltklib extension in ruby 1.8. It seems to be working
>>>> well for my transition from tcl. There are a couple of stumbling
>>>> blocks I'm running into:
>>>>
>>>> 1) is there a way to _not_ start tk? When I create a new interpreter
>>>> (let's say from a non X-fwded ssh session) it may cause a failure. I'm
>>>> only interested in Tcl.
>>>
>>> This is a big pain for me as well. I would really like to have this fixed,
>>> as Ruby/Tcl interaction is important to me. But it hasn't been a big
>>> enough pain to try and hack around in the C code :) (yet)
>>
>> I'm more than willing to spend some time on this. But I'm new to ruby, and
>> to the tcl-C portions.
>>
>> It seems like the thing to do is be able to pass the desire for no tk in via
>> the new call:
>>
>> TclTkIp.new(notk => 1),
>>
>> It looks like tcltklib.c:ip_init() gets called. The current parameters wind
>> up being plugged into Tcl's argv0 and args. So, in keeping with the current
>> implementation perhaps something like:
>>
>> TclTkIp.new($argv0, $args, 1) would be "better"
>>
>> Where 1 represents the non-desire to load Tk.
>>
>> One would need to skip over when 1 is set.:
>>
>> /* from Tcl_AppInit() */
>> DUMP1("Tk_Init");
>> if (Tk_Init(ptr->ip) == TCL_ERROR) {
>> rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
>> }
>> DUMP1("Tcl_StaticPackage(\"Tk\")");
>> #if TCL_MAJOR_VERSION >= 8
>> Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit);
>> #else
>> Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
>> (Tcl_PackageInitProc *) NULL);
>> #endif
>
> This kind of approach has merit... however, in the current setup, simply
> doing:
>
> require 'tk'

I think I've been using the library at a lower layer. This is where I get
the problem:

[20:28:02] chapanoke:~> irb
irb(main):001:0> require 'tcltklib'
=> true
irb(main):002:0> ip = TclTkIp.new("bobo")
RuntimeError: this isn't a Tk applicationcouldn't connect to display
"chapanoke:0.0"
from (irb):2:in `initialize'
from (irb):2:in `new'
from (irb):2

I think 'tk' is probably doing a whole lot more than just loading tcltklib

>
> dies if the DISPLAY is not set. It seems a reorganization of how the
> tcltklib module is presented would be needed as well.

;-) that may well be true. I'm just guessing on the above addition. I
haven't tried anything yet.

>
> Am I missing a better way to get access to the Tcl interpreter?
>
>> ;-) yeah. I already ran into that. I've been using the ruby_fmt proc that
>> tcltk creates on init. That's just a wrapper for calling the ruby tcl
>> command.
>
> I have not been using this, but perhaps I should. The way I've been doing
> it usually leads to naming differences and confusion, like:
>
> TclFuncs = <<-EOTCL
> proc foo {args} {
> ruby {bar('$args')}
> }
> EOTCL
>
> #TclFuncs is evaled into the tcl interpreter...
>
> def bar(args)
> ...
> end
>
>
>>> You likely will have to do some creative things to get the scope that you
>>> want--Tcl can only communicate directly with class or global variables.
>>> This means if you call out to Tcl from Ruby, you will not have access to
>>> instance or local variables. It makes perfect sense, but typically
>>> requires doing some non-rubyish things to get access to what you need in
>>> Tcl.
>>
>> I don't think the importance of the above has sunk in yet. Do you mean to
>> say that in a class, I won't be able to do something like:
>>
>> Ip._eval("puts #{var}")
>
> No, because #{var} will be interpolated before the call to Tcl's eval.
>
> What I mean is that the following will not work (note that TclUtils
> provides some wrapper functionality that ultimately results in a call to
> Tk.tk_call("eval", cmd)... I didn't know about _eval which is probably what
> I should be using):

All roads eventually lead to _eval

>
> #tcl function defined as follows...
> proc some_proc {} {
> set somevar [ruby {do_something()}]
> }
>
> #and a ruby methods defined as...
> class SomeClass
> def do_something()
> ...
> return some_str
> end
>
> def some_instance_method()
> TclUtils.eval("some_proc")
> end
> end
>
> When you call some_instance_method(), and it runs the tcl proc 'some_proc',
> the Tcl interpreter is calling things at the basest level of Ruby scoping,
> so there will be no such method 'do_something' at that level.

Yes, that makes sense. And (given that you mentioned it) I see how it can
get annoying pretty quick.

> If this seemed obvious to you that such a thing wouldn't work, perhaps it
> is. But it is an ugliness you have to deal with when spanning the two
> worlds.
>
> I end up having a current_obj variable or something which can be gotten at
> with a class method at the Tcl level, i.e.:
>
> proc some_proc {} {
> set somevar [ruby {SomeClass.current_obj.do_something()}]
> }
>
> #and...
> class SomeClass
> def SomeClass.current_obj
> return @@current_obj
> end
>
> ...
>
> def some_instance_method()
> @@current_obj = self
> TclUtils.eval("some_proc")
> end
> end
>
> Ugly. Sinfully ugly. Luckily, I try to keep Ruby in control of most
> everything, and the Tcl is a configuration file, so I don't need to do this
> that often.

Aamer Akhter

10/2/2003 12:51:00 AM

0

On 10/1/03 3:32 PM, in article 3F7B2BC9.A06E6B27@engard.hu, "Ferenc Engard"
<ferenc@engard.hu> wrote:

> "Brett H. Williams" wrote:
>>
>> On Oct 1, Aamer Akhter wrote:
> [...]
>>> 2) Is there a japanese to english translation of
>>> ext/tcltklib/MANUAL.euc? Or can somebody point to a tool that I may
>>> use to do the translation? babelfish.altavista does not appear to
>>> work.
>
> I have some hungarian notes about its work... :)) Sorry. :-/
>
>> for Ruby/Tk. Access to the Tcl interpreter through it is a side effect--a
>> highly useful side effect for me and you, but nevertheless not really
>
> And me :)
>
>>> 3). Are there any examples of ruby methods being called from the tcl
>>> code running inside the interpreter?
>
> You can register ruby proc objects into tcl and use it. However, it is a
> bit though to understand.
>
> Actually, there is a ruby_fmt proc which is buggy, but it is extensively
> used by tcltklib. Here is a patch for 1.6.7, but I do not think that it
> has changed since then...

It looks like 1.8 has this.

Your example does bring up a problem that I'll probably have to deal with
pretty quickly if this transition is going to work. Is there any work done
with regards to converting tcl hashes to ruby hashes (probably not), tcl
"lists" to ruby array's and tclX keyedlists to ruby hashes.

>
> --------------------------------------------------------------------
> --- tcltk.old.rb 2002-02-07 02:53:30.000000000 +0100
> +++ tcltk_jav.rb 2003-01-07 02:36:04.000000000 +0100
> @@ -93,9 +93,9 @@
> # ruby_fmt command format arguments by `format' and call `ruby'
> command
> # (notice ruby command receives only one argument)
> if $DEBUG
> - @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt
> $args\" ; ruby [format $fmt $args] }")
> + @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt
> $args\" ; set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }")
> else
> - @ip._eval("proc ruby_fmt {fmt args} { ruby [format $fmt $args]
> }")
> + @ip._eval("proc ruby_fmt {fmt args} { set cmd [list ruby [format
> $fmt $args]] ; uplevel $cmd }")
> end
>
> # @ip._get_eval_string(*args): generate string to evaluate in tcl
> interpreter
> --------------------------------------------------------------------
>
> Here I post a testprog of mine, ask if you cannot figure out what is
> going on...
>
> --------------------------------------------------------------------
> require "tcltk"
>
> $DEBUG=1
>
> ip=TclTkInterpreter.new
> pr=proc { |*args|
> puts "args: #{args}"
> puts "valami"
> }
> # megoldás paraméterátadásra
> # cb.to_eval: {ruby_fmt {TclTk._callcallback("c_1", "%%s")} %s}
> cb=TclTkCallback.new(ip,pr,"%s")
> puts "cb to_eval: #{cb.to_eval}"
>
> # a [format] a %%s helyére %s-t, %s helyére pedig param1-et helyettesít,
> azaz:
> # ... -command {ruby_fmt {TclTk._callcallback("c_1", "%s")} param1}
> btn1=TclTkWidget.new(ip,".","button","-text valami","-command [format ",
> cb,"param1]")
> ip.pack(btn1)
>
> TclTk.mainloop
> --------------------------------------------------------------------

Aamer Akhter

10/2/2003 1:38:00 AM

0

The following changes appear to work fine. All you need to do (for not
starting tk) is to give a non-nil value to the third arg in new:

irb(main):003:0> ip1 = TclTkIp.new("bobo",nil,1)
tcltklib: Tcl_CreateInterp
tcltklib: Tcl_Init
tcltklib: tknoload set
tcltklib: Tcl_CreateObjCommand("ruby")
=> #<TclTkIp:0x1a3678>
irb(main):004:0> ip1 = TclTkIp.new("bobo",nil,nil)
tcltklib: Tcl_CreateInterp
tcltklib: Tcl_Init
tcltklib: Tk_Init
tcltklib: Tcl_StaticPackage("Tk")
tcltklib: Tcl_CreateObjCommand("ruby")



*** bak/tcltklib.c Wed Oct 1 21:13:43 2003
--- tcltklib.c Wed Oct 1 21:30:28 2003
***************
*** 642,662 ****
return Data_Wrap_Struct(self, 0, ip_free, 0);
}

static VALUE
ip_init(argc, argv, self)
int argc;
VALUE *argv;
VALUE self;
{
struct tcltkip *ptr; /* tcltkip data struct */
! VALUE argv0, opts;
int cnt;

/* create object */
Data_Get_Struct(self, struct tcltkip, ptr);
ptr = ALLOC(struct tcltkip);
DATA_PTR(self) = ptr;
ptr->return_value = 0;

/* from Tk_Main() */
DUMP1("Tcl_CreateInterp");
--- 642,662 ----
return Data_Wrap_Struct(self, 0, ip_free, 0);
}

static VALUE
ip_init(argc, argv, self)
int argc;
VALUE *argv;
VALUE self;
{
struct tcltkip *ptr; /* tcltkip data struct */
! VALUE argv0, opts, tknoload;
int cnt;

/* create object */
Data_Get_Struct(self, struct tcltkip, ptr);
ptr = ALLOC(struct tcltkip);
DATA_PTR(self) = ptr;
ptr->return_value = 0;

/* from Tk_Main() */
DUMP1("Tcl_CreateInterp");
***************
*** 664,711 ****
Tcl_Preserve((ClientData)ptr->ip);
current_interp = ptr->ip;

/* from Tcl_AppInit() */
DUMP1("Tcl_Init");
if (Tcl_Init(ptr->ip) == TCL_ERROR) {
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}

/* set variables */
! cnt = rb_scan_args(argc, argv, "02", &argv0, &opts);
switch(cnt) {
case 2:
/* options */
! Tcl_SetVar(ptr->ip, "argv", StringValuePtr(opts), 0);
case 1:
/* argv0 */
if (argv0 != Qnil) {
Tcl_SetVar(ptr->ip, "argv0", StringValuePtr(argv0), 0);
}
case 0:
/* no args */
;
}

/* from Tcl_AppInit() */
DUMP1("Tk_Init");
if (Tk_Init(ptr->ip) == TCL_ERROR) {
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}
DUMP1("Tcl_StaticPackage(\"Tk\")");
#if TCL_MAJOR_VERSION >= 8
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit);
#else
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
(Tcl_PackageInitProc *) NULL);
#endif
!
/* add ruby command to the interpreter */
#if TCL_MAJOR_VERSION >= 8
DUMP1("Tcl_CreateObjCommand(\"ruby\")");
Tcl_CreateObjCommand(ptr->ip, "ruby", ip_ruby, (ClientData)NULL,
(Tcl_CmdDeleteProc *)NULL);
#else
DUMP1("Tcl_CreateCommand(\"ruby\")");
Tcl_CreateCommand(ptr->ip, "ruby", ip_ruby, (ClientData)NULL,
(Tcl_CmdDeleteProc *)NULL);
#endif
--- 664,720 ----
Tcl_Preserve((ClientData)ptr->ip);
current_interp = ptr->ip;

/* from Tcl_AppInit() */
DUMP1("Tcl_Init");
if (Tcl_Init(ptr->ip) == TCL_ERROR) {
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}

/* set variables */
! cnt = rb_scan_args(argc, argv, "03", &argv0, &opts, &tknoload);
switch(cnt) {
+ case 3:
+ /* do we load tk or not */
case 2:
/* options */
! if (opts != Qnil) {
! Tcl_SetVar(ptr->ip, "argv", StringValuePtr(opts), 0);
! }
case 1:
/* argv0 */
if (argv0 != Qnil) {
Tcl_SetVar(ptr->ip, "argv0", StringValuePtr(argv0), 0);
}
case 0:
/* no args */
;
}

/* from Tcl_AppInit() */
+ if ( tknoload == Qnil ) {
DUMP1("Tk_Init");
if (Tk_Init(ptr->ip) == TCL_ERROR) {
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}
DUMP1("Tcl_StaticPackage(\"Tk\")");
#if TCL_MAJOR_VERSION >= 8
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit);
#else
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
(Tcl_PackageInitProc *) NULL);
#endif
! } else {
! DUMP1("tknoload set");
! }
!
!
/* add ruby command to the interpreter */
#if TCL_MAJOR_VERSION >= 8
DUMP1("Tcl_CreateObjCommand(\"ruby\")");
Tcl_CreateObjCommand(ptr->ip, "ruby", ip_ruby, (ClientData)NULL,
(Tcl_CmdDeleteProc *)NULL);
#else
DUMP1("Tcl_CreateCommand(\"ruby\")");
Tcl_CreateCommand(ptr->ip, "ruby", ip_ruby, (ClientData)NULL,
(Tcl_CmdDeleteProc *)NULL);
#endif


How do I go about getting this code reviewed and into ruby proper? I would
appreciate any corrections or better ideas for the above.

Thanks.

Aamer Akhter
cisco Systems

Ferenc Engard

10/2/2003 8:04:00 PM

0

> I end up having a current_obj variable or something which can be gotten at
> with a class method at the Tcl level, i.e.:
>
> proc some_proc {} {
> set somevar [ruby {SomeClass.current_obj.do_something()}]
> }
>
> #and...
> class SomeClass
> def SomeClass.current_obj
> return @@current_obj
> end
>
> ...
>
> def some_instance_method()
> @@current_obj = self
> TclUtils.eval("some_proc")
> end
> end
>
> Ugly. Sinfully ugly. Luckily, I try to keep Ruby in control of most
> everything, and the Tcl is a configuration file, so I don't need to do this
> that often.

Or you can use the TclTkCallback class as I have shown in my previous
post:

class SomeClass
...
def do_something
...
return some_str
end

def some_instance_method()
pr=proc {do_something}
cb=TclTkCallback.new(ip,pr,"%s")
$interpreter._eval(cb.to_eval) # or something to eval cb.eval in the
tcl interpreter
end
end

Hidetoshi NAGAI

10/4/2003 4:56:00 PM

0

aakhter

10/4/2003 9:40:00 PM

0

Hidetoshi NAGAI <nagai@dumbo.ai.kyutech.ac.jp> wrote in message news:<20031005.015546.74755857.nagai@dumbo.ai.kyutech.ac.jp>...
> Hi,
>
> Maybe this reply mail is too late.
> # Sorry, but I was out on business trip.

Hidetoshi,

Thank-you for responding. It seems like these changes were in r1.39 of
tcltklib.c, while 1.38 was the version released with with 1.8.0. I
should have checked the CVS.

> > 1) is there a way to _not_ start tk? When I create a new interpreter
> > (let's say from a non X-fwded ssh session) it may cause a failure. I'm
> > only interested in Tcl.
>
> from ChangeLog of CVS Head,
> ----------------------------------------------
> Fri Aug 29 17:30:15 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
> (snip)
> * ext/tcltklib/tcltklib.c : can create a interpreter without Tk
> ----------------------------------------------
> Please create a Tcl interpreter by TclTkIp.new(ip_name, nil).
> 'ip_name' is the name of the interpreter which is shown with
> 'winfo interps' and so on.
> Usually, 2nd argument of TclTkIp.new method is given command
> line options of 'wish' (e.g. TclTkIp.new('FOO', '-geometry
> 500x200 -use 0x2200009') ). But if given nil or false, the
> interpreter starts without Tk.

I would suggest not using the argv parameter space for indicating the
non-desire for Tk. One might one to pass command line arguments to
tclsh ( in the same way as to wish)

>
> Unfortunately, tk.rb doesn't work with the interpreter without
> initialized Tk library. Therefore you must call TclTkIp#invoke
> or TclTkIp#eval. If you want to wrap the control script using
> such methods by Ruby's classes or modules, please refer TkCore
> or TkComm moduless on tk.rb. They may help you.
>
> BTW, there is a known bug on tcltklib.c. It causes 'Segmentation
> Fault' when 'vwait' or 'tkwait' command is called on the other
> thread than 'mainloop' thread. Those commands call Tcl_DoOneEvent()
> function. And it conflicts with the eventloop control of tcltklib.c.
> I've been working on fixing the problem. I think I must implement
> the routines to replace 'vwait' and 'tkwait'.

While I'm not an active user of vwait, tkwait and espically not
threads as they're not supported in tcl-expect, I think the TKinter
python library has worked around these type of issues see:

Modules/_tkinter.c in the regular python distribution


I would like to work with yon on improving the transferability of
lists and arrays between tcl and ruby, if you are interisted.