Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/external/cpptcl/cpptcl.cc @ 8351

Last change on this file since 8351 was 8351, checked in by rgrieder, 13 years ago

Merged kicklib2 branch back to trunk (includes former branches ois_update, mac_osx and kicklib).

Notes for updating

Linux:
You don't need an extra package for CEGUILua and Tolua, it's already shipped with CEGUI.
However you do need to make sure that the OgreRenderer is installed too with CEGUI 0.7 (may be a separate package).
Also, Orxonox now recognises if you install the CgProgramManager (a separate package available on newer Ubuntu on Debian systems).

Windows:
Download the new dependency packages versioned 6.0 and use these. If you have problems with that or if you don't like the in game console problem mentioned below, you can download the new 4.3 version of the packages (only available for Visual Studio 2005/2008).

Key new features:

  • *Support for Mac OS X*
  • Visual Studio 2010 support
  • Bullet library update to 2.77
  • OIS library update to 1.3
  • Support for CEGUI 0.7 —> Support for Arch Linux and even SuSE
  • Improved install target
  • Compiles now with GCC 4.6
  • Ogre Cg Shader plugin activated for Linux if available
  • And of course lots of bug fixes

There are also some regressions:

  • No support for CEGUI 0.5, Ogre 1.4 and boost 1.35 - 1.39 any more
  • In game console is not working in main menu for CEGUI 0.7
  • Tolua (just the C lib, not the application) and CEGUILua libraries are no longer in our repository. —> You will need to get these as well when compiling Orxonox
  • And of course lots of new bugs we don't yet know about
  • Property svn:eol-style set to native
File size: 23.8 KB
Line 
1//
2// Copyright (C) 2004-2006, Maciej Sobczak
3//
4// Permission to copy, use, modify, sell and distribute this software
5// is granted provided this copyright notice appears in all copies.
6// This software is provided "as is" without express or implied
7// warranty, and with no claim as to its suitability for any purpose.
8//
9
10#include "cpptcl.h"
11#include <map>
12#include <sstream>
13#include <iterator>
14
15
16using namespace Tcl;
17using namespace Tcl::details;
18using namespace std;
19// boost::shared_ptr conflicts with the new std::shared_ptr
20//using namespace boost;
21
22
23result::result(Tcl_Interp *interp) : interp_(interp) {}
24
25result::operator bool() const
26{
27     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
28     
29     int val, cc;
30     cc = Tcl_GetBooleanFromObj(interp_, obj, &val);
31     if (cc != TCL_OK)
32     {
33          throw tcl_error(interp_);
34     }
35     
36     return static_cast<bool>(val);
37}
38
39result::operator double() const
40{
41     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
42     
43     double val;
44     int cc = Tcl_GetDoubleFromObj(interp_, obj, &val);
45     if (cc != TCL_OK)
46     {
47          throw tcl_error(interp_);
48     }
49     
50     return val;
51}
52
53result::operator int() const
54{
55     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
56     
57     int val, cc;
58     cc = Tcl_GetIntFromObj(interp_, obj, &val);
59     if (cc != TCL_OK)
60     {
61          throw tcl_error(interp_);
62     }
63     
64     return val;
65}
66
67result::operator long() const
68{
69     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
70     
71     long val;
72     int cc;
73     cc = Tcl_GetLongFromObj(interp_, obj, &val);
74     if (cc != TCL_OK)
75     {
76          throw tcl_error(interp_);
77     }
78     
79     return val;
80}
81
82result::operator string() const
83{
84     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
85     return Tcl_GetString(obj);
86}
87
88result::operator object() const
89{
90     return object(Tcl_GetObjResult(interp_));
91}
92
93
94void details::set_result(Tcl_Interp *interp, bool b)
95{
96     Tcl_SetObjResult(interp, Tcl_NewBooleanObj(b));
97}
98
99void details::set_result(Tcl_Interp *interp, int i)
100{
101     Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
102}
103
104void details::set_result(Tcl_Interp *interp, long i)
105{
106     Tcl_SetObjResult(interp, Tcl_NewLongObj(i));
107}
108
109void details::set_result(Tcl_Interp *interp, double d)
110{
111     Tcl_SetObjResult(interp, Tcl_NewDoubleObj(d));
112}
113
114void details::set_result(Tcl_Interp *interp, string const &s)
115{
116     Tcl_SetObjResult(interp,
117          Tcl_NewStringObj(s.data(), static_cast<int>(s.size())));
118}
119
120void details::set_result(Tcl_Interp *interp, void *p)
121{
122     ostringstream ss;
123     ss << 'p' << p;
124     string s(ss.str());
125
126     Tcl_SetObjResult(interp,
127          Tcl_NewStringObj(s.data(), static_cast<int>(s.size())));
128}
129
130void details::set_result(Tcl_Interp *interp, object const &o)
131{
132     Tcl_SetObjResult(interp, o.get_object());
133}
134
135
136void details::check_params_no(int objc, int required)
137{
138     if (objc < required)
139     {
140          throw tcl_error("Too few arguments.");
141     }
142}
143
144object details::get_var_params(Tcl_Interp *interp,
145     int objc, Tcl_Obj * CONST objv[],
146     int from, policies const &pol)
147{
148     object o;
149     if (pol.variadic_)
150     {
151          check_params_no(objc, from);
152          o.assign(objv + from, objv + objc);
153     }
154     else
155     {
156          check_params_no(objc, from + 1);
157          o.assign(objv[from]);
158     }
159
160     o.set_interp(interp);
161
162     return o;
163}
164
165
166namespace // anonymous
167{
168
169// map of polymorphic callbacks
170typedef map<string, boost::shared_ptr<callback_base> > callback_interp_map;
171typedef map<Tcl_Interp *, callback_interp_map> callback_map;
172
173callback_map callbacks;
174callback_map constructors;
175
176// map of call policies
177typedef map<string, policies> policies_interp_map;
178typedef map<Tcl_Interp *, policies_interp_map> policies_map;
179
180policies_map call_policies;
181
182// map of object handlers
183typedef map<string, boost::shared_ptr<class_handler_base> > class_interp_map;
184typedef map<Tcl_Interp *, class_interp_map> class_handlers_map;
185
186class_handlers_map class_handlers;
187
188
189// helper for finding call policies - returns true when found
190bool find_policies(Tcl_Interp *interp, string const &cmdName,
191     policies_interp_map::iterator &piti)
192{
193     policies_map::iterator pit = call_policies.find(interp);
194     if (pit == call_policies.end())
195     {
196          return false;
197     }
198     
199     piti = pit->second.find(cmdName);
200     return piti != pit->second.end();
201}
202
203extern "C"
204int object_handler(ClientData cd, Tcl_Interp *interp,
205     int objc, Tcl_Obj * CONST objv[]);
206
207// helper function for post-processing call policies
208// for both free functions (isMethod == false)
209// and class methods (isMethod == true)
210void post_process_policies(Tcl_Interp *interp, policies &pol,
211     Tcl_Obj * CONST objv[], bool isMethod)
212{
213     // check if it is a factory
214     if (!pol.factory_.empty())
215     {
216          class_handlers_map::iterator it = class_handlers.find(interp);
217          if (it == class_handlers.end())
218          {
219               throw tcl_error(
220                    "Factory was registered for unknown class.");
221          }
222
223          class_interp_map::iterator oit = it->second.find(pol.factory_);
224          if (oit == it->second.end())
225          {
226               throw tcl_error(
227                    "Factory was registered for unknown class.");
228          }
229
230          class_handler_base *chb = oit->second.get();
231
232          // register a new command for the object returned
233          // by this factory function
234          // if everything went OK, the result is the address of the
235          // new object in the 'pXXX' form
236          // - the new command will be created with this name
237
238          Tcl_CreateObjCommand(interp,
239               Tcl_GetString(Tcl_GetObjResult(interp)),
240               object_handler, static_cast<ClientData>(chb), 0);
241     }
242
243     // process all declared sinks
244     // - unregister all object commands that envelopes the pointers
245     for (vector<int>::iterator s = pol.sinks_.begin();
246          s != pol.sinks_.end(); ++s)
247     {
248          if (isMethod == false)
249          {
250               // example: if there is a declared sink at parameter 3,
251               // and the Tcl command was:
252               // % fun par1 par2 PAR3 par4
253               // then the index 3 correctly points into the objv array
254
255               int index = *s;
256               Tcl_DeleteCommand(interp, Tcl_GetString(objv[index]));
257          }
258          else
259          {
260               // example: if there is a declared sink at parameter 3,
261               // and the Tcl command was:
262               // % $p method par1 par2 PAR3 par4
263               // then the index 3 needs to be incremented
264               // in order correctly point into the 4th index of objv array
265
266               int index = *s + 1;
267               Tcl_DeleteCommand(interp, Tcl_GetString(objv[index]));
268          }
269     }
270}
271
272// actual functions handling various callbacks
273
274// generic callback handler
275extern "C"
276int callback_handler(ClientData, Tcl_Interp *interp,
277     int objc, Tcl_Obj * CONST objv[])
278{
279     callback_map::iterator it = callbacks.find(interp);
280     if (it == callbacks.end())
281     {
282          Tcl_SetResult(interp,
283               "Trying to invoke non-existent callback (wrong interpreter?)",
284               TCL_STATIC);
285          return TCL_ERROR;
286     }
287     
288     string cmdName(Tcl_GetString(objv[0]));
289     callback_interp_map::iterator iti = it->second.find(cmdName);
290     if (iti == it->second.end())
291     {
292          Tcl_SetResult(interp,
293               "Trying to invoke non-existent callback (wrong cmd name?)",
294               TCL_STATIC);
295          return TCL_ERROR;
296     }
297     
298     policies_map::iterator pit = call_policies.find(interp);
299     if (pit == call_policies.end())
300     {
301          Tcl_SetResult(interp,
302               "Trying to invoke callback with no known policies",
303               TCL_STATIC);
304          return TCL_ERROR;
305     }
306     
307     policies_interp_map::iterator piti;
308     if (find_policies(interp, cmdName, piti) == false)
309     {
310          Tcl_SetResult(interp,
311               "Trying to invoke callback with no known policies",
312               TCL_STATIC);
313          return TCL_ERROR;
314     }
315
316     policies &pol = piti->second;
317     
318     try
319     {
320          iti->second->invoke(interp, objc, objv, pol);
321
322          post_process_policies(interp, pol, objv, false);
323     }
324     catch (std::exception const &e)
325     {
326          Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
327          return TCL_ERROR;
328     }
329     catch (...)
330     {
331          Tcl_SetResult(interp, "Unknown error.", TCL_STATIC);
332          return TCL_ERROR;
333     }
334     
335     return TCL_OK;
336}
337
338// generic "object" command handler
339extern "C"
340int object_handler(ClientData cd, Tcl_Interp *interp,
341     int objc, Tcl_Obj * CONST objv[])
342{
343     // here, client data points to the singleton object
344     // which is responsible for managing commands for
345     // objects of a given type
346
347     class_handler_base *chb = reinterpret_cast<class_handler_base*>(cd);
348
349     // the command name has the form 'pXXX' where XXX is the address
350     // of the "this" object
351
352     string const str(Tcl_GetString(objv[0]));
353     istringstream ss(str);
354     char dummy;
355     void *p;
356     ss >> dummy >> p;
357
358     try
359     {
360          string methodName(Tcl_GetString(objv[1]));
361          policies &pol = chb->get_policies(methodName);
362
363          chb->invoke(p, interp, objc, objv, pol);
364
365          post_process_policies(interp, pol, objv, true);
366     }
367     catch (std::exception const &e)
368     {
369          Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
370          return TCL_ERROR;
371     }
372     catch (...)
373     {
374          Tcl_SetResult(interp, "Unknown error.", TCL_STATIC);
375          return TCL_ERROR;
376     }
377
378     return TCL_OK;
379}
380
381// generic "constructor" command
382extern "C"
383int constructor_handler(ClientData cd, Tcl_Interp *interp,
384     int objc, Tcl_Obj * CONST objv[])
385{
386     // here, client data points to the singleton object
387     // which is responsible for managing commands for
388     // objects of a given type
389
390     class_handler_base *chb = reinterpret_cast<class_handler_base*>(cd);
391
392     callback_map::iterator it = constructors.find(interp);
393     if (it == constructors.end())
394     {
395          Tcl_SetResult(interp,
396               "Trying to invoke non-existent callback (wrong interpreter?)",
397               TCL_STATIC);
398          return TCL_ERROR;
399     }
400     
401     string className(Tcl_GetString(objv[0]));
402     callback_interp_map::iterator iti = it->second.find(className);
403     if (iti == it->second.end())
404     {
405          Tcl_SetResult(interp,
406               "Trying to invoke non-existent callback (wrong class name?)",
407               TCL_STATIC);
408          return TCL_ERROR;
409     }
410     
411     policies_interp_map::iterator piti;
412     if (find_policies(interp, className, piti) == false)
413     {
414          Tcl_SetResult(interp,
415               "Trying to invoke callback with no known policies",
416               TCL_STATIC);
417          return TCL_ERROR;
418     }
419
420     policies &pol = piti->second;
421
422     try
423     {
424          iti->second->invoke(interp, objc, objv, pol);
425
426          // if everything went OK, the result is the address of the
427          // new object in the 'pXXX' form
428          // - we can create a new command with this name
429
430          Tcl_CreateObjCommand(interp,
431               Tcl_GetString(Tcl_GetObjResult(interp)),
432               object_handler, static_cast<ClientData>(chb), 0);
433     }
434     catch (std::exception const &e)
435     {
436          Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
437          return TCL_ERROR;
438     }
439     catch (...)
440     {
441          Tcl_SetResult(interp, "Unknown error.", TCL_STATIC);
442          return TCL_ERROR;
443     }
444
445     return TCL_OK;
446}
447
448} // namespace anonymous
449
450Tcl::details::no_init_type Tcl::no_init;
451
452
453policies & policies::factory(string const &name)
454{
455     factory_ = name;
456     return *this;
457}
458
459policies & policies::sink(int index)
460{
461     sinks_.push_back(index);
462     return *this;
463}
464
465policies & policies::variadic()
466{
467     variadic_ = true;
468     return *this;
469}
470
471policies Tcl::factory(string const &name)
472{
473     return policies().factory(name);
474}
475
476policies Tcl::sink(int index)
477{
478     return policies().sink(index);
479}
480
481policies Tcl::variadic()
482{
483     return policies().variadic();
484}
485
486
487class_handler_base::class_handler_base()
488{
489     // default policies for the -delete command
490     policies_["-delete"] = policies();
491}
492
493void class_handler_base::register_method(string const &name,
494     boost::shared_ptr<object_cmd_base> ocb, policies const &p)
495{
496     methods_[name] = ocb;
497     policies_[name] = p;
498}
499
500policies & class_handler_base::get_policies(string const &name)
501{
502     policies_map_type::iterator it = policies_.find(name);
503     if (it == policies_.end())
504     {
505          throw tcl_error("Trying to use non-existent policy: " + name);
506     }
507
508     return it->second;
509}
510
511
512object::object()
513     : interp_(0)
514{
515     obj_ = Tcl_NewObj();
516     Tcl_IncrRefCount(obj_);
517}
518
519object::object(bool b)
520     : interp_(0)
521{
522     obj_ = Tcl_NewBooleanObj(b);
523     Tcl_IncrRefCount(obj_);
524}
525
526object::object(char const *buf, size_t size)
527     : interp_(0)
528{
529     obj_ = Tcl_NewByteArrayObj(
530          reinterpret_cast<unsigned char const *>(buf),
531          static_cast<int>(size));
532     Tcl_IncrRefCount(obj_);
533}
534
535object::object(double d)
536     : interp_(0)
537{
538     obj_ = Tcl_NewDoubleObj(d);
539     Tcl_IncrRefCount(obj_);
540}
541
542object::object(int i)
543     : interp_(0)
544{
545     obj_ = Tcl_NewIntObj(i);
546     Tcl_IncrRefCount(obj_);
547}
548
549object::object(long l)
550     : interp_(0)
551{
552     obj_ = Tcl_NewLongObj(l);
553     Tcl_IncrRefCount(obj_);
554}
555
556object::object(char const *s)
557     : interp_(0)
558{
559     obj_ = Tcl_NewStringObj(s, -1);
560     Tcl_IncrRefCount(obj_);
561}
562
563object::object(string const &s)
564     : interp_(0)
565{
566     obj_ = Tcl_NewStringObj(s.data(), static_cast<int>(s.size()));
567     Tcl_IncrRefCount(obj_);
568}
569
570object::object(Tcl_Obj *o, bool shared)
571     : interp_(0)
572{
573     init(o, shared);
574}
575
576object::object(object const &other, bool shared)
577     : interp_(other.get_interp())
578{
579     init(other.obj_, shared);
580}
581
582void object::init(Tcl_Obj *o, bool shared)
583{
584     if (shared)
585     {
586          obj_ = o;
587     }
588     else
589     {
590          obj_ = Tcl_DuplicateObj(o);
591     }
592     Tcl_IncrRefCount(obj_);
593}
594
595object::~object()
596{
597     Tcl_DecrRefCount(obj_);
598}
599
600object & object::assign(bool b)
601{
602     Tcl_SetBooleanObj(obj_, b);
603     return *this;
604}
605
606object & object::resize(size_t size)
607{
608     Tcl_SetByteArrayLength(obj_, static_cast<int>(size));
609     return *this;
610}
611
612object & object::assign(char const *buf, size_t size)
613{
614     Tcl_SetByteArrayObj(obj_,
615          reinterpret_cast<unsigned char const *>(buf),
616          static_cast<int>(size));
617     return *this;
618}
619
620object & object::assign(double d)
621{
622     Tcl_SetDoubleObj(obj_, d);
623     return *this;
624}
625
626object & object::assign(int i)
627{
628     Tcl_SetIntObj(obj_, i);
629     return *this;
630}
631
632object & object::assign(long l)
633{
634     Tcl_SetLongObj(obj_, l);
635     return *this;
636}
637
638object & object::assign(char const *s)
639{
640     Tcl_SetStringObj(obj_, s, -1);
641     return *this;
642}
643
644object & object::assign(string const &s)
645{
646     Tcl_SetStringObj(obj_, s.data(), static_cast<int>(s.size()));
647     return *this;
648}
649
650object & object::assign(object const &other)
651{
652     object(other).swap(*this);
653     return *this;
654}
655
656object & object::assign(Tcl_Obj *o)
657{
658     object(o).swap(*this);
659     return *this;
660}
661
662object & object::swap(object &other)
663{
664     std::swap(obj_, other.obj_);
665     std::swap(interp_, other.interp_);
666     return *this;
667}
668
669template <>
670bool object::get<bool>(interpreter &i) const
671{
672     int retVal;
673     int res = Tcl_GetBooleanFromObj(i.get(), obj_, &retVal);
674     if (res != TCL_OK)
675     {
676          throw tcl_error(i.get());
677     }
678
679     return static_cast<bool>(retVal);
680}
681
682template <>
683vector<char> object::get<vector<char> >(interpreter &) const
684{
685     size_t size;
686     char const *buf = get(size);
687     return vector<char>(buf, buf + size);
688}
689
690template <>
691double object::get<double>(interpreter &i) const
692{
693     double retVal;
694     int res = Tcl_GetDoubleFromObj(i.get(), obj_, &retVal);
695     if (res != TCL_OK)
696     {
697          throw tcl_error(i.get());
698     }
699
700     return retVal;
701}
702
703template <>
704int object::get<int>(interpreter &i) const
705{
706     int retVal;
707
708     int res = Tcl_GetIntFromObj(i.get(), obj_, &retVal);
709     if (res != TCL_OK)
710     {
711          throw tcl_error(i.get());
712     }
713
714     return retVal;
715}
716
717template <>
718long object::get<long>(interpreter &i) const
719{
720     long retVal;
721     int res = Tcl_GetLongFromObj(i.get(), obj_, &retVal);
722     if (res != TCL_OK)
723     {
724          throw tcl_error(i.get());
725     }
726
727     return retVal;
728}
729
730template <>
731char const * object::get<char const *>(interpreter &) const
732{
733     return get();
734}
735
736template <>
737string object::get<string>(interpreter &) const
738{
739     int len;
740     char const *buf = Tcl_GetStringFromObj(obj_, &len);
741     return string(buf, buf + len);
742}
743
744char const * object::get() const
745{
746     return Tcl_GetString(obj_);
747}
748
749char const * object::get(size_t &size) const
750{
751     int len;
752     unsigned char *buf = Tcl_GetByteArrayFromObj(obj_, &len);
753     size = len;
754     return const_cast<char const *>(reinterpret_cast<char *>(buf));
755}
756
757size_t object::length(interpreter &i) const
758{
759     int len;
760     int res = Tcl_ListObjLength(i.get(), obj_, &len);
761
762     if (res != TCL_OK)
763     {
764          throw tcl_error(i.get());
765     }
766
767     return static_cast<size_t>(len);
768}
769
770object object::at(interpreter &i, size_t index) const
771{
772     Tcl_Obj *o;
773     int res = Tcl_ListObjIndex(i.get(), obj_, static_cast<int>(index), &o);
774     if (res != TCL_OK)
775     {
776          throw tcl_error(i.get());
777     }
778     if (o == NULL)
779     {
780          throw tcl_error("Index out of range.");
781     }
782
783     return object(o);
784}
785
786object & object::append(interpreter &i, object const &o)
787{
788     int res = Tcl_ListObjAppendElement(i.get(), obj_, o.obj_);
789     if (res != TCL_OK)
790     {
791          throw tcl_error(i.get());
792     }
793
794     return *this;
795}
796
797object & object::append_list(interpreter &i, object const &o)
798{
799     int res = Tcl_ListObjAppendList(i.get(), obj_, o.obj_);
800     if (res != TCL_OK)
801     {
802          throw tcl_error(i.get());
803     }
804
805     return *this;
806}
807
808object & object::replace(interpreter &i, size_t index, size_t count,
809     object const &o)
810{
811     int res = Tcl_ListObjReplace(i.get(), obj_,
812          static_cast<int>(index), static_cast<int>(count),
813          1, &(o.obj_));
814     if (res != TCL_OK)
815     {
816          throw tcl_error(i.get());
817     }
818
819     return *this;
820}
821
822object & object::replace_list(interpreter &i, size_t index, size_t count,
823     object const &o)
824{
825     int objc;
826     Tcl_Obj **objv;
827
828     int res = Tcl_ListObjGetElements(i.get(), o.obj_, &objc, &objv);
829     if (res != TCL_OK)
830     {
831          throw tcl_error(i.get());
832     }
833
834     res = Tcl_ListObjReplace(i.get(), obj_,
835          static_cast<int>(index), static_cast<int>(count),
836          objc, objv);
837     if (res != TCL_OK)
838     {
839          throw tcl_error(i.get());
840     }
841
842     return *this;
843}
844
845void object::set_interp(Tcl_Interp *interp)
846{
847     interp_ = interp;
848}
849
850Tcl_Interp * object::get_interp() const
851{
852     return interp_;
853}
854
855
856interpreter::interpreter()
857{
858     interp_ =  Tcl_CreateInterp();
859     owner_ = true;
860}
861
862interpreter::interpreter(Tcl_Interp *interp, bool owner)
863{
864     interp_ =  interp;
865     owner_ = owner;
866}
867
868interpreter::~interpreter()
869{
870     if (owner_)
871     {
872          // clear all callback info belonging to this interpreter
873          clear_definitions(interp_);
874
875          Tcl_DeleteInterp(interp_);
876     }
877}
878
879void interpreter::make_safe()
880{
881     int cc = Tcl_MakeSafe(interp_);
882     if (cc != TCL_OK)
883     {
884          throw tcl_error(interp_);
885     }
886}
887
888result interpreter::eval(string const &script)
889{
890     int cc = Tcl_Eval(interp_, script.c_str());
891     if (cc != TCL_OK)
892     {
893          throw tcl_error(interp_);
894     }
895 
896     return result(interp_);
897}
898
899result interpreter::eval(istream &s)
900{
901     string str(
902          istreambuf_iterator<char>(s.rdbuf()),
903          istreambuf_iterator<char>()
904     );
905     return eval(str);
906}
907
908result interpreter::eval(object const &o)
909{
910     int cc = Tcl_EvalObjEx(interp_, o.get_object(), 0);
911     if (cc != TCL_OK)
912     {
913          throw tcl_error(interp_);
914     }
915 
916     return result(interp_);
917}
918
919void interpreter::pkg_provide(string const &name, string const &version)
920{
921     int cc = Tcl_PkgProvide(interp_, name.c_str(), version.c_str());
922     if (cc != TCL_OK)
923     {
924          throw tcl_error(interp_);
925     }
926}
927
928void interpreter::create_alias(string const &cmd,
929     interpreter &targetInterp, string const &targetCmd)
930{
931     int cc = Tcl_CreateAlias(interp_, cmd.c_str(),
932          targetInterp.interp_, targetCmd.c_str(), 0, 0);
933     if (cc != TCL_OK)
934     {
935          throw tcl_error(interp_);
936     }
937}
938
939void interpreter::clear_definitions(Tcl_Interp *interp)
940{
941     // delete all callbacks that were registered for given interpreter
942
943     {
944          callback_map::iterator it = callbacks.find(interp);
945          if (it == callbacks.end())
946          {
947               // no callbacks defined for this interpreter
948               return;
949          }
950
951          callback_interp_map &imap = it->second;
952          for (callback_interp_map::iterator it2 = imap.begin();
953               it2 != imap.end(); ++it2)
954          {
955               Tcl_DeleteCommand(interp, it2->first.c_str());
956          }
957
958          callbacks.erase(interp);
959     }
960
961     // delete all constructors
962
963     {
964          callback_map::iterator it = constructors.find(interp);
965          if (it == constructors.end())
966          {
967               // no callbacks defined for this interpreter
968               return;
969          }
970
971          callback_interp_map &imap = it->second;
972          for (callback_interp_map::iterator it2 = imap.begin();
973               it2 != imap.end(); ++it2)
974          {
975               Tcl_DeleteCommand(interp, it2->first.c_str());
976          }
977
978          callbacks.erase(interp);
979     }
980
981     // delete all call policies
982
983     call_policies.erase(interp);
984
985     // delete all object handlers
986     // (we have to assume that all living objects were destroyed,
987     // otherwise Bad Things will happen)
988
989     class_handlers.erase(interp);
990}
991
992void interpreter::add_function(string const &name,
993     boost::shared_ptr<callback_base> cb, policies const &p)
994{
995     Tcl_CreateObjCommand(interp_, name.c_str(),
996          callback_handler, 0, 0);
997     
998     callbacks[interp_][name] = cb;
999     call_policies[interp_][name] = p;
1000}
1001
1002void interpreter::add_class(string const &name,
1003     boost::shared_ptr<class_handler_base> chb)
1004{
1005     class_handlers[interp_][name] = chb;
1006}
1007
1008void interpreter::add_constructor(string const &name,
1009     boost::shared_ptr<class_handler_base> chb, boost::shared_ptr<callback_base> cb,
1010     policies const &p)
1011{
1012     Tcl_CreateObjCommand(interp_, name.c_str(),
1013          constructor_handler, static_cast<ClientData>(chb.get()), 0);
1014
1015     constructors[interp_][name] = cb;
1016     call_policies[interp_][name] = p;
1017}
1018
1019
1020int tcl_cast<int>::from(Tcl_Interp *interp, Tcl_Obj *obj)
1021{
1022     int res;
1023     int cc = Tcl_GetIntFromObj(interp, obj, &res);
1024     if (cc != TCL_OK)
1025     {
1026          throw tcl_error(interp);
1027     }
1028     
1029     return res;
1030}
1031
1032long tcl_cast<long>::from(Tcl_Interp *interp, Tcl_Obj *obj)
1033{
1034     long res;
1035     int cc = Tcl_GetLongFromObj(interp, obj, &res);
1036     if (cc != TCL_OK)
1037     {
1038          throw tcl_error(interp);
1039     }
1040     
1041     return res;
1042}
1043
1044bool tcl_cast<bool>::from(Tcl_Interp *interp, Tcl_Obj *obj)
1045{
1046     int res;
1047     int cc = Tcl_GetBooleanFromObj(interp, obj, &res);
1048     if (cc != TCL_OK)
1049     {
1050          throw tcl_error(interp);
1051     }
1052     
1053     return res != 0;
1054}
1055
1056double tcl_cast<double>::from(Tcl_Interp *interp, Tcl_Obj *obj)
1057{
1058     double res;
1059     int cc = Tcl_GetDoubleFromObj(interp, obj, &res);
1060     if (cc != TCL_OK)
1061     {
1062          throw tcl_error(interp);
1063     }
1064     
1065     return res;
1066}
1067
1068string tcl_cast<string>::from(Tcl_Interp *, Tcl_Obj *obj)
1069{
1070     return Tcl_GetString(obj);
1071}
1072
1073char const * tcl_cast<char const *>::from(Tcl_Interp *, Tcl_Obj *obj)
1074{
1075     return Tcl_GetString(obj);
1076}
1077
1078object tcl_cast<object>::from(Tcl_Interp *interp, Tcl_Obj *obj)
1079{
1080     object o(obj);
1081     o.set_interp(interp);
1082
1083     return o;
1084}
Note: See TracBrowser for help on using the repository browser.