import source from 1.3.40
[external/swig.git] / Examples / test-suite / li_boost_shared_ptr.i
1 // This tests shared_ptr is working okay. It also checks that there are no memory leaks in the
2 // class that shared_ptr is pointing via a counting mechanism in the constructors and destructor of Klass.
3 // In order to test that there are no leaks of the shared_ptr class itself (as it is created on the heap)
4 // the runtime tests can be run for a long time to monitor memory leaks using memory monitor tools 
5 // like 'top'. There is a wrapper for shared_ptr in shared_ptr_wrapper.h which enables one to
6 // count the instances of shared_ptr. Uncomment the SHARED_PTR_WRAPPER macro to turn this on.
7 //
8 // Also note the debug_shared flag  which can be set from the target language.
9
10 %module li_boost_shared_ptr
11
12 %warnfilter(SWIGWARN_TYPEMAP_SWIGTYPELEAK);
13
14 %inline %{
15 #include "boost/shared_ptr.hpp"
16 #include "swig_examples_lock.h"
17
18 // Uncomment macro below to turn on shared_ptr memory leak checking as described above
19 //#define SHARED_PTR_WRAPPER
20
21 #ifdef SHARED_PTR_WRAPPER
22 # include "shared_ptr_wrapper.h"
23 #endif
24 %}
25
26 %{
27 #ifndef SHARED_PTR_WRAPPER
28 # define SwigBoost boost
29 #endif
30 %}
31
32 %include "std_string.i"
33 #ifndef SHARED_PTR_WRAPPER
34 # define SWIG_SHARED_PTR_NAMESPACE SwigBoost
35 #endif
36
37 #if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON)
38 #define SHARED_PTR_WRAPPERS_IMPLEMENTED
39 #endif
40
41 #if defined(SHARED_PTR_WRAPPERS_IMPLEMENTED)
42
43 %include <boost_shared_ptr.i>
44 SWIG_SHARED_PTR(Klass, Space::Klass)
45 SWIG_SHARED_PTR_DERIVED(KlassDerived, Space::Klass, Space::KlassDerived)
46 SWIG_SHARED_PTR_DERIVED(Klass2ndDerived, Space::Klass, Space::Klass2ndDerived)
47 SWIG_SHARED_PTR_DERIVED(Klass3rdDerived, Space::Klass2ndDerived, Space::Klass3rdDerived)
48
49 // TEMP for python
50 %types(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< Space::Klass3rdDerived > = SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< Space::Klass >) {
51   *newmemory = SWIG_CAST_NEW_MEMORY;
52   return (void *) new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< Space::Klass >(*(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< Space::Klass3rdDerived > *)$from);
53 }
54
55 #endif
56
57 // TODO:
58 // const shared_ptr
59 // std::vector
60 // Add in generic %extend for the Upcast function for derived classes
61 // Remove proxy upcast method - implement %feature("shadow") ??? which replaces the proxy method
62
63 %exception {
64   if (debug_shared) {
65     cout << "++++++" << endl;
66     cout << "calling $name" << endl;
67   }
68   $action
69   if (debug_shared) {
70     cout << "------" << endl;
71   }
72 }
73
74 %ignore IgnoredMultipleInheritBase;
75 %ignore Space::Klass::operator=;
76 %newobject pointerownertest();
77 %newobject smartpointerpointerownertest();
78
79 %inline %{
80 #include <iostream>
81 using namespace std;
82
83 static bool debug_shared = false;
84
85 namespace Space {
86
87 struct Klass {
88   Klass() : value("EMPTY") { if (debug_shared) cout << "Klass() [" << value << "]" << endl; increment(); }
89
90   Klass(const std::string &val) : value(val) { if (debug_shared) cout << "Klass(string) [" << value << "]" << endl; increment(); }
91
92   virtual ~Klass() { if (debug_shared) cout << "~Klass() [" << value << "]" << endl; decrement(); }
93   virtual std::string getValue() const { return value; }
94   void append(const std::string &s) { value += s; }
95   Klass(const Klass &other) : value(other.value) { if (debug_shared) cout << "Klass(const Klass&) [" << value << "]" << endl; increment(); }
96
97   Klass &operator=(const Klass &other) { value = other.value; return *this; }
98   static int getTotal_count() { return total_count; }
99
100 private:
101   // lock increment and decrement as a destructor could be called at the same time as a 
102   // new object is being created - C# / Java, at least, have finalizers run in a separate thread
103   static SwigExamples::CriticalSection critical_section;
104   static void increment() { SwigExamples::Lock lock(critical_section); total_count++; if (debug_shared) cout << "      ++xxxxx Klass::increment tot: " << total_count << endl;}
105   static void decrement() { SwigExamples::Lock lock(critical_section); total_count--; if (debug_shared) cout << "      --xxxxx Klass::decrement tot: " << total_count << endl;}
106   static int total_count;
107   std::string value;
108   int array[1024];
109 };
110 SwigExamples::CriticalSection Space::Klass::critical_section;
111
112 struct IgnoredMultipleInheritBase { 
113   IgnoredMultipleInheritBase() : d(0.0), e(0.0) {}
114   virtual ~IgnoredMultipleInheritBase() {} 
115   double d; 
116   double e;
117   virtual void AVirtualMethod() {} 
118 };
119
120 // For most compilers, this use of multiple inheritance results in different derived and base class 
121 // pointer values ... for some more challenging tests :)
122 struct KlassDerived : IgnoredMultipleInheritBase, Klass {
123   KlassDerived() : Klass() {}
124   KlassDerived(const std::string &val) : Klass(val) {}
125   KlassDerived(const KlassDerived &other) : Klass(other) {}
126   virtual ~KlassDerived() {}
127   virtual std::string getValue() const { return Klass::getValue() + "-Derived"; }
128 };
129 KlassDerived* derivedpointertest(KlassDerived* kd) {
130   if (kd)
131     kd->append(" derivedpointertest");
132   return kd;
133 }
134 KlassDerived& derivedreftest(KlassDerived& kd) {
135   kd.append(" derivedreftest");
136   return kd;
137 }
138 SwigBoost::shared_ptr<KlassDerived> derivedsmartptrtest(SwigBoost::shared_ptr<KlassDerived> kd) {
139   if (kd)
140     kd->append(" derivedsmartptrtest");
141   return kd;
142 }
143 SwigBoost::shared_ptr<KlassDerived>* derivedsmartptrpointertest(SwigBoost::shared_ptr<KlassDerived>* kd) {
144   if (kd && *kd)
145     (*kd)->append(" derivedsmartptrpointertest");
146   return kd;
147 }
148 SwigBoost::shared_ptr<KlassDerived>* derivedsmartptrreftest(SwigBoost::shared_ptr<KlassDerived>* kd) {
149   if (kd && *kd)
150     (*kd)->append(" derivedsmartptrreftest");
151   return kd;
152 }
153 SwigBoost::shared_ptr<KlassDerived>*& derivedsmartptrpointerreftest(SwigBoost::shared_ptr<KlassDerived>*& kd) {
154   if (kd && *kd)
155     (*kd)->append(" derivedsmartptrpointerreftest");
156   return kd;
157 }
158
159 // 3 classes in inheritance chain test
160 struct Klass2ndDerived : Klass {
161   Klass2ndDerived() : Klass() {}
162   Klass2ndDerived(const std::string &val) : Klass(val) {}
163 };
164 struct Klass3rdDerived : IgnoredMultipleInheritBase, Klass2ndDerived {
165   Klass3rdDerived() : Klass2ndDerived() {}
166   Klass3rdDerived(const std::string &val) : Klass2ndDerived(val) {}
167   virtual ~Klass3rdDerived() {}
168   virtual std::string getValue() const { return Klass2ndDerived::getValue() + "-3rdDerived"; }
169 };
170
171 std::string test3rdupcast( SwigBoost::shared_ptr< Klass > k) {
172   return k->getValue();
173 }
174
175
176
177 SwigBoost::shared_ptr<Klass> factorycreate() {
178   return SwigBoost::shared_ptr<Klass>(new Klass("factorycreate"));
179 }
180 // smart pointer
181 SwigBoost::shared_ptr<Klass> smartpointertest(SwigBoost::shared_ptr<Klass> k) {
182   if (k)
183     k->append(" smartpointertest");
184   return SwigBoost::shared_ptr<Klass>(k);
185 }
186 SwigBoost::shared_ptr<Klass>* smartpointerpointertest(SwigBoost::shared_ptr<Klass>* k) {
187   if (k && *k)
188     (*k)->append(" smartpointerpointertest");
189   return k;
190 }
191 SwigBoost::shared_ptr<Klass>& smartpointerreftest(SwigBoost::shared_ptr<Klass>& k) {
192   if (k)
193     k->append(" smartpointerreftest");
194   return k;
195 }
196 SwigBoost::shared_ptr<Klass>*& smartpointerpointerreftest(SwigBoost::shared_ptr<Klass>*& k) {
197   if (k && *k)
198     (*k)->append(" smartpointerpointerreftest");
199   return k;
200 }
201 // const
202 SwigBoost::shared_ptr<const Klass> constsmartpointertest(SwigBoost::shared_ptr<const Klass> k) {
203   return SwigBoost::shared_ptr<const Klass>(k);
204 }
205 SwigBoost::shared_ptr<const Klass>* constsmartpointerpointertest(SwigBoost::shared_ptr<const Klass>* k) {
206   return k;
207 }
208 SwigBoost::shared_ptr<const Klass>& constsmartpointerreftest(SwigBoost::shared_ptr<const Klass>& k) {
209   return k;
210 }
211 // plain pointer
212 Klass valuetest(Klass k) {
213   k.append(" valuetest");
214   return k;
215 }
216 Klass *pointertest(Klass *k) {
217   if (k)
218     k->append(" pointertest");
219   return k;
220 }
221 Klass& reftest(Klass& k) {
222   k.append(" reftest");
223   return k;
224 }
225 Klass*& pointerreftest(Klass*& k) {
226   k->append(" pointerreftest");
227   return k;
228 }
229 // null
230 std::string nullsmartpointerpointertest(SwigBoost::shared_ptr<Klass>* k) {
231   if (k && *k)
232     return "not null";
233   else if (!k)
234     return "null smartpointer pointer";
235   else if (!*k)
236     return "null pointer";
237   else
238     return "also not null";
239 }
240 // $owner
241 Klass *pointerownertest() {
242   return new Klass("pointerownertest");
243 }
244 SwigBoost::shared_ptr<Klass>* smartpointerpointerownertest() {
245   return new SwigBoost::shared_ptr<Klass>(new Klass("smartpointerpointerownertest"));
246 }
247
248 // Provide overloads for Klass and derived classes as some language modules, eg Python, create an extra reference in
249 // the marshalling if an upcast to a base class is required.
250 long use_count(const SwigBoost::shared_ptr<Klass3rdDerived>& sptr) {
251   return sptr.use_count();
252 }
253 long use_count(const SwigBoost::shared_ptr<Klass2ndDerived>& sptr) {
254   return sptr.use_count();
255 }
256 long use_count(const SwigBoost::shared_ptr<KlassDerived>& sptr) {
257   return sptr.use_count();
258 }
259 long use_count(const SwigBoost::shared_ptr<Klass>& sptr) {
260   return sptr.use_count();
261 }
262 const SwigBoost::shared_ptr<Klass>& ref_1() { 
263   static SwigBoost::shared_ptr<Klass> sptr;
264   return sptr;
265 }
266
267 // overloading tests
268 std::string overload_rawbyval(int i) { return "int"; }
269 std::string overload_rawbyval(Klass k) { return "rawbyval"; }
270
271 std::string overload_rawbyref(int i) { return "int"; }
272 std::string overload_rawbyref(Klass &k) { return "rawbyref"; }
273
274 std::string overload_rawbyptr(int i) { return "int"; }
275 std::string overload_rawbyptr(Klass *k) { return "rawbyptr"; }
276
277 std::string overload_rawbyptrref(int i) { return "int"; }
278 std::string overload_rawbyptrref(Klass *&k) { return "rawbyptrref"; }
279
280
281
282 std::string overload_smartbyval(int i) { return "int"; }
283 std::string overload_smartbyval(SwigBoost::shared_ptr<Klass> k) { return "smartbyval"; }
284
285 std::string overload_smartbyref(int i) { return "int"; }
286 std::string overload_smartbyref(SwigBoost::shared_ptr<Klass> &k) { return "smartbyref"; }
287
288 std::string overload_smartbyptr(int i) { return "int"; }
289 std::string overload_smartbyptr(SwigBoost::shared_ptr<Klass> *k) { return "smartbyptr"; }
290
291 std::string overload_smartbyptrref(int i) { return "int"; }
292 std::string overload_smartbyptrref(SwigBoost::shared_ptr<Klass> *&k) { return "smartbyptrref"; }
293
294 } // namespace Space
295
296 %}
297 %{
298   int Space::Klass::total_count = 0;
299 %}
300
301
302 // Member variables
303
304 %inline %{
305 struct MemberVariables {
306   MemberVariables() : SmartMemberPointer(&SmartMemberValue), SmartMemberReference(SmartMemberValue), MemberPointer(0), MemberReference(MemberValue) {}
307   SwigBoost::shared_ptr<Space::Klass> SmartMemberValue;
308   SwigBoost::shared_ptr<Space::Klass> * SmartMemberPointer;
309   SwigBoost::shared_ptr<Space::Klass> & SmartMemberReference;
310   Space::Klass MemberValue;
311   Space::Klass * MemberPointer;
312   Space::Klass & MemberReference;
313 };
314
315 // Global variables
316 SwigBoost::shared_ptr<Space::Klass> GlobalSmartValue;
317 Space::Klass GlobalValue;
318 Space::Klass * GlobalPointer = 0;
319 Space::Klass & GlobalReference = GlobalValue;
320
321 %}
322
323 #if defined(SHARED_PTR_WRAPPERS_IMPLEMENTED)
324
325 // Note: %template after the shared_ptr typemaps
326 SWIG_SHARED_PTR(BaseIntDouble, Base<int, double>)
327 // Note: cannot use Base<int, double> in the macro below because of the comma in the type, 
328 // so we use a typedef instead. Alternatively use %arg(Base<int, double>). %arg is defined in swigmacros.swg.
329 SWIG_SHARED_PTR_DERIVED(PairIntDouble, BaseIntDouble_t, Pair<int, double>)
330
331 #endif
332
333 // Templates
334 %inline %{
335 template <class T1, class T2> struct Base {
336   Space::Klass klassBase;
337   T1 baseVal1;
338   T2 baseVal2;
339   Base(T1 t1, T2 t2) : baseVal1(t1*2), baseVal2(t2*2) {}
340   virtual std::string getValue() const { return "Base<>"; };
341 };
342 typedef Base<int, double> BaseIntDouble_t;
343 %}
344
345 %template(BaseIntDouble) Base<int, double>;
346
347 %inline %{
348 template <class T1, class T2> struct Pair : Base<T1, T2> {
349   Space::Klass klassPair;
350   T1 val1;
351   T2 val2;
352   Pair(T1 t1, T2 t2) : Base<T1, T2>(t1, t2), val1(t1), val2(t2) {}
353   virtual std::string getValue() const { return "Pair<>"; };
354 };
355 Pair<int, double> pair_id2(Pair<int, double> p) { return p; }
356 SwigBoost::shared_ptr< Pair<int, double> > pair_id1(SwigBoost::shared_ptr< Pair<int, double> > p) { return p; }
357 %}
358
359 %template(PairIntDouble) Pair<int, double>;
360
361
362 // For counting the instances of shared_ptr (all of which are created on the heap)
363 // shared_ptr_wrapper_count() gives overall count
364 %inline %{
365 namespace SwigBoost {
366   const int NOT_COUNTING = -123456;
367   int shared_ptr_wrapper_count() { 
368   #ifdef SHARED_PTR_WRAPPER
369     return SwigBoost::SharedPtrWrapper::getTotalCount(); 
370   #else
371     return NOT_COUNTING;
372   #endif
373   }
374   #ifdef SHARED_PTR_WRAPPER
375   template<> std::string show_message(boost::shared_ptr<Space::Klass >*t) {
376     if (!t)
377       return "null shared_ptr!!!";
378     if (boost::get_deleter<SWIG_null_deleter>(*t))
379       return "Klass NULL DELETER"; // pointer may be dangling so cannot use it
380     if (*t)
381       return "Klass: " + (*t)->getValue();
382     else
383       return "Klass: NULL";
384   }
385   template<> std::string show_message(boost::shared_ptr<const Space::Klass >*t) {
386     if (!t)
387       return "null shared_ptr!!!";
388     if (boost::get_deleter<SWIG_null_deleter>(*t))
389       return "Klass NULL DELETER"; // pointer may be dangling so cannot use it
390     if (*t)
391       return "Klass: " + (*t)->getValue();
392     else
393       return "Klass: NULL";
394   }
395   template<> std::string show_message(boost::shared_ptr<Space::KlassDerived >*t) {
396     if (!t)
397       return "null shared_ptr!!!";
398     if (boost::get_deleter<SWIG_null_deleter>(*t))
399       return "KlassDerived NULL DELETER"; // pointer may be dangling so cannot use it
400     if (*t)
401       return "KlassDerived: " + (*t)->getValue();
402     else
403       return "KlassDerived: NULL";
404   }
405   template<> std::string show_message(boost::shared_ptr<const Space::KlassDerived >*t) {
406     if (!t)
407       return "null shared_ptr!!!";
408     if (boost::get_deleter<SWIG_null_deleter>(*t))
409       return "KlassDerived NULL DELETER"; // pointer may be dangling so cannot use it
410     if (*t)
411       return "KlassDerived: " + (*t)->getValue();
412     else
413       return "KlassDerived: NULL";
414   }
415   #endif
416 }
417 %}
418