Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy2/src/cpptcl/CppTcl.h @ 2345

Last change on this file since 2345 was 1505, checked in by rgrieder, 16 years ago

f* svn: It doesn't even inform you if you attempt to set a non existing property. It is svn:eol-style and not eol-style when using the command by the way…

  • 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();
470     interpreter(std::string const &libpath);
471     interpreter(Tcl_Interp *, bool owner = true);
472     ~interpreter();
473
474     void make_safe();
475
476     Tcl_Interp * get() const { return interp_; }
477
478     // free function definitions
479
480     template <typename R>
481     void def(std::string const &name, R (*f)(),
482          policies const &p = policies())
483     {
484          add_function(name,
485               boost::shared_ptr<details::callback_base>(
486                    new details::callback0<R>(f)), p);
487     }
488
489     template <typename R, typename T1>
490     void def(std::string const &name, R (*f)(T1),
491          policies const &p = policies())
492     {
493          add_function(name,
494               boost::shared_ptr<details::callback_base>(
495                    new details::callback1<R, T1>(f)), p);
496     }
497
498     template <typename R, typename T1, typename T2>
499     void def(std::string const &name, R (*f)(T1, T2),
500          policies const &p = policies())
501     {
502          add_function(name,
503               boost::shared_ptr<details::callback_base>(
504                    new details::callback2<R, T1, T2>(f)), p);
505     }
506
507     template <typename R, typename T1, typename T2, typename T3>
508     void def(std::string const &name, R (*f)(T1, T2, T3),
509          policies const &p = policies())
510     {
511          add_function(name,
512               boost::shared_ptr<details::callback_base>(
513                    new details::callback3<R, T1, T2, T3>(f)), p);
514     }
515
516     template <typename R, typename T1, typename T2, typename T3, typename T4>
517     void def(std::string const &name, R (*f)(T1, T2, T3, T4),
518          policies const &p = policies())
519     {
520          add_function(name,
521               boost::shared_ptr<details::callback_base>(
522                    new details::callback4<R, T1, T2, T3, T4>(f)), p);
523     }
524
525     template <typename R, typename T1, typename T2, typename T3,
526          typename T4, typename T5>
527     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5),
528          policies const &p = policies())
529     {
530          add_function(name,
531               boost::shared_ptr<details::callback_base>(
532                    new details::callback5<R, T1, T2, T3, T4, T5>(f)), p);
533     }
534
535     template <typename R, typename T1, typename T2, typename T3,
536          typename T4, typename T5, typename T6>
537     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6),
538          policies const &p = policies())
539     {
540          add_function(name,
541               boost::shared_ptr<details::callback_base>(
542                    new details::callback6<R, T1, T2, T3, T4, T5, T6>(f)), p);
543     }
544
545     template <typename R, typename T1, typename T2, typename T3,
546          typename T4, typename T5, typename T6, typename T7>
547     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6, T7),
548          policies const &p = policies())
549     {
550          add_function(name,
551               boost::shared_ptr<details::callback_base>(
552                    new details::callback7<R,
553                    T1, T2, T3, T4, T5, T6, T7>(f)), p);
554     }
555
556     template <typename R, typename T1, typename T2, typename T3,
557          typename T4, typename T5, typename T6, typename T7, typename T8>
558     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6, T7, T8),
559          policies const &p = policies())
560     {
561          add_function(name,
562               boost::shared_ptr<details::callback_base>(
563                    new details::callback8<R,
564                    T1, T2, T3, T4, T5, T6, T7, T8>(f)), p);
565     }
566
567     template <typename R, typename T1, typename T2, typename T3,
568          typename T4, typename T5, typename T6, typename T7, typename T8,
569          typename T9>
570     void def(std::string const &name,
571          R (*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9),
572          policies const &p = policies())
573     {
574          add_function(name,
575               boost::shared_ptr<details::callback_base>(
576                    new details::callback9<R,
577                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(f)), p);
578     }
579
580
581     // class definitions
582
583     template <class C>
584     details::class_definer<C> class_(std::string const &name)
585     {
586          boost::shared_ptr<details::class_handler<C> > ch(
587               new details::class_handler<C>());
588
589          add_class(name, ch);
590
591          add_constructor(name, ch,
592               boost::shared_ptr<details::callback_base>(
593                    new details::callback0<C*>(&details::construct<
594                         C, void, void, void, void, void, void, void,
595                         void, void>::doit)));
596
597          return details::class_definer<C>(ch);
598     }
599
600     template <class C, typename T1, typename T2, typename T3, typename T4,
601               typename T5, typename T6, typename T7, typename T8,
602               typename T9>
603     details::class_definer<C> class_(std::string const &name,
604          init<T1, T2, T3, T4, T5, T6, T7, T8, T9> const &,
605          policies const &p = policies())
606     {
607          typedef typename details::get_callback_type_for_construct<
608               C, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
609               callback_type;
610
611          boost::shared_ptr<details::class_handler<C> > ch(
612               new details::class_handler<C>());
613
614          add_class(name, ch);
615
616          add_constructor(name, ch,
617               boost::shared_ptr<details::callback_base>(
618                    new callback_type(&details::construct<
619                         C, T1, T2, T3, T4, T5, T6, T7, T8, T9>::doit)), p);
620
621          return details::class_definer<C>(ch);
622     }
623
624     template <class C>
625     details::class_definer<C> class_(
626          std::string const &name, details::no_init_type const &)
627     {
628          boost::shared_ptr<details::class_handler<C> > ch(
629               new details::class_handler<C>());
630
631          add_class(name, ch);
632
633          return details::class_definer<C>(ch);
634     }
635
636     // free script evaluation
637     details::result eval(std::string const &script);
638     details::result eval(std::istream &s);
639
640     details::result eval(object const &o);
641
642     // the InputIterator should give object& or Tcl_Obj* when dereferenced
643     template <class InputIterator>
644     details::result eval(InputIterator first, InputIterator last);
645
646     // create alias from the *this interpreter to the target interpreter
647     void create_alias(std::string const &cmd,
648          interpreter &targetInterp, std::string const &targetCmd);
649
650     // register a package info (useful when defining packages)
651     void pkg_provide(std::string const &name, std::string const &version);
652
653     // helper for cleaning up callbacks in non-managed interpreters
654     static void clear_definitions(Tcl_Interp *);
655
656private:
657
658     // copy not supported
659     interpreter(const interpreter &);
660     void operator=(const interpreter &);
661
662     void add_function(std::string const &name,
663          boost::shared_ptr<details::callback_base> cb,
664          policies const &p = policies());
665
666     void add_class(std::string const &name,
667          boost::shared_ptr<details::class_handler_base> chb);
668
669     void add_constructor(std::string const &name,
670          boost::shared_ptr<details::class_handler_base> chb,
671          boost::shared_ptr<details::callback_base> cb,
672          policies const &p = policies());
673
674     Tcl_Interp *interp_;
675     bool owner_;
676};
677
678
679// object wrapper
680class object
681{
682public:
683
684     // constructors
685
686     object();
687
688     explicit object(bool b);
689     object(char const *buf, size_t size); // byte array
690     explicit object(double b);
691     explicit object(int i);
692
693     // list creation
694     // the InputIterator should give object& or Tcl_Obj* when dereferenced
695     template <class InputIterator>
696     object(InputIterator first, InputIterator last)
697          : interp_(0)
698     {
699          std::vector<Tcl_Obj*> v;
700          fill_vector(v, first, last);
701          obj_ = Tcl_NewListObj(static_cast<int>(v.size()),
702               v.empty() ? NULL : &v[0]);
703          Tcl_IncrRefCount(obj_);
704     }
705
706     explicit object(long i);
707     explicit object(char const *s);        // string construction
708     explicit object(std::string const &s); // string construction
709
710     explicit object(Tcl_Obj *o, bool shared = false);
711
712     object(object const &other, bool shared = false);
713     ~object();
714
715     // assignment
716
717     object & assign(bool b);
718     object & resize(size_t size);                  // byte array resize
719     object & assign(char const *buf, size_t size); // byte array assignment
720     object & assign(double d);
721     object & assign(int i);
722
723     // list assignment
724     // the InputIterator should give Tcl_Obj* or object& when dereferenced
725     template <class InputIterator>
726     object & assign(InputIterator first, InputIterator last)
727     {
728          std::vector<Tcl_Obj*> v;
729          fill_vector(v, first, last);
730          Tcl_SetListObj(obj_, static_cast<int>(v.size()),
731               v.empty() ? NULL : &v[0]);
732          return *this;
733     }
734
735     object & assign(long l);
736     object & assign(char const *s);        // string assignment
737     object & assign(std::string const &s); // string assignment
738     object & assign(object const &o);
739     object & assign(Tcl_Obj *o);
740
741     object & operator=(bool b)               { return assign(b); }
742     object & operator=(double d)             { return assign(d); }
743     object & operator=(int i)                { return assign(i); }
744     object & operator=(long l)               { return assign(l); }
745     object & operator=(char const *s)        { return assign(s); }
746     object & operator=(std::string const &s) { return assign(s); }
747
748     object & operator=(object const &o)      { return assign(o); }
749     object & swap(object &other);
750
751     // (logically) non-modifying members
752
753     template <typename T>
754     T get(interpreter &i) const;
755
756     char const * get() const;             // string get
757     char const * get(size_t &size) const; // byte array get
758
759     size_t length(interpreter &i) const;  // returns list length
760     object at(interpreter &i, size_t index) const;
761
762     Tcl_Obj * get_object() const { return obj_; }
763
764     // modifying members
765
766     object & append(interpreter &i, object const &o);
767     object & append_list(interpreter &i, object const &o);
768
769     // list replace
770     // the InputIterator should give Tcl_Obj* or object& when dereferenced
771     template <class InputIterator>
772     object & replace(interpreter &i, size_t index, size_t count,
773          InputIterator first, InputIterator last)
774     {
775          std::vector<Tcl_Obj*> v;
776          fill_vector(v, first, last);
777          int res = Tcl_ListObjReplace(i.get(), obj_,
778               static_cast<int>(index), static_cast<int>(count),
779               static_cast<int>(v.size()), v.empty() ? NULL : &v[0]);
780          if (res != TCL_OK)
781          {
782               throw tcl_error(i.get());
783          }
784
785          return *this;
786     }
787
788     object & replace(interpreter &i, size_t index, size_t count,
789          object const &o);
790     object & replace_list(interpreter &i, size_t index, size_t count,
791          object const &o);
792
793     // helper functions for piggy-backing interpreter info
794     void set_interp(Tcl_Interp *interp);
795     Tcl_Interp * get_interp() const;
796
797     // helper function, also used from interpreter::eval
798     template <class InputIterator>
799     static void fill_vector(std::vector<Tcl_Obj*> &v,
800          InputIterator first, InputIterator last)
801     {
802          for (; first != last; ++first)
803          {
804               object o(*first, true);
805               v.push_back(o.obj_);
806          }
807     }
808
809private:
810
811     // helper function used from copy constructors
812     void init(Tcl_Obj *o, bool shared);
813
814     Tcl_Obj *obj_;
815     Tcl_Interp *interp_;
816};
817
818// available specializations for object::get
819template <> bool         object::get<bool>(interpreter &i) const;
820template <> double       object::get<double>(interpreter &i) const;
821template <> int          object::get<int>(interpreter &i) const;
822template <> long         object::get<long>(interpreter &i) const;
823template <> char const * object::get<char const *>(interpreter &i) const;
824template <> std::string  object::get<std::string>(interpreter &i) const;
825template <>
826std::vector<char> object::get<std::vector<char> >(interpreter &i) const;
827
828// the InputIterator should give object& or Tcl_Obj* when dereferenced
829template <class InputIterator>
830details::result interpreter::eval(InputIterator first, InputIterator last)
831{
832     std::vector<Tcl_Obj*> v;
833     object::fill_vector(v, first, last);
834     int cc = Tcl_EvalObjv(interp_,
835          static_cast<int>(v.size()), v.empty() ? NULL : &v[0], 0);
836     if (cc != TCL_OK)
837     {
838          throw tcl_error(interp_);
839     }
840
841     return details::result(interp_);
842}
843
844namespace details
845{
846
847// additional callback envelopes for variadic functions
848#include "details/callbacks_v.h"
849
850// additional method envelopes for variadic methods
851#include "details/methods_v.h"
852
853} // namespace details
854
855} // namespace Tcl
856
857
858// macro for defining loadable module entry point
859// - used for extending Tcl interpreter
860
861#define CPPTCL_MODULE(name, i) void name##_cpptcl_Init(Tcl::interpreter &i); \
862     extern "C" int name##_Init(Tcl_Interp *interp) \
863     { \
864          Tcl::interpreter i(interp, false); \
865          name##_cpptcl_Init(i); \
866          return TCL_OK; \
867     } \
868     void name##_cpptcl_Init(Tcl::interpreter &i)
869
870
871#endif // CPPTCL_INCLUDED
Note: See TracBrowser for help on using the repository browser.