How to tell TCL and TK that default `.tcl` language files should be searched locally?
When you compile TCL/Tk manually from sources or just install it from ActiveState you get the following structure in your TCL/Tk installation folder:
+- bin
+- tcl85.dll
+- tk85.dll
//...
+- lib/
+- tcl8.5/
//All TCL files (.tcl)
+- tk8.5/
//All TK files (.tcl)
//...
So when you compile some app of yours and link it to TCL and TK DLL's that DLL's search for all TCL/TK files in relative to tham (to DLL's) directory ../lib/tk8.5 and ../lib/tcl8.5. This makes it quite hard to distribute your app not having to make end users install TCL and TK.
I want to distribute my C++ app.
I use CPPTK for default GUI layout.
I want to make it possible so that end users would not have need in installing TCL and TK. I want to provide them with folders with TK and TCL .TCL
source files that would be located in some directory relative to my app like extras/TCL
and extras/TK
. How to tell TK and TCL DLLs where that source file folders are? what are TK and TCL API function names for doing that? Are there any special cpptk functions for that?
Update So I tried Donal Fellows answer with next folder structure.
app/
+- app.exe
+- tcl85.dll
+- tk85.dll
+- extras/
+- tcl/
//All TCL files you can find开发者_运维问答 in TCL install folder/ lib/tcl8.5
+- tk/
//All TK files you can find in TCL install folder/ lib/tk8.5
My code looked like:
#include <stdio.h>
#include "cpptk/cpptk.h"
using namespace Tk;
int main(int, char *argv[])
{
static char* str = "set extrasDir [file dirname [info nameofexecutable]]/extras\n"
"# Now use it to load some code...\n"
"source $extrasDir/tcl/init.tcl\n"
"# Another way to load code, using all *.tk files from a directory:\n"
"foreach tkFile [glob -nocomplain -directory $extrasDir/tk *.tk] {\n"
" source $tkFile\n"
"}\n";
// This next part is in a function or method...
//std::string script("the script to evaluate goes here");
std::string result = Tk::details::Expr(str,true); // I think this is correct
std::cout<< result << std::endl;
std::cin.get();
Tk::init(argv[0]);
button(".b") -text("Say Hello");
pack(".b") -padx(20) -pady(6);
Tk::runEventLoop();
std::cin.get();
}
It compiles but failes on line 36 of cpptkbase.cc
BTW: I used this html\js app to get char string.
If you have a directory that contains your binary, and you want to locate those Tcl files relative to it, like this:
yourapp1.0/ +- yourapp.exe +- extras/ +- tcl/ +- foo.tcl +- bar.tcl +- tk/ +- grill.tk
Then you can write Tcl code to find those scripts. That code would be like this:
set extrasDir [file dirname [info nameofexecutable]]/extras
# Now use it to load some code...
source $extrasDir/tcl/foo.tcl
source $extrasDir/tcl/bar.tcl
# Another way to load code, using all *.tk files from a directory:
foreach tkFile [glob -nocomplain -directory $extrasDir/tk *.tk] {
source $tkFile
}
If you're using a script as your main program, but otherwise set up in the structure as above, you'd use $argv0
(a special global variable) instead of [info nameofexecutable]
. Or possibly [info script]
(though there are some caveats with that).
[EDIT]: To make that code work with C++/Tk, you need to be trickier. In particular, you need to access some extra guts:
#include "cpptk.h" // might need "base/cpptkbase.h" instead
#include <string>
// This next part is in a function or method...
std::string script("the script to evaluate goes here");
std::string result = Tk::details::Expr(script,true); // I think this is correct
I should warn that I don't write C++ very often so there's a fair chance that this won't work; it's just based off reading the C++/Tk source and taking a guess. Caveat emptor.
精彩评论