Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C++/Tcl/C++ Interface

550 views
Skip to first unread message

Soumen

unread,
Apr 10, 2008, 5:47:20 AM4/10/08
to
Hi,

I'm a newbie in Tcl and Tcl/C++ interfacing. I need to develop a
prototype for one
of our upcoming project.

I've a shared library which provides Tcl procedures to traverse
through some graph
which is being created upon reading a file of specific format. If I
load this shared
library in Tcl shell and call those proc to read the specific file and
traverse the graph.
Graph traversal proc are like:
* getting neighbor nodes of a given node
* getting the node name and edge names to/from a node

Let's name this Tcl library GL (graph lib).

Now, in my C++ program I need create a duplicate graph since I don't
have capability
read that file directly. So from my C++ code, I need to create a Tcl
channel, send
commands through the Tcl channel for GL procs and get information from
those GL
procs to my C++ application to build a duplicate graph on my end.

Could some one provide hints how to go about this? Any pointers to
existing resource
(doc/open source code) will be very helpful.

Please redirect me to correct group if this is not the most
appropriate one.

Regards,
~ Soumen

Ron Fox

unread,
Apr 10, 2008, 6:34:13 AM4/10/08
to
Soumen wrote:
> Hi,
>
> I'm a newbie in Tcl and Tcl/C++ interfacing. I need to develop a
> prototype for one
> of our upcoming project.
>
> I've a shared library which provides Tcl procedures to traverse
> through some graph
> which is being created upon reading a file of specific format. If I
> load this shared
> library in Tcl shell and call those proc to read the specific file and
> traverse the graph.
> Graph traversal proc are like:
> * getting neighbor nodes of a given node
> * getting the node name and edge names to/from a node
>
> Let's name this Tcl library GL (graph lib).
>
> Now, in my C++ program I need create a duplicate graph since I don't
> have capability
> read that file directly. So from my C++ code, I need to create a Tcl
> channel, send
> commands through the Tcl channel for GL procs and get information from
> those GL
> procs to my C++ application to build a duplicate graph on my end.
>

In reading your explanation, I'm confused about the actual structure of
the software... Do you have a free standing C++ program as well as the
shared library or just a shared library? Is the Tcl script, the free
standing program, or the library reading the file?

Depending on the actual structure the way you propose doing this may not
be, or is not the best way:

1. If your Tcl script must read the file, and communicate it to a C++
library: The C++ library should supply commands the script can use
to build the graph. The Tcl script uses [open] [close] [read] [gets]
as needed to read the file and decode the graph elements, and the
commands the library exports to communicate the graph to the Tcl
script. No channel needed between Tcl and C++, a Tcl channel
is needed by the Tcl scrip to read the file.

2. If your C++ library must read the file, build the graph and
communicate its structure to the Tcl script:
Your C++ library already provides graph traversal commands if I
understand your description. Add a command to the library that reads
the graph from the file, and the Tcl script builds its image of the
graph using the traversals commands already built in to the C++
library. No Tcl channels required between C++ and Tcl.

3. There's an independent Tcl script with some C++ library and an
independent C++ program that run concurrently or serially:
That all depends on the nature of the C++ and Tcl scripts.
You can use sockets, pipes, files to communicate information
betweeen the two... how you do it depends on the constraints of the
two programs.

> Could some one provide hints how to go about this? Any pointers to
> existing resource
> (doc/open source code) will be very helpful.
>

The man pages for
[open] http://www.tcl.tk/man/tcl8.4/TclCmd/open.htm
[close]http://www.tcl.tk/man/tcl8.4/TclCmd/close.htm
[gets] http://www.tcl.tk/man/tcl8.4/TclCmd/gets.htm
[read] http://www.tcl.tk/man/tcl8.4/TclCmd/read.htm

searching http://wiki.tcl.tk for almost any Tcl topic will provide an
additional wealth of information.

All have simple examples.


> Please redirect me to correct group if this is not the most
> appropriate one.
>
> Regards,
> ~ Soumen

RF

Soumen

unread,
Apr 10, 2008, 7:06:28 AM4/10/08
to
> searchinghttp://wiki.tcl.tkfor almost any Tcl topic will provide an

> additional wealth of information.
>
> All have simple examples.
>
> > Please redirect me to correct group if this is not the most
> > appropriate one.
>
> > Regards,
> > ~ Soumen
>
> RF

Hi Ron,

Say there is a text file of specific format. And the shared library
(GL)
is say a standard reader of that specific format. Now, when I load
this
GL.so in tcl shell, and call procedure to read a file of the specific
format
it internally builds a graph. I've some gl_* procedures to traverse
that
graph.

Now, my objective is from C++ program, create a tcl channel and send
commands
to read that specific file, to iterate over the graph using gl_*
procs. Get
the required information (o/p of those gl_* tcl procs) in the C++
program to
mimic the graph of Tcl env in C++ env.

For example (this is not the exact case) following file is the
specific format
and it represents an adjacency list.

a ->b ->c
b ->c
c -> a ->d
d -> a -> b

Now, in the GL.so, I've following Tcl procs:

gl_read_file ---> reads the adjacency list file
gl_get_nodes ---> returns a list of node
gl_get_node_name ---> gives node name of Tcl node obj
gl_get_neighbor_nodes ---> gives a Tcl list of adjacent nodes of a
specified node name (or Tcl node obj)
gl_get_edge ---> gives Tcl edge object connecting two node obj
gl_get_edge_name ---> gives the edge name of Tcl edge object
gl_get_out_edge ---> gives list of Tcl edge objects which are outgoing
edge of specified node.

Now, in my C++ program I need to create the same graph. But I don't
have capability of reading this file format. So what I need to do
create some tcl channel, call required gl_* Tcl proc to create
the same graph using C++ objects so that later in C++ program
I can only use the graph in C++ env to do further processing.

Hope it's clear now.

Regards,
~ Soumen

Neil Madden

unread,
Apr 10, 2008, 11:17:55 AM4/10/08
to
Soumen wrote:
...

> For example (this is not the exact case) following file is the
> specific format
> and it represents an adjacency list.
>
> a ->b ->c
> b ->c
> c -> a ->d
> d -> a -> b
>
> Now, in the GL.so, I've following Tcl procs:
>
> gl_read_file ---> reads the adjacency list file
> gl_get_nodes ---> returns a list of node
> gl_get_node_name ---> gives node name of Tcl node obj
> gl_get_neighbor_nodes ---> gives a Tcl list of adjacent nodes of a
> specified node name (or Tcl node obj)
> gl_get_edge ---> gives Tcl edge object connecting two node obj
> gl_get_edge_name ---> gives the edge name of Tcl edge object
> gl_get_out_edge ---> gives list of Tcl edge objects which are outgoing
> edge of specified node.
>
> Now, in my C++ program I need to create the same graph. But I don't
> have capability of reading this file format. So what I need to do
> create some tcl channel, call required gl_* Tcl proc to create
> the same graph using C++ objects so that later in C++ program
> I can only use the graph in C++ env to do further processing.

OK, so the C++ program is separate from the Tcl/GL.so program, and the
C++ program doesn't have access to the graph file. Is this because it
just doesn't understand the file format (in which case, why not simply
link the C++ program against GL.so)? Or is it that it is on a separate
machine or otherwise doesn't have physical access to the file?

There are many possible ways of implementing this, but it really depends
what your exact requirements are. If you are on a separate machine, then
you will likely need to use a socket: open a server socket in the Tcl
script and then connect to it from C++. If you are on the same machine,
then the easiest thing would seem to be to just link your C++ app
against GL.so and Tcl and just use it to read the file.

-- Neil

Soumen

unread,
Apr 11, 2008, 3:59:29 AM4/11/08
to

Yes, the file format is something std format and I don't want to spend
time in reinventing wheel.

The interesting part of the challenge is I don't know C/C++ APIs of
the
GL.so. The vendor of GL.so don't want to disclose C/C++ API level
details.
So even though I link my app with GL.so, I cannot do the operation in
C/C++ level.

I have access only to the Tcl commands. If I load the GL.so on tclsh,
I can
use tcl procs to read the file and traverse the graph from tcl shell.
So only
option I can think of is to establish a Tcl channel and communicate
through it.

Regards,
~ Soumen

Christian Gollwitzer

unread,
Apr 11, 2008, 4:23:02 AM4/11/08
to
Soumen schrieb:

> Yes, the file format is something std format and I don't want to spend
> time in reinventing wheel.
>
> The interesting part of the challenge is I don't know C/C++ APIs of
> the
> GL.so. The vendor of GL.so don't want to disclose C/C++ API level
> details.
> So even though I link my app with GL.so, I cannot do the operation in
> C/C++ level.
>
> I have access only to the Tcl commands. If I load the GL.so on tclsh,
> I can use tcl procs to read the file and traverse the graph from tcl shell.
> So only option I can think of is to establish a Tcl channel and communicate
> through it.

Part of the miscommunication here is that you talk about "Tcl channel",
which has a precise meaning, but probably isn't what you want and/or
mean. (In TCL a "channel" is the same as a "file descriptor" in C) If
you need to do only the same thing from C++ what you can do in Tcl, then
you just construct a tcl interpreter (look on http://wiki.tcl.tk/2074)
and call TclEval and friends from C++ to do your stuff. The other way
would be to call the interface functions like TCL does it. The only
problem now is, that you won't have access to the inner data structure
of the lib; you are restricted to calling the functions provided by the
vendor of GL.so

Christian

Soumen

unread,
Apr 11, 2008, 5:37:40 AM4/11/08
to
On Apr 11, 1:23 pm, Christian Gollwitzer <Christian.Gollwit...@uni-

bayreuth.de> wrote:
> Soumen schrieb:
>
> > Yes, the file format is something std format and I don't want to spend
> > time in reinventing wheel.
>
> > The interesting part of the challenge is I don't know C/C++ APIs of
> > the
> > GL.so. The vendor of GL.so don't want to disclose C/C++ API level
> > details.
> > So even though I link my app with GL.so, I cannot do the operation in
> > C/C++ level.
>
> > I have access only to the Tcl commands. If I load the GL.so on tclsh,
> > I can use tcl procs to read the file and traverse the graph from tcl shell.
> > So only option I can think of is to establish a Tcl channel and communicate
> > through it.
>
> Part of the miscommunication here is that you talk about "Tcl channel",
> which has a precise meaning, but probably isn't what you want and/or
> mean. (In TCL a "channel" is the same as a "file descriptor" in C)

Thanks for clarifying. And sorry for creating confusion.

> If you need to do only the same thing from C++ what you can do in Tcl, then

> you just construct a tcl interpreter (look onhttp://wiki.tcl.tk/2074)


> and call TclEval and friends from C++ to do your stuff. The other way
> would be to call the interface functions like TCL does it. The only
> problem now is, that you won't have access to the inner data structure
> of the lib; you are restricted to calling the functions provided by the
> vendor of GL.so
>

But I hope if any gl_* proc returns me Tcl list or any other "non-
string" Tcl
object handle, there's a way of extracting from it from C/C++ env.
Right?

Regards,
~ Soumen

Neil Madden

unread,
Apr 11, 2008, 6:07:33 AM4/11/08
to
Soumen wrote:
...

>> If you need to do only the same thing from C++ what you can do in Tcl, then
>> you just construct a tcl interpreter (look onhttp://wiki.tcl.tk/2074)
>> and call TclEval and friends from C++ to do your stuff. The other way
>> would be to call the interface functions like TCL does it. The only
>> problem now is, that you won't have access to the inner data structure
>> of the lib; you are restricted to calling the functions provided by the
>> vendor of GL.so
>>
>
> But I hope if any gl_* proc returns me Tcl list or any other "non-
> string" Tcl
> object handle, there's a way of extracting from it from C/C++ env.
> Right?

Yes -- see the Tcl C library interface:
http://www.tcl.tk/man/tcl8.5/TclLib/contents.htm

For instance, you can use Tcl_ListObjGetElements to get a C array of the
elements returned and then call Tcl_Get<Foo>FromObj on each element to
retrieve them in a convenient format.

Neil

Alexandre Ferrieux

unread,
Apr 11, 2008, 6:32:56 AM4/11/08
to

Alternatively, you might entirely avoid diving into the guts of Tcl by
spawning from C (fork/exec) a tclsh subprocess and doing I/O with it
through pipes. Then accessing from C/C++ is just a matter of parsing
strings written by Tcl, which is nearly trivial if you stay away from
crazy levels of {} nesting and/or quoting hell.

The performance hit may be significant (I/O + context switch) but can
be diluted by defining "bulk exchanges". For example, if in the Tcl
script you write a procedure dumping the entire graph, there will be
just a few context switches (as opposed to one exchange per node or
link). The only remaining overhead being the string parsing in C,
should be limited.

-Alex

Neil Madden

unread,
Apr 11, 2008, 6:52:53 AM4/11/08
to
Alexandre Ferrieux wrote:
...

>> Yes -- see the Tcl C library interface:http://www.tcl.tk/man/tcl8.5/TclLib/contents.htm
>>
>> For instance, you can use Tcl_ListObjGetElements to get a C array of the
>> elements returned and then call Tcl_Get<Foo>FromObj on each element to
>> retrieve them in a convenient format.
>
> Alternatively, you might entirely avoid diving into the guts of Tcl by
> spawning from C (fork/exec) a tclsh subprocess and doing I/O with it
> through pipes. Then accessing from C/C++ is just a matter of parsing
> strings written by Tcl, which is nearly trivial if you stay away from
> crazy levels of {} nesting and/or quoting hell.

This isn't "diving into the guts of Tcl", it is using the Tcl API in the
manner it was designed for. Why bother writing C++ code to parse Tcl
strings when you can just get the Tcl library to do it for you?

>
> The performance hit may be significant (I/O + context switch) but can
> be diluted by defining "bulk exchanges". For example, if in the Tcl
> script you write a procedure dumping the entire graph, there will be
> just a few context switches (as opposed to one exchange per node or
> link). The only remaining overhead being the string parsing in C,
> should be limited.

If the OP wants to go to this level of complexity, why not just parse
the original graph file format? Indeed, all this approach seems to
achieve is to trade one format for representing the graph for another
(whatever the Tcl script sends over the pipe).

-- Neil

Soumen

unread,
Apr 11, 2008, 11:57:15 AM4/11/08
to

Thanks for Tcl C API pointer. I don't have the package name
information
of GL.so. In tclsh if I load GL.so, gl_* procs work. Now, even though
I
link my test C++ application with GL.so and use some gl_* proc (say
gl_read_file) it's not able to recognize gl_* procs as valid tcl
command.
What's C-way of doing "load" of tclsh? May be that would help me.
In case I know package name, then I guess Tcl_PkgRequire might solve
my problem. Or is there a way to find the package name from GL.so?

Regards,
~ Soumen

G

Alexandre Ferrieux

unread,
Apr 12, 2008, 6:05:21 AM4/12/08
to
On Apr 11, 12:52 pm, Neil Madden <n...@cs.nott.ac.uk> wrote:
> Alexandre Ferrieux wrote:
>
> ...
>
> >> Yes -- see the Tcl C library interface:http://www.tcl.tk/man/tcl8.5/TclLib/contents.htm
>
> >> For instance, you can use Tcl_ListObjGetElements to get a C array of the
> >> elements returned and then call Tcl_Get<Foo>FromObj on each element to
> >> retrieve them in a convenient format.
>
> > Alternatively, you might entirely avoid diving into the guts of Tcl by
> > spawning from C (fork/exec) a tclsh subprocess and doing I/O with it
> > through pipes. Then accessing from C/C++ is just a matter of parsing
> > strings written by Tcl, which is nearly trivial if you stay away from
> > crazy levels of {} nesting and/or quoting hell.
>
> This isn't "diving into the guts of Tcl", it is using the Tcl API in the
> manner it was designed for. Why bother writing C++ code to parse Tcl
> strings when you can just get the Tcl library to do it for you?

Because when you don't master the details of Tcl's C interface,
"writing C++ to parse a string" is much simpler, and easier to debug
autonomously, than learning about Tcl_Objs, string reps that may or
may not be available, iterating over a Tcl list, etc.

Neil, I'm not "fighting the C interface", I'm just trying to give
advice adapted to the background of the person concerned.

> > The performance hit may be significant (I/O + context switch) but can
> > be diluted by defining "bulk exchanges". For example, if in the Tcl
> > script you write a procedure dumping the entire graph, there will be
> > just a few context switches (as opposed to one exchange per node or
> > link). The only remaining overhead being the string parsing in C,
> > should be limited.
>
> If the OP wants to go to this level of complexity, why not just parse
> the original graph file format? Indeed, all this approach seems to
> achieve is to trade one format for representing the graph for another
> (whatever the Tcl script sends over the pipe).

First, because the original format, be it text, may be horrendously
complicated (think about an nroff-to-docbook converter ;-).

Second, because this general approach goes far beyond text formats and
allows to wrap arbitrarily complex "loaders", including of binary
formats. And not only loaders: some Tcl extensions provide a useful
level of abstraction over the underlying thing, and this method allows
non-Tcl programmers to enjoy this abstraction. This could even lead
them to enjoy Tcl itself !

-Alex

Neil Madden

unread,
Apr 12, 2008, 10:42:07 AM4/12/08
to
Alexandre Ferrieux wrote:
> On Apr 11, 12:52 pm, Neil Madden <n...@cs.nott.ac.uk> wrote:
>> Alexandre Ferrieux wrote:
>>
>> ...
>>
>>>> Yes -- see the Tcl C library interface:http://www.tcl.tk/man/tcl8.5/TclLib/contents.htm
>>>> For instance, you can use Tcl_ListObjGetElements to get a C array of the
>>>> elements returned and then call Tcl_Get<Foo>FromObj on each element to
>>>> retrieve them in a convenient format.
>>> Alternatively, you might entirely avoid diving into the guts of Tcl by
>>> spawning from C (fork/exec) a tclsh subprocess and doing I/O with it
>>> through pipes. Then accessing from C/C++ is just a matter of parsing
>>> strings written by Tcl, which is nearly trivial if you stay away from
>>> crazy levels of {} nesting and/or quoting hell.
>> This isn't "diving into the guts of Tcl", it is using the Tcl API in the
>> manner it was designed for. Why bother writing C++ code to parse Tcl
>> strings when you can just get the Tcl library to do it for you?
>
> Because when you don't master the details of Tcl's C interface,
> "writing C++ to parse a string" is much simpler, and easier to debug
> autonomously, than learning about Tcl_Objs, string reps that may or
> may not be available, iterating over a Tcl list, etc.

The implication of this is that calling e.g. Tcl_GetDoubleFromObj or
Tcl_ListObjGetElements is harder than writing a Tcl parser from scratch.
That's nonsense (and if you think that, why use the Tcl C API ever?).
You don't need to know all the ins-and-outs of Tcl_Objs, internal reps
etc just to use the API.

>
> Neil, I'm not "fighting the C interface", I'm just trying to give
> advice adapted to the background of the person concerned.
>
>>> The performance hit may be significant (I/O + context switch) but can
>>> be diluted by defining "bulk exchanges". For example, if in the Tcl
>>> script you write a procedure dumping the entire graph, there will be
>>> just a few context switches (as opposed to one exchange per node or
>>> link). The only remaining overhead being the string parsing in C,
>>> should be limited.
>> If the OP wants to go to this level of complexity, why not just parse
>> the original graph file format? Indeed, all this approach seems to
>> achieve is to trade one format for representing the graph for another
>> (whatever the Tcl script sends over the pipe).
>
> First, because the original format, be it text, may be horrendously
> complicated (think about an nroff-to-docbook converter ;-).
>
> Second, because this general approach goes far beyond text formats and
> allows to wrap arbitrarily complex "loaders", including of binary
> formats. And not only loaders: some Tcl extensions provide a useful
> level of abstraction over the underlying thing, and this method allows
> non-Tcl programmers to enjoy this abstraction. This could even lead
> them to enjoy Tcl itself !

I just don't think this is a sensible idea. Tcl as a C library is very
easy to get started with, and very well designed for the most part.
Introducing extra layers of indirection doesn't seem to accomplish much.

-- Neil

Alexandre Ferrieux

unread,
Apr 12, 2008, 12:23:11 PM4/12/08
to
On Apr 12, 4:42 pm, Neil Madden <n...@cs.nott.ac.uk> wrote:
>
> The implication of this is that calling e.g. Tcl_GetDoubleFromObj or
> Tcl_ListObjGetElements is harder than writing a Tcl parser from scratch.

A full-blown Tcl parser is not needed: it often amounts to sscanf().

> That's nonsense (and if you think that, why use the Tcl C API ever?).

I don't, except for extensions (or when fixing the core of course).

> You don't need to know all the ins-and-outs of Tcl_Objs, internal reps
> etc just to use the API.

Yes but using it properly, including initialization, thread safety,
and lifecycle of objects (like the list you're iterating over), is not
necessariy objvious to the newcomer.

> I just don't think this is a sensible idea. Tcl as a C library is very
> easy to get started with, and very well designed for the most part.
> Introducing extra layers of indirection doesn't seem to accomplish much.

OK. I'll drop it here. I must be to fond of IPC and unit-testability
to see the truth, sorry.

-Alex

Soumen

unread,
Apr 15, 2008, 2:38:48 PM4/15/08
to

Hi Neil, Christian,

Sorry to bug you again. I'm facing some difficulty in sending gl_*
procs the tcl object handles properly.

Suppose gl_read_file returns graph object and gl_get_nodes needs
uses
this handle

tclsh% set grph [gl_read_file "file.adj" ]
tclsh% set nodes [gl_get_nodes $grph "a*" ]

Assume here the second command returns list of all nodes in $graph
whose name begins with 'a'.

Now, say I've done following for the first command in C++

string fileName("file.adj");
TclCommander cmd("gl_read_file") << fileName; /* http://wiki.tcl.tk/1133
--> by Benoit Goudreault-Emond */
if (cmd.invoke() == TCL_OK) {
Tcl_obj *glObj = Tcl_GetobjResult(interp);
}

Now, I'm not sure how to send this "glObj" to next "gl_get_nodes"
command and interpret its list object. Please provide me some
pointer.
I tried it in following way ... But it doesn't work. It gives me
error
same as providing following in tclsh prompt : "gl_get_nodes a*"
<-- as if
$grph is missing. Also, point me if the getting tcl list in
following way
is OK or not.

TclCommander cmd("gl_get_nodes");
string pattern("a*");
cmd << glObj << pattern;

if (cmd.invoke() == TCL_OK) {
Tcl_Obj *nodes = Tcl_GetobjResult(interp);
int numElements = 0;
if (nodes && Tcl_ListObjLength(interp_, nodes, &numElements) ==
TCL_OK) {
cout << "Number of nodes with matched pattern: " <<
numElements << endl;
}
}

Thanks in advance,

Regards,
~ Soumen

Neil Madden

unread,
Apr 15, 2008, 4:06:00 PM4/15/08
to
Soumen wrote:
...

>
> Now, say I've done following for the first command in C++
>
> string fileName("file.adj");
> TclCommander cmd("gl_read_file") << fileName; /* http://wiki.tcl.tk/1133
> --> by Benoit Goudreault-Emond */
> if (cmd.invoke() == TCL_OK) {
> Tcl_obj *glObj = Tcl_GetobjResult(interp);
> }
...

>
> TclCommander cmd("gl_get_nodes");
> string pattern("a*");
> cmd << glObj << pattern;
...

I believe you just want:

cmd << Tcl_GetString(glObj) << pattern;

Ideally the TclCommander code would understand Tcl_Objs rather than just
strings, which you can probably add by another overload:

TclCommander& operator<< (Tcl_Obj *arg)
{
push(arg);
return *this;
}

The push method already is set up to take Tcl_Objs and does the
appropriate Tcl_IncrRefCount.

-- Neil

Soumen

unread,
Apr 16, 2008, 1:20:29 AM4/16/08
to
On Apr 16, 1:06 am, Neil Madden <n...@cs.nott.ac.uk> wrote:
> Soumen wrote:
>
> ...
>
> > Now, say I've done following for the first command in C++
>
> > string fileName("file.adj");
> > TclCommander cmd("gl_read_file") << fileName; /*http://wiki.tcl.tk/1133

> > --> by Benoit Goudreault-Emond */
> > if (cmd.invoke() == TCL_OK) {
> > Tcl_obj *glObj = Tcl_GetobjResult(interp);
> > }
> ...
>
> > TclCommander cmd("gl_get_nodes");
> > string pattern("a*");
> > cmd << glObj << pattern;
>
> ...
>
> I believe you just want:
>
> cmd << Tcl_GetString(glObj) << pattern;
>
> Ideally the TclCommander code would understand Tcl_Objs rather than just
> strings, which you can probably add by another overload:
>
> TclCommander& operator<< (Tcl_Obj *arg)
> {
> push(arg);
> return *this;
>
> }
>
> The push method already is set up to take Tcl_Objs and does the
> appropriate Tcl_IncrRefCount.
>
> -- Neil

Hi Neil,

I've already tried adding the overloaded operator<< you just
mentioned
yesterday itself before this posting. But it doesn't work. I thought
may it expects it in different way.

Regards,
~ Soumen

Neil Madden

unread,
Apr 16, 2008, 6:43:59 AM4/16/08
to
Soumen wrote:
> On Apr 16, 1:06 am, Neil Madden <n...@cs.nott.ac.uk> wrote:
>> Soumen wrote:
>>
>> ...
>>
>>> Now, say I've done following for the first command in C++
>>> string fileName("file.adj");
>>> TclCommander cmd("gl_read_file") << fileName; /*http://wiki.tcl.tk/1133
>>> --> by Benoit Goudreault-Emond */

This needs to be:

TclCommander cmd(interp);
cmd("gl_read_file") << fileName;

>>> if (cmd.invoke() == TCL_OK) {
>>> Tcl_obj *glObj = Tcl_GetobjResult(interp);
>>> }

You should handle this error if the result is not TCL_OK -- i.e., return
TCL_ERROR. I'm guessing this is not your real code, however, as there a
several mistakes here (e.g. Tcl_obj should be Tcl_Obj and glObj is
scoped incorrectly).


>> ...
>>
>>> TclCommander cmd("gl_get_nodes");

Again, this should just be:

cmd("gl_get_nodes");

>>> string pattern("a*");
>>> cmd << glObj << pattern;
>> ...
>>
>> I believe you just want:
>>
>> cmd << Tcl_GetString(glObj) << pattern;
>>
>> Ideally the TclCommander code would understand Tcl_Objs rather than just
>> strings, which you can probably add by another overload:
>>
>> TclCommander& operator<< (Tcl_Obj *arg)
>> {
>> push(arg);
>> return *this;
>>
>> }
>>
>> The push method already is set up to take Tcl_Objs and does the
>> appropriate Tcl_IncrRefCount.
>>
>> -- Neil
>
> Hi Neil,
>
> I've already tried adding the overloaded operator<< you just
> mentioned
> yesterday itself before this posting. But it doesn't work. I thought
> may it expects it in different way.

In what way doesn't it work? Do you get an error message? Did you try
just using Tcl_GetString?


-- Neil

Soumen

unread,
Apr 16, 2008, 12:20:57 PM4/16/08
to
On Apr 16, 3:43 pm, Neil Madden <n...@cs.nott.ac.uk> wrote:
> Soumen wrote:
> > On Apr 16, 1:06 am, Neil Madden <n...@cs.nott.ac.uk> wrote:
> >> Soumen wrote:
>
> >> ...
>
> >>> Now, say I've done following for the first command in C++
> >>> string fileName("file.adj");
> >>> TclCommander cmd("gl_read_file") << fileName; /*http://wiki.tcl.tk/1133
> >>> --> by Benoit Goudreault-Emond */
>
> This needs to be:
>
> TclCommander cmd(interp);
> cmd("gl_read_file") << fileName;
>
> >>> if (cmd.invoke() == TCL_OK) {
> >>> Tcl_obj *glObj = Tcl_GetobjResult(interp);
> >>> }
>
> You should handle this error if the result is not TCL_OK -- i.e., return
> TCL_ERROR. I'm guessing this is not your real code, however, as there a
> several mistakes here (e.g. Tcl_obj should be Tcl_Obj and glObj is
> scoped incorrectly).
>
> >> ...
>
> >>> TclCommander cmd("gl_get_nodes");
>
> Again, this should just be:
>
> cmd("gl_get_nodes");

This was a typo here ...


>
>
>
> >>> string pattern("a*");
> >>> cmd << glObj << pattern;
> >> ...
>
> >> I believe you just want:
>
> >> cmd << Tcl_GetString(glObj) << pattern;
>
> >> Ideally the TclCommander code would understand Tcl_Objs rather than just
> >> strings, which you can probably add by another overload:
>
> >> TclCommander& operator<< (Tcl_Obj *arg)
> >> {
> >> push(arg);
> >> return *this;
>
> >> }
>
> >> The push method already is set up to take Tcl_Objs and does the
> >> appropriate Tcl_IncrRefCount.
>
> >> -- Neil
>
> > Hi Neil,
>
> > I've already tried adding the overloaded operator<< you just
> > mentioned
> > yesterday itself before this posting. But it doesn't work. I thought
> > may it expects it in different way.
>
> In what way doesn't it work? Do you get an error message? Did you try
> just using Tcl_GetString?
>
> -- Neil

Looks like I've got the cause, but not sure how to resolve it
Say, I've two different methods : readFile() and getNodesOfName() in
class say GLInterface.

class GLInterface {
public:
// ctr and dtr declarations ...

bool readFile(const std::string &filename); /* returns true if
cmdr_.invoke() returns TCL_OK */
bool getNodesOfName(const std::string &pattern); /* same as above */

private:
TclCommander cmdr_;
Tcl_Interp *intrp_;
string objStringHalde_;

}

bool
GLInterface::readFile(const std::string &name)
{
bool status = false;
if (!name.empty()) {
cmdr_("gl_read_file") << name;
if (cmdr_.invoke() == TCL_OK) {
Tcl_Obj *objHandle = Tcl_GetObjResult(intrp_);
objStringHandle_ = Tcl_GetStringFromObj(objHandle, 0);
status = true;
}
return status;
}
}

And implementation of getNodesOfName() is similar ...
bool
GLInterface::getNodesOfName(const std::string &pattern)
{
// obvious things go here

cmdr_("gl_get_nodes") << objStringHandle_ << pattern;
if (cmdr_.invoke() == TCL_OK) {
//code to get parse returned tcl list
}

return status;
}

Looks like when readFile() finishes, objStringHandle_ becomes
invalid ...
Is there a way to protect the tcl objects returned during readFile()
so that it doesn't get invalid when readFile() method gets
finished???

Regards,
~ Soumen

Neil Madden

unread,
Apr 16, 2008, 12:27:39 PM4/16/08
to
Soumen wrote:
...

Tcl_IncrRefCount(objStringHandle_) when you store it and
Tcl_DecrRefCount when you are finished with it.

-- Neil

Soumen

unread,
Apr 17, 2008, 5:40:35 AM4/17/08
to

I've tried this. But, this doesn't help. The following call in
GLInterface::getNodesOfName() still doesn't return me TCL_OK

cmdr_.invoke() == TCL_OK

but, if I place the same code inside the following if block
of GLInterface::readFile(), it works ....

if (cmdr_.invoke() == TCL_OK) {
objHandle_ = Tcl_GetObjResult(intrp_); //I've made objHandle_
member
Tcl_IncrRefCount(objHandle_);

std::string pattern("*");
cmdr_("gl_get_nodes") << objHandle_ << pattern;
if (cmdr_.invoke() == TCL_OK) {
std::cout << "Got nodes" << std::endl;
} else {
std::cout << "Still not OK!!" << std::endl;
}
status = true;
}

I've tested from a test() method that objHandle_ is now shared
object after ref count increment. And if decrement ref count
it's becoming shared.

So I don't understand why in GLInterface::getNodesOfName()
the same code doesn't work even though I increment ref count
in readFile() method.

Regards,
~ Soumen

Soumen

unread,
Apr 17, 2008, 6:01:04 AM4/17/08
to

It works now ... Incrementing ref count twice at first place
makes it work. Not sure why. I'll debug further. Anyway, thanks
for helpful suggestions.

Regards,
~ Soumen

0 new messages