Updated 2012-07-09 14:33:08 by wsong

gary thomson When it comes to embedding Tcl in C/C++ what would be the best way in which to run an entire Tcl script, as opposed to a single command (as shown in Maciej's documentation)? - Just open the file, read it in, and execute the lines in the script? Or is there some other way which I have missed?

Richard Suchenwirth 2004-11-23 - The very generic name stands for "A C++ library for interoperability between C++ and Tcl" by Maciej Sobczak, based on the Boost project. On SourceForge it goes under the name cpptcl at http://cpptcl.sourceforge.net/.

LV So is this cpptcl different from what is documented on this wiki page - cpptcl? RS: Yes - that's the risk with too-generic names... The software I discuss here was only announced on 2004-11-22, but looks pretty powerful.

It "was inspired by the Boost.Python library and was designed to provide a similar interface"... "The C++/Tcl library depends on the Tcl core library and on the Boost library (see http://www.boost.org/ ). Any recent version of these two should work fine."

The documentation (one could also call it a tutorial) makes a good impression - it looks as if combining C++ and Tcl, both for making shared libraries and embedded interpreters, go very easy, for instance compared to SWIG.

Here's (untested, but drawing from the documentation) how to make a shared library with two commands (that both are served by the same C++ function):
#include "cpptcl.h"

int sum(int a, int b) {return a + b;}

CPPTCL_MODULE(Example, i) {

$ tclsh
% load ./example.so
% + 3 4

Has anybody made practical experiences with this? Especially on Windows? According to the Boost site, it should be possible.

MAK (11 Oct 2004) - Looks very interesting. The code (both for cpptcl its self and how you use it) seem very nicely compact. cpptk also looks very interesting. I'm curious how much overhead the Boost library would add, though; I'll have to look into that. Two things I don't see from the documentation, though:

  1. What's the license?
  2. How would you create a function that can take a variable number of arguments (a la widget configuration parameters)?

snichols The documentation looks very strait forward. So, I thought I would try compiling the hello example Tcl extension for Windows. However, there are some header files and library dependencies, and I do not know where to get these. Its looking for something called boost/shared_ptr.hpp and a couple other dependencies. - RS: Scott, that dependency on Boost from http://www.boost.com/ is documented even on this page :^)

snichols Thanks for the info on Boost. I'll try including the headers and give the hello example another try. I think I would have use for this. It appears to simplify some of the Tcl to C++/C library programming and would be handy for small C++ Tcl extensions, like ones I have written in the past.


Ok, this is what I have found out from compiling the sample hello world C++/Tcl extension under Windows. The code will not compile with Microsoft Visual Studio 6 because of this error, "template class has already been defined as a non-template class." Microsoft has confirmed that their older VC++ 6.0 compiler does not support this (the template thing), but luckily their newer 2003 C++ compiler does. So, I downloaded and installed the free Microsoft C++ 2003 Toolkit to compile this from Microsoft's web site. It does compile ok, but I get the following link error when compiling and linking with cl (MS 2003 C++ Compiler):
 cl main.cpp cpptcl.cpp /I C:/Tcl/Include /I C:/Programming/boost_1_32_0 /I C:/Downloads/TCL/cpptcl-1.0.0 /link /dll c:/Tcl/lib/Tcl84.lib

 Generates Code OK
 Following Link Error Returned:

 "main.obj : error LNK2019: unresolved external symbol "void __cdecl boost::throw_exception(class exception const &)" ([email protected]@@YAXABVexception@@@Z) referenced in function "public: __this
        call boost::detail::shared_count::shared_count<class Tcl::details::callback0<void> *,struct boost::checked_deleter<class Tcl::details::callback0<void> > >(class Tcl::details::callback0<void> *,struct
        boost::checked_deleter<class Tcl::details::callback0<void> >)" ([email protected]@[email protected]@@[email protected][email protected]@[email protected]@@@boost@@@[email protected]@boost@@[email protected]?$callback0
        @[email protected]@Tcl@@[email protected][email protected]@[email protected]@@@2@@Z)"

Thanks for the help with my link error (above) in advance. Once I get through the link error, I feel good that I can port some of my previous Tcl C++ extension to use this, and write some new ones. Is my cl command line missing a lib file or something? I have only included the one Tcl84.lib.


Well, I was able to compile and link the hello world example. I added /EHs to the compiler options. Which basically tells the compiler to ignore unhandled exceptions. The winning MS C++ 2003 command line syntax was:
 cl main.cpp cpptcl.cpp /EHs /I C:/Tcl/Include /I C:/Programming/boost_1_32_0 /I C:/Downloads/TCL/cpptcl-1.0.0 /LD c:/Tcl/lib/Tcl84.lib

NOTE: The include and lib paths above are unique to my computer I would assume. You will need to change these to match where you downloaded and placed these files. Now, I get the following load error when loading in the library in Tcl:

load C:/Programming/C++/CplusplusTcl/main.dll couldn't find procedure Main_Init

Do I need to include the Tcl Init function even though its not used under Windows?

snichols Well after a little expermintation I finally got the Hello World! example working in Windows. The only thing I had to add was the extern "C" command below. My DLL was called Main.dll (I wouldn't recommend this name. I used it for testing only). Tcl, uses the file name to look for the Initialize function in Tcl. The other thing I noticed too is that the console out didn't appear in the Wish interp, but did appear in a Tclsh interp. Also, remember that this will not compile with Visual Studio 6, you need MS 2003 C++ to compile this.
 /* Microsoft Windows Hello World Example */
 /* Compiled using MS 2003 C++ Tool Kit */
 /* Console out only appeared in Tclsh. */
 /* Does not appear in Wish for some reason */
 /* Compiled File Name: Main.dll */
 /* Scott Nichols */
 #include "cpptcl.h"
 #include <iostream>

 using namespace std;

 extern "C"
   __declspec(dllexport) int Main_Init(Tcl_Interp* interp);


 void hello()
     cout << "Hello C++/Tcl!" << endl;

     i.def("hello", hello);

snichols I have been trying out the C++/Tcl library and it looks very promising. Iniatilly, I have compiled the samples added some new test functions that are not inline functions, but still part of the class. I am planning on converting a couple of my Tcl extensions I have written in the past, and have a feeling the new sources will be much shorter then going through the standard C/Tcl interface. A couple things I would like to see added that should make this extension very popular include:

1. Tcl Package Provide. This will allow extension programmers to generate pkindex.tcl scripts and use, "package require <insert name>" instead of the load command. This is more generic then having to put the file path to where the actual library file is located.

2. Support for Tcl stub libraries. This will make any custom extensions written with C++/Tcl backwards compatible with future versions of Tcl. An advantage of stub libraries is that the extension authors do not have to recompile their sources when a newer version of Tcl is used.

3. Support for overloaded functions. This will allow for C++ functions with the same name but with different signatures to be called from Tcl. I am especially interested in overloaded constructors. Overloaded constructors would allow for the Tcl programmer to create the object different ways. Which is a common implentation of overloading.

4. How to return Tcl Error.

RS: #4 seems to be covered already - just throw an exception... #3 seems difficult, as overloaded functions are distinguished by their signature - you might have
 int foo(char* string);
 int foo(int i);
 int foo(double d);

Now if you call [foo 5] from Tcl, "5" is both a string and an int, and can easily be coerced into a double, too...

snichols Thanks for the tip about #4. I'll try throwing an exception. Regarding #5, overloading, I am mostly interested in functions of the same name but with a different number of arguments. On Sourceforge's features request page, Maciej Sobczak the extension author, says this is listed as one of the the features he wants to add. I am interested in what he comes up with in regards to overloading.

One thing I noticed about the C++/Tcl extension that looks very nice is not having to program a big switch statment in C for the different types of arguments passed into the extension. You simply expose functions to Tcl using the i.def calls from C++. Not having to program a large switch statement makes the code more compact.

Maciej Sobczak - The C++/Tcl library depends on some of header-only Boost libraries. This means that it is enough to download Boost, unpack it somewhere and add that path to the compiler's include search path. No compilation of Boost is required. The license is stated in each source file, but will be soon stated more explicitly. It is extremely permissive, anyway.
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.

Robert J. Peters' GroovX [1] package makes for an interesting comparison [2].

See also CABLE [3]

I did try to use this, set up boost includes, tcl lib and tcl include path. Unfortunately it seams not so easy to use this. Could someone please try to update this instructions to get it working with Visual Studio 2005?

[wiwat] - Successfully run it on Ubuntu and Windows 7 with Visual Studio 10. A little tweak on extern "C" as mentioned above is needed for Windows. Will work on package provide. cpptcl is quite old. It needs update.

[wsong83] - Due to the needs of my own project, I have cloned C++/Tcl to github [4]. It is expanded with some more features: 1. When defining a Tcl command, a pointer pointing to a user data is allowed to be passed to the command as the last argument. 2. It is now able to define and remove write and read trace functions to Tcl variables. Minor: extern "C" is added in cpptcl.h so the little tweak in Vistual Studio should be saved. Also namespace conflicts in new GNU C++ compilers are resolved (eg. std::shared_ptr and boost::shared_ptr).