]> Creatis software - gdcm.git/blob - gdcmPython/gdcm.i
ENH: Final -hopefully- change to jpeg lib. In order to match ITK structure, and be...
[gdcm.git] / gdcmPython / gdcm.i
1 %module gdcm
2 %{
3 #include "gdcmCommon.h"
4 #include "gdcmDict.h"
5 #include "gdcmDictEntry.h"
6 #include "gdcmDictSet.h"
7 #include "gdcmDicomDir.h"
8 #include "gdcmDicomDirElement.h"
9 #include "gdcmDicomDirImage.h"
10 #include "gdcmDicomDirMeta.h"
11 #include "gdcmDicomDirObject.h"
12 #include "gdcmDicomDirPatient.h"
13 #include "gdcmDicomDirStudy.h"
14 #include "gdcmDicomDirSerie.h"
15 #include "gdcmDocEntrySet.h"
16 #include "gdcmDocument.h"
17 #include "gdcmElementSet.h"
18 #include "gdcmFile.h"
19 #include "gdcmGlobal.h"
20 #include "gdcmHeader.h"
21 #include "gdcmHeaderHelper.h"
22 #include "gdcmRLEFramesInfo.h"
23 #include "gdcmJPEGFragmentsInfo.h"
24 #include "gdcmSQItem.h"
25 #include "gdcmUtil.h"
26 #include "gdcmValEntry.h"
27
28 ////////////////////////////////////////////////////////////////////////////
29 // Utility functions on strings for removing leading and trailing spaces
30 void EatLeadingAndTrailingSpaces(std::string & s) {
31         while ( s.length() && (s[0] == ' ') )
32                 s.erase(0,1);
33         while ( s.length() && (s[s.length()-1] == ' ') )
34                 s.erase(s.length()-1, 1);
35 }
36
37 void gdcmPythonVoidFunc(void *arg)
38 {
39   PyObject *arglist, *result;
40   PyObject *func = (PyObject *)arg;
41
42   arglist = Py_BuildValue("()");
43
44   result = PyEval_CallObject(func, arglist);
45   Py_DECREF(arglist);
46
47   if (result)
48     {
49     Py_XDECREF(result);
50     }
51   else
52     {
53     if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
54       {
55       std::cerr << "Caught a Ctrl-C within python, exiting program.\n";
56       Py_Exit(1);
57       }
58     PyErr_Print();
59     }
60 }
61
62 void gdcmPythonVoidFuncArgDelete(void *arg)
63 {
64   PyObject *func = (PyObject *)arg;
65   if (func)
66     {
67     Py_DECREF(func);
68     }
69 }
70
71 using namespace gdcm;
72 %}
73 typedef  unsigned short guint16;
74 typedef  unsigned int guint32;
75
76 ////////////////////////////////////////////////////////////////////////////
77 // Convert an STL list<> to a python native list
78 %typemap(out) std::list<std::string> * {
79    PyObject* NewItem = (PyObject*)0;
80    PyObject* NewList = PyList_New(0); // The result of this typemap
81
82    for (std::list<std::string>::iterator NewString = ($1)->begin();
83         NewString != ($1)->end();
84         ++NewString)
85    {
86       NewItem = PyString_FromString(NewString->c_str());
87       PyList_Append( NewList, NewItem);
88    }
89    $result = NewList;
90 }
91
92 ////////////////////////////////////////////////////////////////////////////
93 // Convert an STL map<> (hash table) to a python native dictionary
94 %typemap(out) std::map<std::string, std::list<std::string> > * {
95    PyObject* NewDict = PyDict_New(); // The result of this typemap
96    PyObject* NewKey = (PyObject*)0;
97    PyObject* NewVal = (PyObject*)0;
98
99    for (std::map<std::string,
100         std::list<std::string> >::iterator tag = ($1)->begin();
101         tag != ($1)->end(); ++tag)
102    {
103       std::string first = tag->first;
104       // Do not publish entries whose keys is made of spaces
105       if (first.length() == 0)
106          continue;
107       NewKey = PyString_FromString(first.c_str());
108       PyObject* NewList = PyList_New(0);
109       for (std::list<std::string>::iterator Item = tag->second.begin();
110            Item != tag->second.end();
111            ++Item)
112       {
113          NewVal = PyString_FromString(Item->c_str());
114          PyList_Append( NewList, NewVal);
115       }
116       PyDict_SetItem( NewDict, NewKey, NewList);
117    }
118    $result = NewDict;
119 }
120
121 ////////////////////////////////////////////////////////////////////////////
122 // Convert a c++ hash table in a python native dictionary
123 %typemap(out) gdcm::TagDocEntryHT & {
124    PyObject* NewDict = PyDict_New(); // The result of this typemap
125    std::string RawName;              // Element name as gotten from gdcm
126    PyObject* NewKey = (PyObject*)0;  // Associated name as python object
127    std::string RawValue;             // Element value as gotten from gdcm
128    PyObject* NewVal = (PyObject*)0;  // Associated value as python object
129
130    for (gdcm::TagDocEntryHT::iterator tag = $1->begin(); tag != $1->end(); ++tag)
131    {
132       // The element name shall be the key:
133       RawName = tag->second->GetName();
134       // gdcm unrecognized (including not loaded because their size exceeds
135       // the user specified treshold) elements are exported with their
136       // TagKey as key.
137       if (RawName == "Unknown")
138          RawName = tag->second->GetKey();
139       NewKey = PyString_FromString(RawName.c_str());
140
141       // Element values are striped from leading/trailing spaces
142       if (gdcm::ValEntry* ValEntryPtr =
143                 dynamic_cast< gdcm::ValEntry* >(tag->second) )
144       {
145          RawValue = ValEntryPtr->GetValue();
146       }
147       else
148         continue; 
149       EatLeadingAndTrailingSpaces(RawValue);
150       NewVal = PyString_FromString(RawValue.c_str());
151       PyDict_SetItem( NewDict, NewKey, NewVal);
152    }
153    $result = NewDict;
154 }
155
156 ////////////////////////////////////////////////////////////////////////////
157 %typemap(out) ListDicomDirPatient & {
158         PyObject* NewItem = (PyObject*)0;
159         $result = PyList_New(0); // The result of this typemap
160
161         for (std::list<gdcm::DicomDirPatient *>::iterator New = ($1)->begin();
162             New != ($1)->end(); ++New) {
163                 NewItem = SWIG_NewPointerObj(*New,SWIGTYPE_p_DicomDirPatient,1);
164                 PyList_Append($result, NewItem);
165         }
166 }
167
168 %typemap(out) ListDicomDirStudy & {
169         PyObject* NewItem = (PyObject*)0;
170         $result = PyList_New(0); // The result of this typemap
171
172         for (std::list<gdcm::DicomDirStudy *>::iterator New = ($1)->begin();
173             New != ($1)->end(); ++New) {
174                 NewItem = SWIG_NewPointerObj(*New,SWIGTYPE_p_DicomDirStudy,1);
175                 PyList_Append($result, NewItem);
176         }
177 }
178
179 %typemap(out) ListDicomDirSerie & {
180         PyObject* NewItem = (PyObject*)0;
181         $result = PyList_New(0); // The result of this typemap
182
183         for (std::list<gdcm::DicomDirSerie *>::iterator New = ($1)->begin();
184             New != ($1)->end(); ++New) {
185                 NewItem = SWIG_NewPointerObj(*New,SWIGTYPE_p_DicomDirSerie,1);
186                 PyList_Append($result, NewItem);
187         }
188 }
189
190 %typemap(out) ListDicomDirImage & {
191         PyObject* NewItem = (PyObject*)0;
192         $result = PyList_New(0); // The result of this typemap
193
194         for (std::list<gdcm::DicomDirImage *>::iterator New = ($1)->begin();
195             New != ($1)->end(); ++New) {
196                 NewItem = SWIG_NewPointerObj(*New,SWIGTYPE_p_DicomDirImage,1);
197                 PyList_Append($result, NewItem);
198         }
199 }
200
201 ////////////////////////////////////////////////////////////////////////////
202 // Deals with function returning a C++ string.
203 %typemap(python, in) (gdcm::Method *,void * =NULL,gdcm::Method * =NULL) {
204         if($input!=Py_None)
205         {
206                 Py_INCREF($input);
207                 $1=gdcmPythonVoidFunc;
208                 $2=$input;
209                 $3=gdcmPythonVoidFuncArgDelete;
210         }
211         else
212         {
213                 $1=NULL;
214                 $2=NULL;
215                 $3=NULL;
216         }
217 }
218
219
220 ////////////////////  STL string versus Python str  ////////////////////////
221 // Convertion returning a C++ string.
222 %typemap(out) string, std::string  {
223     $result = PyString_FromString(($1).c_str());
224 }
225
226 // Convertion of incoming Python str to STL string
227 %typemap(python, in) const std::string, std::string
228 {
229   $1 = PyString_AsString($input);
230 }
231
232 // Same convertion as above but references (since swig converts C++
233 // refererences to pointers)
234 %typemap(python, in) std::string const &
235 {
236    $1 = new std::string( PyString_AsString( $input ) );
237 }
238
239 ////////////////////////////////////////////////////////////////////////////
240 // Because overloading and %rename don't work together (see below Note 1)
241 // we need to ignore the default constructor.
242 // The gdcm::Header class doesn't have any SetFilename method anyhow, and
243 // this constructor is only used internaly (not from the API) so this is
244 // not a big loss.
245 %ignore gdcm::Header::Header();
246
247 ////////////////////////////////////////////////////////////////////////////
248 // Warning: Order matters !
249 %include "gdcmCommon.h"
250 %include "gdcmRLEFramesInfo.h"
251 %include "gdcmJPEGFragmentsInfo.h"
252 %include "gdcmDictEntry.h"
253 %include "gdcmDict.h"
254 %include "gdcmDocEntry.h"
255 %include "gdcmDocEntrySet.h"
256 %include "gdcmElementSet.h"
257 %include "gdcmDictSet.h"
258 %include "gdcmTS.h"
259 %include "gdcmVR.h"
260 %include "gdcmSQItem.h"
261 %include "gdcmDicomDirElement.h"
262 %include "gdcmDicomDirObject.h"
263 %include "gdcmDicomDirImage.h"
264 %include "gdcmDicomDirSerie.h"
265 %include "gdcmDicomDirStudy.h"
266 %include "gdcmDicomDirPatient.h"
267 %include "gdcmDicomDirMeta.h"
268 %include "gdcmDocument.h"
269 %include "gdcmHeader.h"
270 %include "gdcmHeaderHelper.h"
271 %include "gdcmFile.h"
272 %include "gdcmUtil.h"
273 %include "gdcmGlobal.h"
274 %include "gdcmDicomDir.h"
275
276 ////////////////////////////////////////////////////////////////////////////
277 // Notes on swig and this file gdcm.i:
278 //
279 /////////////////////////////////////
280 // Note 1: swig collision of method overloading and %typemap
281 // Consider the following junk.i file:
282 //     %module junk
283 //     %{
284 //     #include <string>
285 //     #include <iostream>
286 //     void Junk(std::string const & bozo) { std::cout << bozo << std::endl; }
287 //     void Junk() { std::cout << "Renamed Junk()" << std::endl; }
288 //     %}
289 //   
290 //     %typemap(python, in) std::string const &
291 //     {
292 //     $1 = new std::string( PyString_AsString( $input ) );
293 //     }
294 //   add a note on the rename that works !
295 //     void Junk();
296 //     void Junk(std::string const & bozo);
297 //
298 // that we compile on linux with:
299 //    swig -c++ -python junk.i
300 //    g++ -g -I/usr/include/python2.3/ -o junk_wrap.o -c junk_wrap.cxx
301 //    g++ junk_wrap.o -shared -g -o _junk.so -L/usr/lib/python2.3/config \
302 //        -lpython2.3
303 // and invoque with:
304 //    python -c 'from junk import *; Junk("aaa") '
305 // then we get the following unexpected (for novice) python TypeError:
306 //    TypeError: No matching function for overloaded 'Junk'
307 //
308 // This happens because the swig generated code (at least for python) does
309 // the following two stage process:
310 //   1/ first do a dynamic dispatch ON THE NUMBER OF ARGUMENTS of the overloaded
311 //      Junk function (the same happens with method of course). [Note that the
312 //      dispatch is NOT done on the type of the arguments].
313 //   2/ second apply the typemap.
314 // When the first dynamic dispatch is executed, the swig generated code
315 // has no knowledge of the typemap, and thus expects a pointer to a std::string
316 // type i.e. an argument to Junk of the form _p_std__int<address>. But this
317 // is not what python handles to Junk ! An invocation of the form 'Junk("aaa")'
318 // will make Python pass a PyString to swig (and this is precisely why we
319 // wrote the typemap). And this will fail....
320 /////////////////////////////////////