+2003-01-17 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+ * python/distutilsSwigCPlusPlus.py now properly collects the
+ shadow classes generated by "swig -c++" (gdcm.py in our case)
+ when using "python setup.py install".
+ * python/gdcmPython/__init__.py imports gdcm.py and only manually
+ reexports the working classes.
+ * src/gdcmHeader.cxx all the try/catch/throw calls were replaced
+ by the classical C errno scheme. This is to prevent an obscure
+ behavior of the python wrappers when importing wxPython.wx prior
+ to gdcmPython (which ended up in an abort call). An illustration
+ of this oddity can be found in the Test/ExceptionAndPython
+ subdir (see the README file). This problem probably due to
+ an combination of g++ and dynamic loading.
+ * added Test/ExceptionAndPython (see above)
+
2003-01-17 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
* Changed the layout of the python part to avoid bloating main
directory with setup.py, distutilsSwigCPlusPlus.py, MANIFEST.in
* gdcmPython/__init__.py doesn't export FileName any more (to avoid
collision with other packages). gdcmPython/demo/*.py changed
accordingly.
-
2003-01-15 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
* python subdir moved to gdcmPython (preparation of distutils packaging).
* gdcmPython/setup.py and distutilsSwigCPlusPlus.py added. The
--- /dev/null
+The purpous of this set of files is to illustrate an unexpected behavior
+of exception handling of swig wrapped c++ libraries with wxPython.
+Context:
+ - g++ version 2.96 or 3.2
+ - swig version 1.3.16u
+ - python2.2
+
+Consider the code in one of the foo_main.cxx say foo_main.cxx.minimal:
+ #include <iostream>
+
+ void MyWrappedFunction(void) {
+ try { throw "In thrower"; }
+ catch (const char * str) { cout<<"Exception"<< str << endl; }
+ }
+
+ int main() {
+ MyWrappedFunction();
+ return 0;
+ }
+When compiling this code and executing it one obtains the correct behavior
+of the exception i.e. ExceptionIn thrower.
+Now, wrap the above code with swig and invoque the following python
+script (see test.py):
+ import wxPython.wx
+ import foo
+ foo.MyWrappedFunction()
+Surprisingly enough the exception won't be caugth, but terminate will
+catch it and invoke abort.
+Note that the exception is properly caught when one doesn't import
+wxPython.
+Note that the exception is properly caught when one doesn't import
+wxPython.
+
+In order to play with this example, try the following:
+ln -s foo_main.cxx.minimal foo_main.cxx
+ln -s foo.cxx.minimal foo.cxx
+make
+./main
+ExceptionIn thrower
+python test.py
+
#include "gdcm.h"
#include <stdio.h>
+#include <cerrno>
// For nthos:
#ifdef _MSC_VER
#include <winsock.h>
#define HEADER_LENGTH_TO_READ 256 // on ne lit plus que le debut
#define _MaxSizeLoadElementValue_ 1024 // longueur au dela de laquelle on ne charge plus les valeurs
-namespace Error {
- struct FileReadError {
- FileReadError(FILE* fp, const char* Mesg) {
- if (feof(fp))
- dbg.Verbose(1, "EOF encountered :", Mesg);
- if (ferror(fp))
- dbg.Verbose(1, "Error on reading :", Mesg);
- }
- };
-}
-
//FIXME: this looks dirty to me...
#define str2num(str, typeNum) *((typeNum *)(str))
while ( ! FoundSequenceDelimiter) {
g = ReadInt16();
n = ReadInt16();
+ if (errno == 1)
+ return 0;
TotalLength += 4; // We even have to decount the group and element
if ( g != 0xfffe ) {
dbg.Verbose(1, "gdcmHeader::FindLengthOB: ",
"wrong group for an item sequence.");
- throw Error::FileReadError(fp, "gdcmHeader::FindLengthOB");
+ errno = 1;
+ return 0;
}
if ( n == 0xe0dd )
FoundSequenceDelimiter = true;
else if ( n != 0xe000) {
dbg.Verbose(1, "gdcmHeader::FindLengthOB: ",
"wrong element for an item sequence.");
- throw Error::FileReadError(fp, "gdcmHeader::FindLengthOB");
+ errno = 1;
+ return 0;
}
ItemLength = ReadInt32();
TotalLength += ItemLength + 4; // We add 4 bytes since we just read
// hands on a big endian encoded file: we switch the swap code to
// big endian and proceed...
if ( (element == 0x000) && (length16 == 0x0400) ) {
- if ( ! IsExplicitVRBigEndianTransferSyntax() )
- throw Error::FileReadError(fp, "gdcmHeader::FindLength");
+ if ( ! IsExplicitVRBigEndianTransferSyntax() ) {
+ dbg.Verbose(0, "gdcmHeader::FindLength", "not explicit VR");
+ errno = 1;
+ return;
+ }
length16 = 4;
SwitchSwapToBigEndian();
// Restore the unproperly loaded values i.e. the group, the element
}
// FIXME The exact size should be length if we move to strings or whatever
-
- //
- // QUESTION : y a-t-il une raison pour ne pas utiliser g_malloc ici ?
- //
-
char* NewValue = (char*)malloc(length+1);
if( !NewValue) {
dbg.Verbose(1, "LoadElementValue: Failed to allocate NewValue");
item_read = fread(NewValue, (size_t)length, (size_t)1, fp);
if ( item_read != 1 ) {
free(NewValue);
- Error::FileReadError(fp, "gdcmHeader::LoadElementValue");
+ dbg.Verbose(1, "gdcmHeader::LoadElementValue","unread element value");
ElVal->SetValue("gdcm::UnRead");
return;
}
guint16 g;
size_t item_read;
item_read = fread (&g, (size_t)2,(size_t)1, fp);
- if ( item_read != 1 )
- throw Error::FileReadError(fp, "gdcmHeader::ReadInt16");
+ errno = 0;
+ if ( item_read != 1 ) {
+ dbg.Verbose(1, "gdcmHeader::ReadInt16", " File read error");
+ errno = 1;
+ return 0;
+ }
g = SwapShort(g);
return g;
}
guint32 g;
size_t item_read;
item_read = fread (&g, (size_t)4,(size_t)1, fp);
- if ( item_read != 1 )
- throw Error::FileReadError(fp, "gdcmHeader::ReadInt32");
+ errno = 0;
+ if ( item_read != 1 ) {
+ dbg.Verbose(1, "gdcmHeader::ReadInt32", " File read error");
+ errno = 1;
+ return 0;
+ }
g = SwapLong(g);
return g;
}
guint16 n;
ElValue * NewElVal;
- try {
- g = ReadInt16();
- n = ReadInt16();
- }
- catch ( Error::FileReadError ) {
+ g = ReadInt16();
+ n = ReadInt16();
+ if (errno == 1)
// We reached the EOF (or an error occured) and header parsing
// has to be considered as finished.
return (ElValue *)0;
- }
// Find out if the tag we encountered is in the dictionaries:
gdcmDictEntry * NewTag = IsInDicts(g, n);
}
FindVR(NewElVal);
- try { FindLength(NewElVal); }
- catch ( Error::FileReadError ) { // Call it quits
+ FindLength(NewElVal);
+ if (errno == 1)
+ // Call it quits
return (ElValue *)0;
- }
NewElVal->SetOffset(ftell(fp));
return NewElVal;
}