]> Creatis software - gdcm.git/blob - gdcmPython/gdcm.i
* gdcmPython/gdcm.i : bug fix. Now string are correctly converted in python
[gdcm.git] / gdcmPython / gdcm.i
1 %module gdcm
2 %{
3 #include <iostream>
4
5 #include "gdcmCommon.h"
6 #include "gdcmBase.h"
7 #include "gdcmDict.h"
8 #include "gdcmDictEntry.h"
9 #include "gdcmDictSet.h"
10 #include "gdcmDicomDir.h"
11 #include "gdcmDicomDirElement.h"
12 #include "gdcmDicomDirImage.h"
13 #include "gdcmDicomDirMeta.h"
14 #include "gdcmDicomDirObject.h"
15 #include "gdcmDicomDirPatient.h"
16 #include "gdcmDicomDirStudy.h"
17 #include "gdcmDicomDirSerie.h"
18 #include "gdcmDocEntrySet.h"
19 #include "gdcmDocument.h"
20 #include "gdcmElementSet.h"
21 #include "gdcmFileHelper.h"
22 #include "gdcmGlobal.h"
23 #include "gdcmFile.h"
24 #include "gdcmSerieHelper.h"
25 #include "gdcmRLEFramesInfo.h"
26 #include "gdcmJPEGFragmentsInfo.h"
27 #include "gdcmSQItem.h"
28 #include "gdcmUtil.h"
29 #include "gdcmDocEntry.h"
30 #include "gdcmContentEntry.h"
31 #include "gdcmValEntry.h"
32 #include "gdcmBinEntry.h"
33 #include "gdcmSeqEntry.h"
34
35 ////////////////////////////////////////////////////////////////////////////
36 /// Refer (below) to the definition of multi-argument typemap
37 ///   %typemap(python, in)
38 ///      ( gdcm::DicomDir::Method*, void*, gdcm::DicomDir::Method*)
39 /// for detail on gdcmPythonVoidFunc() and gdcmPythonVoidFuncArgDelete().
40 void gdcmPythonVoidFunc(void *arg)
41 {
42    PyObject *arglist, *result;
43    PyObject *func = (PyObject *)arg;
44
45    arglist = Py_BuildValue("()");
46
47    result = PyEval_CallObject(func, arglist);
48    Py_DECREF(arglist);
49
50    if (result)
51    {
52       Py_XDECREF(result);
53    }
54    else
55    {
56       if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
57       {
58          std::cerr << "Caught a Ctrl-C within python, exiting program.\n";
59          Py_Exit(1);
60       }
61       PyErr_Print();
62    }
63 }
64
65 void gdcmPythonVoidFuncArgDelete(void *arg)
66 {
67    PyObject *func = (PyObject *)arg;
68    if (func)
69    {
70       Py_DECREF(func);
71    }
72 }
73
74 /// This is required in order to avoid %including all the gdcm include files.
75 using namespace gdcm;
76 %}
77
78
79 ///////////////////////  typemap section  ////////////////////////////////////
80
81 ////////////////////////////////////////////////
82 // Redefine all types used
83 typedef char int8_t;
84 typedef unsigned char uint8_t;
85 typedef short int16_t;
86 typedef unsigned short uint16_t;
87 typedef int int32_t;
88 typedef unsigned int uint32_t;
89 typedef long long int64_t;
90 typedef unsigned long long uint64_t;
91
92 ////////////////////////////////////////////////
93 // Convert a DocEntry * to the real derived class
94 %typemap(out) gdcm::DocEntry * 
95 {
96    PyObject *newEntry;
97
98    if($1)
99    {
100       if(dynamic_cast<SeqEntry *>($1)) // SeqEntry *
101          newEntry = SWIG_NewPointerObj($1,SWIGTYPE_p_gdcm__SeqEntry,0);
102       else if(dynamic_cast<BinEntry *>($1)) // BinEntry *
103          newEntry = SWIG_NewPointerObj($1,SWIGTYPE_p_gdcm__BinEntry,0);
104       else // ValEntry *
105          newEntry = SWIG_NewPointerObj($1,SWIGTYPE_p_gdcm__ValEntry,0);
106    }
107    else
108    {
109       newEntry = Py_BuildValue("");
110    }
111    $result = newEntry;
112 }
113
114 ////////////////////////////////////////////////
115 // Convert an STL list<> to a python native list
116 //%typemap(out) std::list<std::string> * 
117 //{
118 //   PyObject *newItem = (PyObject *)0;
119 //   PyObject *newList = PyList_New(0); // The result of this typemap
120 //
121 //   for (std::list<std::string>::iterator strIt = ($1)->begin();
122 //        strIt != ($1)->end();
123 //        ++strIt)
124 //   {
125 //      newItem = PyString_FromString(strIt->c_str());
126 //      PyList_Append( newList, newItem);
127 //   }
128 //   $result = newList;
129 //}
130
131 //////////////////////////////////////////////////////////////////
132 // Convert an STL map<> (hash table) to a python native dictionary
133 //%typemap(out) std::map<std::string, std::list<std::string> > * 
134 //{
135 //   PyObject *newDict = PyDict_New(); // The result of this typemap
136 //   PyObject *newKey = (PyObject *)0;
137 //   PyObject *newVal = (PyObject *)0;
138 //
139 //   for (std::map<std::string,
140 //        std::list<std::string> >::iterator tag = ($1)->begin();
141 //        tag != ($1)->end(); ++tag)
142 //   {
143 //      std::string first = tag->first;
144 //      // Do not publish entries whose keys is made of spaces
145 //      if (first.length() == 0)
146 //         continue;
147 //      newKey = PyString_FromString(first.c_str());
148 //
149 //      PyObject *newList = PyList_New(0);
150 //      for (std::list<std::string>::iterator itemIt = tag->second.begin();
151 //           itemIt != tag->second.end();
152 //           ++itemIt)
153 //      {
154 //         newVal = PyString_FromString(itemIt->c_str());
155 //         PyList_Append( newList, newVal);
156 //      }
157 //      PyDict_SetItem( newDict, newKey, newList);
158 //   }
159 //   $result = newDict;
160 //}
161
162 /////////////////////////////////////////////////////////
163 // Convert a c++ hash table in a python native dictionary
164 //%typemap(out) gdcm::TagDocEntryHT & 
165 //{
166 //   PyObject *newDict = PyDict_New(); // The result of this typemap
167 //   std::string rawName;              // Element name as gotten from gdcm
168 //   PyObject *newKey = (PyObject *)0; // Associated name as python object
169 //   std::string rawValue;             // Element value as gotten from gdcm
170 //   PyObject *newVal = (PyObject *)0; // Associated value as python object
171 //
172 //   for (gdcm::TagDocEntryHT::iterator tag = $1->begin(); tag != $1->end(); ++tag)
173 //   {
174 //      // The element name shall be the key:
175 //      rawName = tag->second->GetName();
176 //      // gdcm unrecognized (including not loaded because their size exceeds
177 //      // the user specified treshold) elements are exported with their
178 //      // TagKey as key.
179 //      if (rawName == "Unknown")
180 //         rawName = tag->second->GetKey();
181 //      newKey = PyString_FromString(rawName.c_str());
182 //
183 //      // Element values are striped from leading/trailing spaces
184 //      gdcm::ValEntry *valEntryPtr = dynamic_cast< gdcm::ValEntry* >(tag->second);
185 //      if ( valEntryPtr )
186 //      {
187 //         rawValue = valEntryPtr->GetValue();
188 //      }
189 //      else
190 //        continue; 
191 //      newVal = PyString_FromString(rawValue.c_str());
192 //      PyDict_SetItem( newDict, newKey, newVal);
193 //   }
194 //   $result = newDict;
195 //}
196
197 /////////////////////////////////////
198 //%typemap(out) ListDicomDirPatient & 
199 //{
200 //      PyObject *newItem = (PyObject *)0;
201 //      $result = PyList_New(0); // The result of this typemap
202 //
203 //      for (std::list<gdcm::DicomDirPatient *>::iterator newIt = ($1)->begin();
204 //          newIt != ($1)->end(); ++newIt)
205 //   {
206 //              newItem = SWIG_NewPointerObj(*newIt,SWIGTYPE_p_DicomDirPatient,0);
207 //              PyList_Append($result, newItem);
208 //      }
209 //}
210
211 //%typemap(out) ListDicomDirStudy & 
212 //{
213 //      PyObject *newItem = (PyObject *)0;
214 //      $result = PyList_New(0); // The result of this typemap
215 //
216 //      for (std::list<gdcm::DicomDirStudy *>::iterator newIt = ($1)->begin();
217 //          newIt != ($1)->end(); ++newIt)
218 //   {
219 //              newItem = SWIG_NewPointerObj(*newIt,SWIGTYPE_p_DicomDirStudy,0);
220 //              PyList_Append($result, newItem);
221 //      }
222 //}
223
224 //%typemap(out) ListDicomDirSerie & 
225 //{
226 //      PyObject* newItem = (PyObject*)0;
227 //      $result = PyList_New(0); // The result of this typemap
228 //
229 //      for (std::list<gdcm::DicomDirSerie *>::iterator newIt = ($1)->begin();
230 //          newIt != ($1)->end(); ++newIt)
231 //   {
232 //              newItem = SWIG_NewPointerObj(*newIt,SWIGTYPE_p_DicomDirSerie,0);
233 //              PyList_Append($result, newItem);
234 //      }
235 //}
236
237 //%typemap(out) ListDicomDirImage & 
238 //{
239 //      PyObject* newItem = (PyObject*)0;
240 //      $result = PyList_New(0); // The result of this typemap
241 //
242 //      for (std::list<gdcm::DicomDirImage *>::iterator newIt = ($1)->begin();
243 //          newIt != ($1)->end(); ++newIt) 
244 //   {
245 //              newItem = SWIG_NewPointerObj(*newIt,SWIGTYPE_p_DicomDirImage,0);
246 //              PyList_Append($result, newItem);
247 //      }
248 //}
249
250 ////////////////////////////////////////////////////////////////////////////
251 // Multi-argument typemap designed for wrapping the progress related methods
252 // in order to control from an external application the computation of
253 // a DicomDir object (see DicomDir::SetStartMethod*,
254 // DicomDir::SetProgressMethod* and DicomDir::SetEndMethod*).
255 // Motivation: since DicomDir parsing can be quite long, a GUI application
256 //             needs to display the avancement and potentially offer a
257 //             cancel method to the user (when this one feels things are
258 //             longer than expected).
259 // Example of usage: refer to demo/DicomDirProgressMethod.py
260 // Note: Uses gdcmPythonVoidFunc and gdcmPythonVoidFuncArgDelete defined
261 //       in the Swig verbatim section of this gdcm.i i.e. in the above section
262 //       enclosed within the %{ ... %} scope operator ).
263 %typemap(python, in) ( gdcm::DicomDir::Method *, 
264                        void * = NULL, 
265                        gdcm::DicomDir::Method * = NULL )
266 {
267         if($input!=Py_None)
268         {
269                 Py_INCREF($input);
270                 $1=gdcmPythonVoidFunc;
271                 $2=$input;
272                 $3=gdcmPythonVoidFuncArgDelete;
273         }
274         else
275         {
276                 $1=NULL;
277                 $2=NULL;
278                 $3=NULL;
279         }
280 }
281
282 ////////////////////  STL string versus Python str  ////////////////////////
283 // Convertion returning a C++ string.
284 %typemap(out) std::string
285 {
286     $result = PyString_FromString(($1).c_str());
287 }
288
289 %typemap(out) string
290 {
291     $result = PyString_FromString(($1).c_str());
292 }
293
294 %typemap(out) std::string const &
295 {
296     $result = PyString_FromString(($1)->c_str());
297 }
298
299 // Convertion of incoming Python str to STL string
300 %typemap(python, in) const std::string, std::string
301 {
302   $1 = PyString_AsString($input);
303 }
304
305 // Same convertion as above but references (since swig converts C++
306 // refererences to pointers)
307 %typemap(python, in) std::string const &
308 {
309    $1 = new std::string( PyString_AsString( $input ) );
310 }
311
312 ////////////////////  gdcm.TagName versus Python str  //////////////////////
313 %typemap(out) gdcm::TagName, const gdcm::TagName &
314 {
315     $result = PyString_FromString(($1)->c_str());
316 }
317
318 // Convertion of incoming Python str to STL string
319 %typemap(python, in) const gdcm::TagName, gdcm::TagName
320 {
321   $1 = PyString_AsString($input);
322 }
323
324 // Same convertion as above but references (since swig converts C++
325 // refererences to pointers)
326 %typemap(python, in) gdcm::TagName const &
327 {
328    $1 = new std::string( PyString_AsString( $input ) );
329 }
330
331
332 ////////////////////////////////////////////////////////////////////////////
333 // Because overloading and %rename don't work together (see below Note 1)
334 // we need to ignore some methods (e.g. the overloaded default constructor).
335 // The gdcm::File class doesn't have any SetFilename method anyhow, and
336 // this constructor is only used internaly (not from the API) so this is
337 // not a big loss.
338 %ignore gdcm::binary_write(std::ostream &,uint32_t const &);
339 %ignore gdcm::binary_write(std::ostream &,uint16_t const &);
340
341 %ignore gdcm::File::File();
342 %ignore gdcm::DicomDir::DicomDir();
343
344 // Ignore all placed in gdcmCommon.h
345 %ignore GDCM_UNKNOWN;
346 %ignore GDCM_UNFOUND;
347 %ignore GDCM_BINLOADED;
348 %ignore GDCM_NOTLOADED;
349 %ignore GDCM_UNREAD;
350
351 ////////////////////////////////////////////////////////////////////////////
352 // Warning: Order matters !
353 %include "gdcmCommon.h"
354 %include "gdcmBase.h"
355 %include "gdcmDictEntry.h"
356 %include "gdcmDict.h"
357 %include "gdcmDictSet.h"
358 %include "gdcmDocEntrySet.h"
359 %include "gdcmElementSet.h"
360 %include "gdcmSQItem.h"
361 %include "gdcmDicomDirElement.h"
362 %include "gdcmDicomDirObject.h"
363 %include "gdcmDicomDirImage.h"
364 %include "gdcmDicomDirSerie.h"
365 %include "gdcmDicomDirStudy.h"
366 %include "gdcmDicomDirPatient.h"
367 %include "gdcmDicomDirMeta.h"
368 %include "gdcmDocument.h"
369 %include "gdcmFile.h"
370 %include "gdcmSerieHelper.h"
371 %include "gdcmFile.h"
372 %include "gdcmUtil.h"
373 %include "gdcmGlobal.h"
374 %include "gdcmDicomDir.h"
375 %include "gdcmDocEntry.h"
376 %include "gdcmContentEntry.h"
377 %include "gdcmValEntry.h"
378 %include "gdcmBinEntry.h"
379 %include "gdcmSeqEntry.h"
380
381 ////////////////////////////////////////////////////////////////////////////
382 // Notes on swig and this file gdcm.i:
383 //
384 /////////////////////////////////////
385 // Note 1: swig collision of method overloading and %typemap
386 // Consider the following junk.i file:
387 //     %module junk
388 //     %{
389 //     #include <string>
390 //     #include <iostream>
391 //     void Junk(std::string const & bozo) { std::cout << bozo << std::endl; }
392 //     void Junk() { std::cout << "Renamed Junk()" << std::endl; }
393 //     %}
394 //   
395 //     %typemap(python, in) std::string const &
396 //     {
397 //     $1 = new std::string( PyString_AsString( $input ) );
398 //     }
399 //     void Junk();
400 //     void Junk(std::string const & bozo);
401 //
402 // that we compile on linux with:
403 //    swig -c++ -python junk.i
404 //    g++ -g -I/usr/include/python2.3/ -o junk_wrap.o -c junk_wrap.cxx
405 //    g++ junk_wrap.o -shared -g -o _junk.so -L/usr/lib/python2.3/config \
406 //        -lpython2.3
407 // and invoque with:
408 //    python -c 'from junk import *; Junk("aaa") '
409 // then we get the following unexpected (for novice) python TypeError:
410 //    TypeError: No matching function for overloaded 'Junk'
411 //
412 // This happens because the swig generated code (at least for python) does
413 // the following two stage process:
414 //   1/ first do a dynamic dispatch ON THE NUMBER OF ARGUMENTS of the overloaded
415 //      Junk function (the same happens with method of course). [Note that the
416 //      dispatch is NOT done on the type of the arguments].
417 //   2/ second apply the typemap.
418 // When the first dynamic dispatch is executed, the swig generated code
419 // has no knowledge of the typemap, and thus expects a pointer to a std::string
420 // type i.e. an argument to Junk of the form _p_std__int<address>. But this
421 // is not what python handles to Junk ! An invocation of the form 'Junk("aaa")'
422 // will make Python pass a PyString to swig (and this is precisely why we
423 // wrote the typemap). And this will fail....
424 /////////////////////////////////////