Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/network/src/cpptcl/CppTcl.h @ 1494

Last change on this file since 1494 was 1494, checked in by rgrieder, 16 years ago
  • set the svn:eol-style property to all files so, that where ever you check out, you'll get the right line endings (had to change every file with mixed endings to windows in order to set the property)
  • Property svn:eol-style set to native
File size: 27.4 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#ifndef CPPTCL_INCLUDED
11#define CPPTCL_INCLUDED
12
13#include <tcl.h>
14#include <string>
15#include <stdexcept>
16#include <sstream>
17#include <map>
18#include <vector>
19#include <boost/shared_ptr.hpp>
20#include <boost/bind.hpp>
21
22
23namespace Tcl
24{
25
26// exception class used for reporting all Tcl errors
27
28class tcl_error : public std::runtime_error
29{
30public:
31     explicit tcl_error(std::string const &msg)
32          : std::runtime_error(msg) {}
33     explicit tcl_error(Tcl_Interp *interp)
34          : std::runtime_error(Tcl_GetString(Tcl_GetObjResult(interp))) {}
35};
36
37// call policies
38
39struct policies
40{
41     policies() : variadic_(false) {}
42
43     policies & factory(std::string const &name);
44
45     // note: this is additive
46     policies & sink(int index);
47
48     policies & variadic();
49
50     std::string factory_;
51     std::vector<int> sinks_;
52     bool variadic_;
53};
54
55// syntax short-cuts
56policies factory(std::string const &name);
57policies sink(int index);
58policies variadic();
59
60
61class interpreter;
62class object;
63
64namespace details
65{
66
67// wrapper for the evaluation result
68class result
69{
70public:
71     result(Tcl_Interp *interp);
72
73     operator bool() const;
74     operator double() const;
75     operator int() const;
76     operator long() const;
77     operator std::string() const;
78     operator object() const;
79
80private:
81     Tcl_Interp *interp_;
82};
83
84// helper functions used to set the result value
85
86void set_result(Tcl_Interp *interp, bool b);
87void set_result(Tcl_Interp *interp, int i);
88void set_result(Tcl_Interp *interp, long i);
89void set_result(Tcl_Interp *interp, double d);
90void set_result(Tcl_Interp *interp, std::string const &s);
91void set_result(Tcl_Interp *interp, void *p);
92void set_result(Tcl_Interp *interp, object const &o);
93
94// helper functor for converting Tcl objects to the given type
95#include "details/conversions.h"
96
97// dispatchers able to capture (or ignore) the result
98#include "details/dispatchers.h"
99
100// helper for checking for required number of parameters
101// (throws tcl_error when not met)
102void check_params_no(int objc, int required);
103
104// helper for gathering optional params in variadic functions
105object get_var_params(Tcl_Interp *interp,
106     int objc, Tcl_Obj * CONST objv[],
107     int from, policies const &pol);
108
109// the callback_base is used to store callback handlers in a polynorphic map
110class callback_base
111{
112public:
113     virtual ~callback_base() {}
114
115     virtual void invoke(Tcl_Interp *interp,
116          int objc, Tcl_Obj * CONST objv[],
117          policies const &pol) = 0;
118};
119
120
121// base class for object command handlers
122// and for class handlers
123class object_cmd_base
124{
125public:
126     // destructor not needed, but exists to shut up the compiler warnings
127     virtual ~object_cmd_base() {}
128
129     virtual void invoke(void *p, Tcl_Interp *interp,
130          int objc, Tcl_Obj * CONST objv[],
131          policies const &pol) = 0;
132};
133
134// base class for all class handlers, still abstract
135class class_handler_base : public object_cmd_base
136{
137public:
138     typedef std::map<std::string, policies> policies_map_type;
139
140     class_handler_base();
141
142     void register_method(std::string const &name,
143          boost::shared_ptr<object_cmd_base> ocb, policies const &p);
144
145     policies & get_policies(std::string const &name);
146
147protected:
148     typedef std::map<
149          std::string,
150          boost::shared_ptr<object_cmd_base>
151          > method_map_type;
152
153     // a map of methods for the given class
154     method_map_type methods_;
155
156     policies_map_type policies_;
157};
158
159// class handler - responsible for executing class methods
160template <class C>
161class class_handler : public class_handler_base
162{
163public:
164     virtual void invoke(void *pv, Tcl_Interp *interp,
165          int objc, Tcl_Obj * CONST objv[], policies const &pol)
166     {
167          C * p = static_cast<C*>(pv);
168
169          if (objc < 2)
170          {
171               throw tcl_error("Too few arguments.");
172          }
173
174          std::string methodName(Tcl_GetString(objv[1]));
175
176          if (methodName == "-delete")
177          {
178               Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
179               delete p;
180               return;
181          }
182
183          // dispatch on the method name
184
185          method_map_type::iterator it = methods_.find(methodName);
186          if (it == methods_.end())
187          {
188               throw tcl_error("Method " + methodName + " not found.");
189          }
190
191          it->second->invoke(pv, interp, objc, objv, pol);
192     }
193};
194
195
196// factory functions for creating class objects
197#include "details/constructors.h"
198
199// actual callback envelopes
200#include "details/callbacks.h"
201
202// actual method envelopes
203#include "details/methods.h"
204
205// helper meta function for figuring appropriate constructor callback
206#include "details/metahelpers.h"
207
208
209// this class is used to provide the "def" interface for defining
210// class member functions
211
212template <class C>
213class class_definer
214{
215public:
216     class_definer(boost::shared_ptr<class_handler<C> > ch) : ch_(ch) {}
217
218     template <typename R>
219     class_definer & def(std::string const &name, R (C::*f)(),
220          policies const &p = policies())
221     {
222          ch_->register_method(name,
223               boost::shared_ptr<details::object_cmd_base>(
224                    new details::method0<C, R>(f)), p);
225          return *this;
226     }
227
228     template <typename R>
229     class_definer & def(std::string const &name, R (C::*f)() const,
230          policies const &p = policies())
231     {
232          ch_->register_method(name,
233               boost::shared_ptr<details::object_cmd_base>(
234                    new details::method0<C, R>(f)), p);
235          return *this;
236     }
237
238     template <typename R, typename T1>
239     class_definer & def(std::string const &name, R (C::*f)(T1),
240          policies const &p = policies())
241     {
242          ch_->register_method(name,
243               boost::shared_ptr<details::object_cmd_base>(
244                    new details::method1<C, R, T1>(f)), p);
245          return *this;
246     }
247
248     template <typename R, typename T1>
249     class_definer & def(std::string const &name, R (C::*f)(T1) const,
250          policies const &p = policies())
251     {
252          ch_->register_method(name,
253               boost::shared_ptr<details::object_cmd_base>(
254                    new details::method1<C, R, T1>(f)), p);
255          return *this;
256     }
257
258     template <typename R, typename T1, typename T2>
259     class_definer & def(std::string const &name, R (C::*f)(T1, T2),
260          policies const &p = policies())
261     {
262          ch_->register_method(name,
263               boost::shared_ptr<details::object_cmd_base>(
264                    new details::method2<C, R, T1, T2>(f)), p);
265          return *this;
266     }
267
268     template <typename R, typename T1, typename T2>
269     class_definer & def(std::string const &name, R (C::*f)(T1, T2) const,
270          policies const &p = policies())
271     {
272          ch_->register_method(name,
273               boost::shared_ptr<details::object_cmd_base>(
274                    new details::method2<C, R, T1, T2>(f)), p);
275          return *this;
276     }
277
278     template <typename R, typename T1, typename T2, typename T3>
279     class_definer & def(std::string const &name, R (C::*f)(T1, T2, T3),
280          policies const &p = policies())
281     {
282          ch_->register_method(name,
283               boost::shared_ptr<details::object_cmd_base>(
284                    new details::method3<C, R, T1, T2, T3>(f)), p);
285          return *this;
286     }
287
288     template <typename R, typename T1, typename T2, typename T3>
289     class_definer & def(std::string const &name, R (C::*f)(T1, T2, T3) const,
290          policies const &p = policies())
291     {
292          ch_->register_method(name,
293               boost::shared_ptr<details::object_cmd_base>(
294                    new details::method3<C, R, T1, T2, T3>(f)), p);
295          return *this;
296     }
297
298     template <typename R, typename T1, typename T2, typename T3, typename T4>
299     class_definer & def(std::string const &name, R (C::*f)(T1, T2, T3, T4),
300          policies const &p = policies())
301     {
302          ch_->register_method(name,
303               boost::shared_ptr<details::object_cmd_base>(
304                    new details::method4<C, R, T1, T2, T3, T4>(f)), p);
305          return *this;
306     }
307
308     template <typename R, typename T1, typename T2, typename T3, typename T4>
309     class_definer & def(std::string const &name,
310          R (C::*f)(T1, T2, T3, T4) const,
311          policies const &p = policies())
312     {
313          ch_->register_method(name,
314               boost::shared_ptr<details::object_cmd_base>(
315                    new details::method4<C, R, T1, T2, T3, T4>(f)), p);
316          return *this;
317     }
318
319     template <typename R, typename T1, typename T2, typename T3, typename T4,
320          typename T5>
321     class_definer & def(std::string const &name,
322          R (C::*f)(T1, T2, T3, T4, T5), policies const &p = policies())
323     {
324          ch_->register_method(name,
325               boost::shared_ptr<details::object_cmd_base>(
326                    new details::method5<C, R, T1, T2, T3, T4, T5>(f)), p);
327          return *this;
328     }
329
330     template <typename R, typename T1, typename T2, typename T3, typename T4,
331          typename T5>
332     class_definer & def(std::string const &name,
333          R (C::*f)(T1, T2, T3, T4, T5) const, policies const &p = policies())
334     {
335          ch_->register_method(name,
336               boost::shared_ptr<details::object_cmd_base>(
337                    new details::method5<C, R, T1, T2, T3, T4, T5>(f)), p);
338          return *this;
339     }
340
341     template <typename R, typename T1, typename T2, typename T3, typename T4,
342          typename T5, typename T6>
343     class_definer & def(std::string const &name,
344          R (C::*f)(T1, T2, T3, T4, T5, T6), policies const &p = policies())
345     {
346          ch_->register_method(name,
347               boost::shared_ptr<details::object_cmd_base>(
348                    new details::method6<C, R, T1, T2, T3, T4, T5, T6>(f)),
349               p);
350          return *this;
351     }
352
353     template <typename R, typename T1, typename T2, typename T3, typename T4,
354          typename T5, typename T6>
355     class_definer & def(std::string const &name,
356          R (C::*f)(T1, T2, T3, T4, T5, T6) const,
357          policies const &p = policies())
358     {
359          ch_->register_method(name,
360               boost::shared_ptr<details::object_cmd_base>(
361                    new details::method6<C, R, T1, T2, T3, T4, T5, T6>(f)),
362               p);
363          return *this;
364     }
365
366     template <typename R, typename T1, typename T2, typename T3, typename T4,
367          typename T5, typename T6, typename T7>
368     class_definer & def(std::string const &name,
369          R (C::*f)(T1, T2, T3, T4, T5, T6, T7),
370          policies const &p = policies())
371     {
372          ch_->register_method(name,
373               boost::shared_ptr<details::object_cmd_base>(
374                    new details::method7<C, R,
375                    T1, T2, T3, T4, T5, T6, T7>(f)), p);
376          return *this;
377     }
378
379     template <typename R, typename T1, typename T2, typename T3, typename T4,
380          typename T5, typename T6, typename T7>
381     class_definer & def(std::string const &name,
382          R (C::*f)(T1, T2, T3, T4, T5, T6, T7) const,
383          policies const &p = policies())
384     {
385          ch_->register_method(name,
386               boost::shared_ptr<details::object_cmd_base>(
387                    new details::method7<C, R,
388                    T1, T2, T3, T4, T5, T6, T7>(f)), p);
389          return *this;
390     }
391
392     template <typename R, typename T1, typename T2, typename T3, typename T4,
393          typename T5, typename T6, typename T7, typename T8>
394     class_definer & def(std::string const &name,
395          R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8),
396          policies const &p = policies())
397     {
398          ch_->register_method(name,
399               boost::shared_ptr<details::object_cmd_base>(
400                    new details::method8<C, R,
401                    T1, T2, T3, T4, T5, T6, T7, T8>(f)), p);
402          return *this;
403     }
404
405     template <typename R, typename T1, typename T2, typename T3, typename T4,
406          typename T5, typename T6, typename T7, typename T8>
407     class_definer & def(std::string const &name,
408          R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8) const,
409          policies const &p = policies())
410     {
411          ch_->register_method(name,
412               boost::shared_ptr<details::object_cmd_base>(
413                    new details::method8<C, R,
414                    T1, T2, T3, T4, T5, T6, T7, T8>(f)), p);
415          return *this;
416     }
417
418     template <typename R, typename T1, typename T2, typename T3, typename T4,
419          typename T5, typename T6, typename T7, typename T8, typename T9>
420     class_definer & def(std::string const &name,
421          R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9),
422          policies const &p = policies())
423     {
424          ch_->register_method(name,
425               boost::shared_ptr<details::object_cmd_base>(
426                    new details::method9<C, R,
427                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(f)), p);
428          return *this;
429     }
430
431     template <typename R, typename T1, typename T2, typename T3, typename T4,
432          typename T5, typename T6, typename T7, typename T8, typename T9>
433     class_definer & def(std::string const &name,
434          R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9) const,
435          policies const &p = policies())
436     {
437          ch_->register_method(name,
438               boost::shared_ptr<details::object_cmd_base>(
439                    new details::method9<C, R,
440                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(f)), p);
441          return *this;
442     }
443
444private:
445     boost::shared_ptr<class_handler<C> > ch_;
446};
447
448} // namespace details
449
450
451// init type for defining class constructors
452template <typename T1 = void, typename T2 = void, typename T3 = void,
453          typename T4 = void, typename T5 = void, typename T6 = void,
454          typename T7 = void, typename T8 = void, typename T9 = void>
455class init {};
456
457// no_init type and object - to define classes without constructors
458namespace details
459{
460     struct no_init_type {};
461} // namespace details
462extern details::no_init_type no_init;
463
464
465// interpreter wrapper
466class interpreter
467{
468public:
469     interpreter();     interpreter(std::string const &libpath);
470     interpreter(Tcl_Interp *, bool owner = true);
471     ~interpreter();
472
473     void make_safe();
474
475     Tcl_Interp * get() const { return interp_; }
476
477     // free function definitions
478
479     template <typename R>
480     void def(std::string const &name, R (*f)(),
481          policies const &p = policies())
482     {
483          add_function(name,
484               boost::shared_ptr<details::callback_base>(
485                    new details::callback0<R>(f)), p);
486     }
487
488     template <typename R, typename T1>
489     void def(std::string const &name, R (*f)(T1),
490          policies const &p = policies())
491     {
492          add_function(name,
493               boost::shared_ptr<details::callback_base>(
494                    new details::callback1<R, T1>(f)), p);
495     }
496
497     template <typename R, typename T1, typename T2>
498     void def(std::string const &name, R (*f)(T1, T2),
499          policies const &p = policies())
500     {
501          add_function(name,
502               boost::shared_ptr<details::callback_base>(
503                    new details::callback2<R, T1, T2>(f)), p);
504     }
505
506     template <typename R, typename T1, typename T2, typename T3>
507     void def(std::string const &name, R (*f)(T1, T2, T3),
508          policies const &p = policies())
509     {
510          add_function(name,
511               boost::shared_ptr<details::callback_base>(
512                    new details::callback3<R, T1, T2, T3>(f)), p);
513     }
514
515     template <typename R, typename T1, typename T2, typename T3, typename T4>
516     void def(std::string const &name, R (*f)(T1, T2, T3, T4),
517          policies const &p = policies())
518     {
519          add_function(name,
520               boost::shared_ptr<details::callback_base>(
521                    new details::callback4<R, T1, T2, T3, T4>(f)), p);
522     }
523
524     template <typename R, typename T1, typename T2, typename T3,
525          typename T4, typename T5>
526     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5),
527          policies const &p = policies())
528     {
529          add_function(name,
530               boost::shared_ptr<details::callback_base>(
531                    new details::callback5<R, T1, T2, T3, T4, T5>(f)), p);
532     }
533
534     template <typename R, typename T1, typename T2, typename T3,
535          typename T4, typename T5, typename T6>
536     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6),
537          policies const &p = policies())
538     {
539          add_function(name,
540               boost::shared_ptr<details::callback_base>(
541                    new details::callback6<R, T1, T2, T3, T4, T5, T6>(f)), p);
542     }
543
544     template <typename R, typename T1, typename T2, typename T3,
545          typename T4, typename T5, typename T6, typename T7>
546     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6, T7),
547          policies const &p = policies())
548     {
549          add_function(name,
550               boost::shared_ptr<details::callback_base>(
551                    new details::callback7<R,
552                    T1, T2, T3, T4, T5, T6, T7>(f)), p);
553     }
554
555     template <typename R, typename T1, typename T2, typename T3,
556          typename T4, typename T5, typename T6, typename T7, typename T8>
557     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6, T7, T8),
558          policies const &p = policies())
559     {
560          add_function(name,
561               boost::shared_ptr<details::callback_base>(
562                    new details::callback8<R,
563                    T1, T2, T3, T4, T5, T6, T7, T8>(f)), p);
564     }
565
566     template <typename R, typename T1, typename T2, typename T3,
567          typename T4, typename T5, typename T6, typename T7, typename T8,
568          typename T9>
569     void def(std::string const &name,
570          R (*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9),
571          policies const &p = policies())
572     {
573          add_function(name,
574               boost::shared_ptr<details::callback_base>(
575                    new details::callback9<R,
576                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(f)), p);
577     }
578
579
580     // class definitions
581
582     template <class C>
583     details::class_definer<C> class_(std::string const &name)
584     {
585          boost::shared_ptr<details::class_handler<C> > ch(
586               new details::class_handler<C>());
587
588          add_class(name, ch);
589
590          add_constructor(name, ch,
591               boost::shared_ptr<details::callback_base>(
592                    new details::callback0<C*>(&details::construct<
593                         C, void, void, void, void, void, void, void,
594                         void, void>::doit)));
595
596          return details::class_definer<C>(ch);
597     }
598
599     template <class C, typename T1, typename T2, typename T3, typename T4,
600               typename T5, typename T6, typename T7, typename T8,
601               typename T9>
602     details::class_definer<C> class_(std::string const &name,
603          init<T1, T2, T3, T4, T5, T6, T7, T8, T9> const &,
604          policies const &p = policies())
605     {
606          typedef typename details::get_callback_type_for_construct<
607               C, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
608               callback_type;
609
610          boost::shared_ptr<details::class_handler<C> > ch(
611               new details::class_handler<C>());
612
613          add_class(name, ch);
614
615          add_constructor(name, ch,
616               boost::shared_ptr<details::callback_base>(
617                    new callback_type(&details::construct<
618                         C, T1, T2, T3, T4, T5, T6, T7, T8, T9>::doit)), p);
619
620          return details::class_definer<C>(ch);
621     }
622
623     template <class C>
624     details::class_definer<C> class_(
625          std::string const &name, details::no_init_type const &)
626     {
627          boost::shared_ptr<details::class_handler<C> > ch(
628               new details::class_handler<C>());
629
630          add_class(name, ch);
631
632          return details::class_definer<C>(ch);
633     }
634
635     // free script evaluation
636     details::result eval(std::string const &script);
637     details::result eval(std::istream &s);
638
639     details::result eval(object const &o);
640
641     // the InputIterator should give object& or Tcl_Obj* when dereferenced
642     template <class InputIterator>
643     details::result eval(InputIterator first, InputIterator last);
644
645     // create alias from the *this interpreter to the target interpreter
646     void create_alias(std::string const &cmd,
647          interpreter &targetInterp, std::string const &targetCmd);
648
649     // register a package info (useful when defining packages)
650     void pkg_provide(std::string const &name, std::string const &version);
651
652     // helper for cleaning up callbacks in non-managed interpreters
653     static void clear_definitions(Tcl_Interp *);
654
655private:
656
657     // copy not supported
658     interpreter(const interpreter &);
659     void operator=(const interpreter &);
660
661     void add_function(std::string const &name,
662          boost::shared_ptr<details::callback_base> cb,
663          policies const &p = policies());
664
665     void add_class(std::string const &name,
666          boost::shared_ptr<details::class_handler_base> chb);
667
668     void add_constructor(std::string const &name,
669          boost::shared_ptr<details::class_handler_base> chb,
670          boost::shared_ptr<details::callback_base> cb,
671          policies const &p = policies());
672
673     Tcl_Interp *interp_;
674     bool owner_;
675};
676
677
678// object wrapper
679class object
680{
681public:
682
683     // constructors
684
685     object();
686
687     explicit object(bool b);
688     object(char const *buf, size_t size); // byte array
689     explicit object(double b);
690     explicit object(int i);
691
692     // list creation
693     // the InputIterator should give object& or Tcl_Obj* when dereferenced
694     template <class InputIterator>
695     object(InputIterator first, InputIterator last)
696          : interp_(0)
697     {
698          std::vector<Tcl_Obj*> v;
699          fill_vector(v, first, last);
700          obj_ = Tcl_NewListObj(static_cast<int>(v.size()),
701               v.empty() ? NULL : &v[0]);
702          Tcl_IncrRefCount(obj_);
703     }
704
705     explicit object(long i);
706     explicit object(char const *s);        // string construction
707     explicit object(std::string const &s); // string construction
708
709     explicit object(Tcl_Obj *o, bool shared = false);
710
711     object(object const &other, bool shared = false);
712     ~object();
713
714     // assignment
715
716     object & assign(bool b);
717     object & resize(size_t size);                  // byte array resize
718     object & assign(char const *buf, size_t size); // byte array assignment
719     object & assign(double d);
720     object & assign(int i);
721
722     // list assignment
723     // the InputIterator should give Tcl_Obj* or object& when dereferenced
724     template <class InputIterator>
725     object & assign(InputIterator first, InputIterator last)
726     {
727          std::vector<Tcl_Obj*> v;
728          fill_vector(v, first, last);
729          Tcl_SetListObj(obj_, static_cast<int>(v.size()),
730               v.empty() ? NULL : &v[0]);
731          return *this;
732     }
733
734     object & assign(long l);
735     object & assign(char const *s);        // string assignment
736     object & assign(std::string const &s); // string assignment
737     object & assign(object const &o);
738     object & assign(Tcl_Obj *o);
739
740     object & operator=(bool b)               { return assign(b); }
741     object & operator=(double d)             { return assign(d); }
742     object & operator=(int i)                { return assign(i); }
743     object & operator=(long l)               { return assign(l); }
744     object & operator=(char const *s)        { return assign(s); }
745     object & operator=(std::string const &s) { return assign(s); }
746
747     object & operator=(object const &o)      { return assign(o); }
748     object & swap(object &other);
749
750     // (logically) non-modifying members
751
752     template <typename T>
753     T get(interpreter &i) const;
754
755     char const * get() const;             // string get
756     char const * get(size_t &size) const; // byte array get
757
758     size_t length(interpreter &i) const;  // returns list length
759     object at(interpreter &i, size_t index) const;
760
761     Tcl_Obj * get_object() const { return obj_; }
762
763     // modifying members
764
765     object & append(interpreter &i, object const &o);
766     object & append_list(interpreter &i, object const &o);
767
768     // list replace
769     // the InputIterator should give Tcl_Obj* or object& when dereferenced
770     template <class InputIterator>
771     object & replace(interpreter &i, size_t index, size_t count,
772          InputIterator first, InputIterator last)
773     {
774          std::vector<Tcl_Obj*> v;
775          fill_vector(v, first, last);
776          int res = Tcl_ListObjReplace(i.get(), obj_,
777               static_cast<int>(index), static_cast<int>(count),
778               static_cast<int>(v.size()), v.empty() ? NULL : &v[0]);
779          if (res != TCL_OK)
780          {
781               throw tcl_error(i.get());
782          }
783
784          return *this;
785     }
786
787     object & replace(interpreter &i, size_t index, size_t count,
788          object const &o);
789     object & replace_list(interpreter &i, size_t index, size_t count,
790          object const &o);
791
792     // helper functions for piggy-backing interpreter info
793     void set_interp(Tcl_Interp *interp);
794     Tcl_Interp * get_interp() const;
795
796     // helper function, also used from interpreter::eval
797     template <class InputIterator>
798     static void fill_vector(std::vector<Tcl_Obj*> &v,
799          InputIterator first, InputIterator last)
800     {
801          for (; first != last; ++first)
802          {
803               object o(*first, true);
804               v.push_back(o.obj_);
805          }
806     }
807
808private:
809
810     // helper function used from copy constructors
811     void init(Tcl_Obj *o, bool shared);
812
813     Tcl_Obj *obj_;
814     Tcl_Interp *interp_;
815};
816
817// available specializations for object::get
818template <> bool         object::get<bool>(interpreter &i) const;
819template <> double       object::get<double>(interpreter &i) const;
820template <> int          object::get<int>(interpreter &i) const;
821template <> long         object::get<long>(interpreter &i) const;
822template <> char const * object::get<char const *>(interpreter &i) const;
823template <> std::string  object::get<std::string>(interpreter &i) const;
824template <>
825std::vector<char> object::get<std::vector<char> >(interpreter &i) const;
826
827// the InputIterator should give object& or Tcl_Obj* when dereferenced
828template <class InputIterator>
829details::result interpreter::eval(InputIterator first, InputIterator last)
830{
831     std::vector<Tcl_Obj*> v;
832     object::fill_vector(v, first, last);
833     int cc = Tcl_EvalObjv(interp_,
834          static_cast<int>(v.size()), v.empty() ? NULL : &v[0], 0);
835     if (cc != TCL_OK)
836     {
837          throw tcl_error(interp_);
838     }
839
840     return details::result(interp_);
841}
842
843namespace details
844{
845
846// additional callback envelopes for variadic functions
847#include "details/callbacks_v.h"
848
849// additional method envelopes for variadic methods
850#include "details/methods_v.h"
851
852} // namespace details
853
854} // namespace Tcl
855
856
857// macro for defining loadable module entry point
858// - used for extending Tcl interpreter
859
860#define CPPTCL_MODULE(name, i) void name##_cpptcl_Init(Tcl::interpreter &i); \
861     extern "C" int name##_Init(Tcl_Interp *interp) \
862     { \
863          Tcl::interpreter i(interp, false); \
864          name##_cpptcl_Init(i); \
865          return TCL_OK; \
866     } \
867     void name##_cpptcl_Init(Tcl::interpreter &i)
868
869
870#endif // CPPTCL_INCLUDED
Note: See TracBrowser for help on using the repository browser.