Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/TclBind.cc @ 3307

Last change on this file since 3307 was 3307, checked in by landauf, 15 years ago

Completely rewrote TclThreadManager. This fixes several bugs from the initial implementation. The main features work fine now, but some tasks are still open (for example destroying a thread or implementing a queue size limit).

I hope this doesn't cause any troubles because I used the TclThreadManager-version from netp6 as a draft for the reimplementation. I've also applied the c-style-cast-fixes from core.

I tested this with boost 1.37, I hope it also works with 1.35 (I haven't seen any remarkable changes in the log). However it won't work with boost 1.34.1 and lower, but this change already happened back in netp6, so please update your dependencies if you're still using an old version (the current release is 1.39 btw).

  • Property svn:eol-style set to native
File size: 5.7 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "TclBind.h"
30
31#include <exception>
32#include <string>
33#include <cpptcl/cpptcl.h>
34
35#include "util/Debug.h"
36#include "util/StringUtils.h"
37#include "CommandExecutor.h"
38#include "ConsoleCommand.h"
39#include "TclThreadManager.h"
40
41namespace orxonox
42{
43    SetConsoleCommandShortcut(TclBind, tcl);
44    SetConsoleCommandShortcut(TclBind, bgerror);
45
46    TclBind* TclBind::singletonRef_s = 0;
47
48    TclBind::TclBind(const std::string& datapath)
49    {
50        assert(singletonRef_s == 0);
51        singletonRef_s = this;
52        this->interpreter_ = 0;
53        this->bSetTclLibPath_ = false;
54        this->setDataPath(datapath);
55    }
56
57    TclBind::~TclBind()
58    {
59        if (this->interpreter_)
60            delete this->interpreter_;
61        singletonRef_s = 0;
62    }
63
64    void TclBind::setDataPath(const std::string& datapath)
65    {
66        // String has POSIX slashes
67        this->tclLibPath_ = datapath + "tcl" + TCL_VERSION + '/';
68        this->bSetTclLibPath_ = true;
69
70        this->createTclInterpreter();
71    }
72
73    void TclBind::createTclInterpreter()
74    {
75        if (this->bSetTclLibPath_ && !this->interpreter_)
76        {
77            this->interpreter_ = new Tcl::interpreter(this->tclLibPath_);
78            this->interpreter_->def("orxonox::query", TclBind::tcl_query, Tcl::variadic());
79            this->interpreter_->def("orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
80            this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
81            this->interpreter_->def("orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
82
83            try
84            {
85                this->interpreter_->eval("proc query args { orxonox::query [join $args] }");
86                this->interpreter_->eval("proc crossquery {id args} { orxonox::crossquery 0 $id [join $args] }");
87                this->interpreter_->eval("proc crossexecute {id args} { orxonox::crossquery 0 $id [join $args] }");
88                this->interpreter_->eval("set id 0");
89                this->interpreter_->eval("rename exit tcl::exit; proc exit {} { execute exit }");
90                this->interpreter_->eval("redef_puts");
91            }
92            catch (Tcl::tcl_error const &e)
93            {   COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl;   }
94            catch (std::exception const &e)
95            {   COUT(1) << "Error while creating Tcl-interpreter: " << e.what() << std::endl;   }
96        }
97    }
98
99    void TclBind::createNewTclInterpreter()
100    {
101        if (this->interpreter_)
102        {
103            delete this->interpreter_;
104            this->interpreter_ = 0;
105        }
106
107        this->createTclInterpreter();
108    }
109
110    std::string TclBind::tcl_query(Tcl::object const &args)
111    {
112        COUT(4) << "Tcl_query: " << args.get() << std::endl;
113
114        std::string command = stripEnclosingBraces(args.get());
115
116        if (!CommandExecutor::execute(command, false))
117        {
118            COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
119        }
120
121        if (CommandExecutor::getLastEvaluation().hasReturnvalue())
122            return CommandExecutor::getLastEvaluation().getReturnvalue().getString();
123
124        return "";
125    }
126
127    void TclBind::tcl_execute(Tcl::object const &args)
128    {
129        COUT(4) << "Tcl_execute: " << args.get() << std::endl;
130        std::string command = stripEnclosingBraces(args.get());
131
132        if (!CommandExecutor::execute(command, false))
133        {
134            COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
135        }
136    }
137
138    std::string TclBind::tcl(const std::string& tclcode)
139    {
140        if (TclBind::getInstance().interpreter_)
141        {
142            try
143            {
144                std::string output = TclBind::getInstance().interpreter_->eval(tclcode);
145                if (output != "")
146                {
147                    COUT(0) << "tcl> " << output << std::endl;
148                }
149                return output;
150            }
151            catch (Tcl::tcl_error const &e)
152            {   COUT(1) << "tcl> Error: " << e.what() << std::endl;   }
153            catch (std::exception const &e)
154            {   COUT(1) << "Error while executing Tcl: " << e.what() << std::endl;   }
155        }
156
157        return "";
158    }
159
160    void TclBind::bgerror(std::string error)
161    {
162        COUT(1) << "Tcl background error: " << stripEnclosingBraces(error) << std::endl;
163    }
164
165    bool TclBind::eval(const std::string& tclcode)
166    {
167        try
168        {
169            TclBind::getInstance().interpreter_->eval(tclcode);
170            return true;
171        }
172        catch (Tcl::tcl_error const &e)
173        {   COUT(1) << "Tcl error: " << e.what() << std::endl;   }
174        catch (std::exception const &e)
175        {   COUT(1) << "Error while executing Tcl: " << e.what() << std::endl;   }
176
177        return false;
178    }
179}
Note: See TracBrowser for help on using the repository browser.