Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/kicklib2/src/external/cpptcl/cpptcl.cc @ 8298

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

Fixed build for MSVC 10: disabling the C++0x features seems a bad idea because some boost code relies on it for the new Visual Studio version.
Leaving it enabled breaks cpptcl though —> fixed.

  • 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.