[Insight-developers] CMake questions related to SimpleITK C# wrapping

Dan Mueller dan.muel at gmail.com
Sat Jun 18 01:17:07 EDT 2011


Hi Insight Developers,

I have found some time here and there to fix/improve SimpleITK C#
wrapping -- I can now generate SimpleITK C# wrappers on Windows using
.NET or Mono, and on Linux using Mono.

However, I still have a number of minor issues for which I need some advice:

1. LIBRARY_OUTPUT_DIRECTORY in Visual Studio:
At CMake configure/generate time, I add a custom command (via the
swig_add_module macro):
    swig_add_module(SimpleITKCSharpNative csharp SimpleITK.i)
For various reasons I need to force the output directory:
    set_target_properties(SimpleITKCSharpNative PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CSHARP_BINARY_DIRECTORY})
where CSHARP_BINARY_DIRECTORY =  /SimpleITK/Build/Wrapping/CSharpBinaries

Under Linux the C# binary is nicely created in:
    /SimpleITK/Build/Wrapping/CSharpBinaries
However, under Windows (using Visual Studio 10 generator) the binary
is created in:
    /SimpleITK/Build/Wrapping/CSharpBinaries/Release
(notice the configuration name "Release" at the end).

Why is $(Configuration) added to the library output path? Can I prevent this?
(This is not a big deal, but it requires yet another "if (WIN32)"
check in the CMakeLists.txt which I'd prefer to avoid...)

2. Determining the platform in Linux:
On Windows using Visual Studio generator, there is a VS macro
$(PlatformShortName) which allows me to detect the platform name (x86
or x64), eg:
   add_custom_command(
    COMMENT "Compiling C# ${type} ${name}"
    OUTPUT ${name}.${output}
    COMMAND ${CSHARP_COMPILER}
    ARGS /t:${type} /out:${name}.${output}
/platform:$(PlatformShortName) ${refs} ${sources} # <<< Use platform
here
    WORKING_DIRECTORY ${CSHARP_BINARY_DIRECTORY}
    DEPENDS "${sources_dep}"
  )

Is there an equivalent to $(PlatformShortName) in UNIX make files? How
can I determine the platform at CMake configuration/generation time
and/or compile time under Linux?

3. PixelIDValueEnum is too complex for some parsers/compilers:
sitkPixelIDValues.h defines the following enum:
  enum PixelIDValueEnum {
    sitkUnknown = -1,
    sitkUInt8 = PixelIDToPixelIDValue< BasicPixelID<uint8_t>
>::Result,   // Unsigned 8 bit integer
    sitkInt8 = PixelIDToPixelIDValue< BasicPixelID<int8_t> >::Result,
   // Signed 8 bit integer
    sitkUInt16 = PixelIDToPixelIDValue< BasicPixelID<uint16_t>
>::Result, // Unsigned 16 bit integer
    ...
  }

I get a number of strange issues related to the (complex) nature of
the templated code assigning the enum values.

These issues are two fold:
(a) the SWIG parser does not seem to be able to determine the integer
enum value. Here is the invalid C# code it generates:
  public enum PixelIDValueEnum {
    sitkUnknown = -1,
    sitkUInt8 = PixelIDToPixelIDValue<(BasicPixelID<(uint8_t)>)>::Result,
    sitkInt8 = PixelIDToPixelIDValue<(BasicPixelID<(int8_t)>)>::Result,
    ...
  }
SWIG should be generating code like this (and does so nicely for other
simpler SimpleITK enums):
  public enum PixelIDValueEnum {
    sitkUnknown = -1,
    sitkUInt8 = 1,
    sitkInt8 = 2,
    ...
  }
Fortunately I can turn on "type safe enum" wrapping, which generates
valid (but not so nice) C# code like this:
  public sealed class PixelIDValueEnum {
    public static readonly PixelIDValueEnum sitkUnknown = new
PixelIDValueEnum("sitkUnknown", SimpleITKPINVOKE.sitkUnknown_get());
    public static readonly PixelIDValueEnum sitkUInt8 = new
PixelIDValueEnum("sitkUInt8", SimpleITKPINVOKE.sitkUInt8_get());
    public static readonly PixelIDValueEnum sitkInt8 = new
PixelIDValueEnum("sitkInt8", SimpleITKPINVOKE.sitkInt8_get());
    ...
  }

(b) When compiling SimpleITK on Linux, I get lots of warnings stemming
from PixelIDValueEnum:
gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)

In file included from
/home/dan/ITK/SimpleITK/Code/Common/sitkMemberFunctionFactory.h:145:0,
                 from /home/dan/ITK/SimpleITK/Code/Common/sitkImage.cxx:2:
/home/dan/ITK/SimpleITK/Code/Common/sitkMemberFunctionFactory.txx: In
member function ‘void
itk::simple::detail::MemberFunctionFactory<TMemberFunctionPointer>::Register(MemberFunctionType,
TImageType*) [with TImageType = itk::Image<signed char, 3u>,
TMemberFunctionPointer = void (itk::simple::Image::*)(unsigned int,
unsigned int, unsigned int), MemberFunctionType = void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)]’:
/home/dan/ITK/SimpleITK/Code/Common/sitkMemberFunctionFactory.txx:41:7:
  instantiated from ‘typename
itk::simple::EnableIf<itk::simple::IsInstantiated<typename
itk::simple::PixelIDToImageType<TPixelIDType,
VImageDimension>::ImageType>::Value>::Type
itk::simple::detail::MemberFunctionInstantiater<TMemberFunctionFactory,
VImageDimension, TAddressor>::operator()(TPixelIDType*) const [with
TPixelIDType = itk::simple::BasicPixelID<signed char>,
TMemberFunctionFactory =
itk::simple::detail::MemberFunctionFactory<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)>,
unsigned int VImageDimension = 3u, TAddressor =
itk::simple::Image::AllocateMemberFunctionAddressor<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)>,
typename itk::simple::EnableIf<itk::simple::IsInstantiated<typename
itk::simple::PixelIDToImageType<TPixelIDType,
VImageDimension>::ImageType>::Value>::Type = void]’
/home/dan/ITK/SimpleITK/Code/Common/Ancillary/TypeList.h:306:5:
instantiated from ‘void typelist::Visit<TTypeList>::operator()(const
Predicate&) [with Predicate =
itk::simple::detail::MemberFunctionInstantiater<itk::simple::detail::MemberFunctionFactory<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)>,
3u, itk::simple::Image::AllocateMemberFunctionAddressor<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)> >,
TTypeList = typelist::TypeList<itk::simple::BasicPixelID<signed char>,
typelist::TypeList<itk::simple::BasicPixelID<unsigned char>,
typelist::TypeList<itk::simple::BasicPixelID<short int>,
typelist::TypeList<itk::simple::BasicPixelID<short unsigned int>,
typelist::TypeList<itk::simple::BasicPixelID<int>,
typelist::TypeList<itk::simple::BasicPixelID<unsigned int>,
typelist::TypeList<itk::simple::BasicPixelID<float>,
typelist::TypeList<itk::simple::BasicPixelID<double>,
typelist::TypeList<itk::simple::BasicPixelID<std::complex<float> >,
typelist::TypeList<itk::simple::BasicPixelID<std::complex<double> >,
typelist::TypeList<itk::simple::VectorPixelID<signed char>,
typelist::TypeList<itk::simple::VectorPixelID<unsigned char>,
typelist::TypeList<itk::simple::VectorPixelID<short int>,
typelist::TypeList<itk::simple::VectorPixelID<short unsigned int>,
typelist::TypeList<itk::simple::VectorPixelID<float>,
typelist::TypeList<itk::simple::VectorPixelID<double>,
typelist::TypeList<itk::simple::LabelPixelID<unsigned char>,
typelist::TypeList<itk::simple::LabelPixelID<short unsigned int>,
typelist::TypeList<itk::simple::LabelPixelID<unsigned int>,
typelist::NullType> > > > > > > > > > > > > > > > > > >]’
/home/dan/ITK/SimpleITK/Code/Common/sitkMemberFunctionFactory.txx:106:3:
  instantiated from ‘void
itk::simple::detail::MemberFunctionFactory<TMemberFunctionPointer>::RegisterMemberFunctions()
[with TPixelIDTypeList =
typelist::TypeList<itk::simple::BasicPixelID<signed char>,
typelist::TypeList<itk::simple::BasicPixelID<unsigned char>,
typelist::TypeList<itk::simple::BasicPixelID<short int>,
typelist::TypeList<itk::simple::BasicPixelID<short unsigned int>,
typelist::TypeList<itk::simple::BasicPixelID<int>,
typelist::TypeList<itk::simple::BasicPixelID<unsigned int>,
typelist::TypeList<itk::simple::BasicPixelID<float>,
typelist::TypeList<itk::simple::BasicPixelID<double>,
typelist::TypeList<itk::simple::BasicPixelID<std::complex<float> >,
typelist::TypeList<itk::simple::BasicPixelID<std::complex<double> >,
typelist::TypeList<itk::simple::VectorPixelID<signed char>,
typelist::TypeList<itk::simple::VectorPixelID<unsigned char>,
typelist::TypeList<itk::simple::VectorPixelID<short int>,
typelist::TypeList<itk::simple::VectorPixelID<short unsigned int>,
typelist::TypeList<itk::simple::VectorPixelID<float>,
typelist::TypeList<itk::simple::VectorPixelID<double>,
typelist::TypeList<itk::simple::LabelPixelID<unsigned char>,
typelist::TypeList<itk::simple::LabelPixelID<short unsigned int>,
typelist::TypeList<itk::simple::LabelPixelID<unsigned int>,
typelist::NullType> > > > > > > > > > > > > > > > > > >, unsigned int
VImageDimension = 3u, TAddressor =
itk::simple::Image::AllocateMemberFunctionAddressor<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)>,
TMemberFunctionPointer = void (itk::simple::Image::*)(unsigned int,
unsigned int, unsigned int)]’
/home/dan/ITK/SimpleITK/Code/Common/sitkImage.cxx:541:96:
instantiated from here
/home/dan/ITK/SimpleITK/Code/Common/sitkMemberFunctionFactory.txx:86:7:
warning: case value ‘2’ not in enumerated type ‘itk::Image<signed
char, 3u>::<anonymous enum>’
/home/dan/ITK/SimpleITK/Code/Common/sitkMemberFunctionFactory.txx: In
member function ‘void
itk::simple::detail::MemberFunctionFactory<TMemberFunctionPointer>::Register(MemberFunctionType,
TImageType*) [with TImageType = itk::Image<signed char, 2u>,
TMemberFunctionPointer = void (itk::simple::Image::*)(unsigned int,
unsigned int, unsigned int), MemberFunctionType = void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)]’:
/home/dan/ITK/SimpleITK/Code/Common/sitkMemberFunctionFactory.txx:41:7:
  instantiated from ‘typename
itk::simple::EnableIf<itk::simple::IsInstantiated<typename
itk::simple::PixelIDToImageType<TPixelIDType,
VImageDimension>::ImageType>::Value>::Type
itk::simple::detail::MemberFunctionInstantiater<TMemberFunctionFactory,
VImageDimension, TAddressor>::operator()(TPixelIDType*) const [with
TPixelIDType = itk::simple::BasicPixelID<signed char>,
TMemberFunctionFactory =
itk::simple::detail::MemberFunctionFactory<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)>,
unsigned int VImageDimension = 2u, TAddressor =
itk::simple::Image::AllocateMemberFunctionAddressor<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)>,
typename itk::simple::EnableIf<itk::simple::IsInstantiated<typename
itk::simple::PixelIDToImageType<TPixelIDType,
VImageDimension>::ImageType>::Value>::Type = void]’
/home/dan/ITK/SimpleITK/Code/Common/Ancillary/TypeList.h:306:5:
instantiated from ‘void typelist::Visit<TTypeList>::operator()(const
Predicate&) [with Predicate =
itk::simple::detail::MemberFunctionInstantiater<itk::simple::detail::MemberFunctionFactory<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)>,
2u, itk::simple::Image::AllocateMemberFunctionAddressor<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)> >,
TTypeList = typelist::TypeList<itk::simple::BasicPixelID<signed char>,
typelist::TypeList<itk::simple::BasicPixelID<unsigned char>,
typelist::TypeList<itk::simple::BasicPixelID<short int>,
typelist::TypeList<itk::simple::BasicPixelID<short unsigned int>,
typelist::TypeList<itk::simple::BasicPixelID<int>,
typelist::TypeList<itk::simple::BasicPixelID<unsigned int>,
typelist::TypeList<itk::simple::BasicPixelID<float>,
typelist::TypeList<itk::simple::BasicPixelID<double>,
typelist::TypeList<itk::simple::BasicPixelID<std::complex<float> >,
typelist::TypeList<itk::simple::BasicPixelID<std::complex<double> >,
typelist::TypeList<itk::simple::VectorPixelID<signed char>,
typelist::TypeList<itk::simple::VectorPixelID<unsigned char>,
typelist::TypeList<itk::simple::VectorPixelID<short int>,
typelist::TypeList<itk::simple::VectorPixelID<short unsigned int>,
typelist::TypeList<itk::simple::VectorPixelID<float>,
typelist::TypeList<itk::simple::VectorPixelID<double>,
typelist::TypeList<itk::simple::LabelPixelID<unsigned char>,
typelist::TypeList<itk::simple::LabelPixelID<short unsigned int>,
typelist::TypeList<itk::simple::LabelPixelID<unsigned int>,
typelist::NullType> > > > > > > > > > > > > > > > > > >]’
/home/dan/ITK/SimpleITK/Code/Common/sitkMemberFunctionFactory.txx:106:3:
  instantiated from ‘void
itk::simple::detail::MemberFunctionFactory<TMemberFunctionPointer>::RegisterMemberFunctions()
[with TPixelIDTypeList =
typelist::TypeList<itk::simple::BasicPixelID<signed char>,
typelist::TypeList<itk::simple::BasicPixelID<unsigned char>,
typelist::TypeList<itk::simple::BasicPixelID<short int>,
typelist::TypeList<itk::simple::BasicPixelID<short unsigned int>,
typelist::TypeList<itk::simple::BasicPixelID<int>,
typelist::TypeList<itk::simple::BasicPixelID<unsigned int>,
typelist::TypeList<itk::simple::BasicPixelID<float>,
typelist::TypeList<itk::simple::BasicPixelID<double>,
typelist::TypeList<itk::simple::BasicPixelID<std::complex<float> >,
typelist::TypeList<itk::simple::BasicPixelID<std::complex<double> >,
typelist::TypeList<itk::simple::VectorPixelID<signed char>,
typelist::TypeList<itk::simple::VectorPixelID<unsigned char>,
typelist::TypeList<itk::simple::VectorPixelID<short int>,
typelist::TypeList<itk::simple::VectorPixelID<short unsigned int>,
typelist::TypeList<itk::simple::VectorPixelID<float>,
typelist::TypeList<itk::simple::VectorPixelID<double>,
typelist::TypeList<itk::simple::LabelPixelID<unsigned char>,
typelist::TypeList<itk::simple::LabelPixelID<short unsigned int>,
typelist::TypeList<itk::simple::LabelPixelID<unsigned int>,
typelist::NullType> > > > > > > > > > > > > > > > > > >, unsigned int
VImageDimension = 2u, TAddressor =
itk::simple::Image::AllocateMemberFunctionAddressor<void
(itk::simple::Image::*)(unsigned int, unsigned int, unsigned int)>,
TMemberFunctionPointer = void (itk::simple::Image::*)(unsigned int,
unsigned int, unsigned int)]’

I'm not sure anything can be done to help SWIG or gcc with the
PixelIDValueEnum complexities, but I thought I should mention it...

4. Process for contributing changes:
I guess this is a question for the SimpleITK people...
What is the process to contribute these changes? I have cloned the
SimpleITK.git repository and have made the changes against this. Do I
simply push them to gerrit for review?

5. SimpleITK stability:
At the moment there is only one C# example.
How stable is SimpleITK? Is it stable enough that I can spend some
time writing more C# examples? Or will things change?

Thanks in advance for any advice.

Regards, Dan


More information about the Insight-developers mailing list