From: frog Date: Wed, 3 Nov 2004 11:54:42 +0000 (+0000) Subject: Trial to get gdcmPython working. demo/PrintHeader should now work. X-Git-Tag: Version0.6.bp~20 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=aab34dc5c3dbfe96532aa1ff611b00e9cf334758;p=gdcm.git Trial to get gdcmPython working. demo/PrintHeader should now work. --- diff --git a/gdcmPython/README b/gdcmPython/README new file mode 100644 index 00000000..8cecd8e4 --- /dev/null +++ b/gdcmPython/README @@ -0,0 +1,10 @@ +Variables that should be set in order to work with gdcmPython: +GDCM_DICT_PATH path to the dictionary GDCM_SOURCE/Dicts/ +GDCM_DATA_PATH path to gdcmData +PYTHONPATH path to both GDCM_BIN and GDCM_BIN/bin + +e.g. + +export GDCM_DICT_PATH=~/cvs/gdcm/Dicts/ +export GDCM_DATA_PATH=~/cvs/gdcmData/ +export PYTHONPATH=~/cvs/gdcmbin/bin:~/cvs/gdcmbin/ diff --git a/gdcmPython/demo/PrintHeader.py b/gdcmPython/demo/PrintHeader.py index 65698538..3239266f 100644 --- a/gdcmPython/demo/PrintHeader.py +++ b/gdcmPython/demo/PrintHeader.py @@ -21,7 +21,8 @@ except IndexError: #s = raw_input("Hit any key in this window to exit") ### Build the header element list -toRead = gdcmHeader(FileName) +print FileName, type(FileName) +toRead = gdcm.Header(FileName) if not toRead.IsReadable(): print "The ", FileName, " file is not readable with gdcm. Sorry." sys.exit() diff --git a/gdcmPython/gdcm.i b/gdcmPython/gdcm.i index 9ebe8b90..f56077fb 100644 --- a/gdcmPython/gdcm.i +++ b/gdcmPython/gdcm.i @@ -74,6 +74,7 @@ typedef unsigned short guint16; typedef unsigned int guint32; //////////////////////////////////////////////////////////////////////////// +// Convert an STL list<> to a python native list %typemap(out) std::list * { PyObject* NewItem = (PyObject*)0; PyObject* NewList = PyList_New(0); // The result of this typemap @@ -89,7 +90,7 @@ typedef unsigned int guint32; } //////////////////////////////////////////////////////////////////////////// -// Convert a c++ hash table in a python native dictionary +// Convert an STL map<> (hash table) to a python native dictionary %typemap(out) std::map > * { PyObject* NewDict = PyDict_New(); // The result of this typemap PyObject* NewKey = (PyObject*)0; @@ -216,17 +217,33 @@ typedef unsigned int guint32; } -//////////////////////////////////////////////////////////////////////////// -// Deals with function returning a C++ string. +//////////////////// STL string versus Python str //////////////////////// +// Convertion returning a C++ string. %typemap(out) string, std::string { $result = PyString_FromString(($1).c_str()); } +// Convertion of incoming Python str to STL string %typemap(python, in) const std::string, std::string { $1 = PyString_AsString($input); } +// Same convertion as above but references (since swig converts C++ +// refererences to pointers) +%typemap(python, in) std::string const & +{ + $1 = new std::string( PyString_AsString( $input ) ); +} + +//////////////////////////////////////////////////////////////////////////// +// Because overloading and %rename don't work together (see below Note 1) +// we need to ignore the default constructor. +// The gdcm::Header class doesn't have any SetFilename method anyhow, and +// this constructor is only used internaly (not from the API) so this is +// not a big loss. +%ignore gdcm::Header::Header(); + //////////////////////////////////////////////////////////////////////////// // Warning: Order matters ! %include "gdcmCommon.h" @@ -255,3 +272,50 @@ typedef unsigned int guint32; %include "gdcmUtil.h" %include "gdcmGlobal.h" %include "gdcmDicomDir.h" + +//////////////////////////////////////////////////////////////////////////// +// Notes on swig and this file gdcm.i: +// +///////////////////////////////////// +// Note 1: swig collision of method overloading and %typemap +// Consider the following junk.i file: +// %module junk +// %{ +// #include +// #include +// void Junk(std::string const & bozo) { std::cout << bozo << std::endl; } +// void Junk() { std::cout << "Renamed Junk()" << std::endl; } +// %} +// +// %typemap(python, in) std::string const & +// { +// $1 = new std::string( PyString_AsString( $input ) ); +// } +// +add a note on the rename that works ! +// void Junk(); +// void Junk(std::string const & bozo); +// +// that we compile on linux with: +// swig -c++ -python junk.i +// g++ -g -I/usr/include/python2.3/ -o junk_wrap.o -c junk_wrap.cxx +// g++ junk_wrap.o -shared -g -o _junk.so -L/usr/lib/python2.3/config \ +// -lpython2.3 +// and invoque with: +// python -c 'from junk import *; Junk("aaa") ' +// then we get the following unexpected (for novice) python TypeError: +// TypeError: No matching function for overloaded 'Junk' +// +// This happens because the swig generated code (at least for python) does +// the following two stage process: +// 1/ first do a dynamic dispatch ON THE NUMBER OF ARGUMENTS of the overloaded +// Junk function (the same happens with method of course). [Note that the +// dispatch is NOT done on the type of the arguments]. +// 2/ second apply the typemap. +// When the first dynamic dispatch is executed, the swig generated code +// has no knowledge of the typemap, and thus expects a pointer to a std::string +// type i.e. an argument to Junk of the form _p_std__int
. But this +// is not what python handles to Junk ! An invocation of the form 'Junk("aaa")' +// will make Python pass a PyString to swig (and this is precisely why we +// wrote the typemap). And this will fail.... +/////////////////////////////////////