mummy-1.0.3/0000755000175000017500000000000012120621217012523 5ustar mathieumathieumummy-1.0.3/CMakeLists.txt0000644000175000017500000005361012120621217015270 0ustar mathieumathieuCMAKE_MINIMUM_REQUIRED(VERSION 2.8.3 FATAL_ERROR) PROJECT(Mummy) # Determine if we're building Mummy as a "top level" project. # SET(Mummy_BUILD_IS_TOP_LEVEL 0) IF("${Mummy_BINARY_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") SET(Mummy_BUILD_IS_TOP_LEVEL 1) ENDIF("${Mummy_BINARY_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") # Version number and default installation location: # SET(Mummy_VERSION_MAJOR 1) SET(Mummy_VERSION_MINOR 0) SET(Mummy_VERSION_PATCH 3) SET(Mummy_VERSION_STRING "${Mummy_VERSION_MAJOR}.${Mummy_VERSION_MINOR}.${Mummy_VERSION_PATCH}") IF(Mummy_BUILD_IS_TOP_LEVEL) SET(Mummy_INSTALL_PREFIX "${CMAKE_BINARY_DIR} Install" CACHE STRING "") SET(CMAKE_INSTALL_PREFIX "${Mummy_INSTALL_PREFIX}" CACHE INTERNAL "" FORCE) ENDIF(Mummy_BUILD_IS_TOP_LEVEL) # Source control system keyword substitutions (from the last # time *this* file was committed): # SET(Mummy_SCS_Author "$Author: david.cole $") SET(Mummy_SCS_Date "$Date: 2011-01-27 $") SET(Mummy_SCS_Id "$Id: CMakeLists.txt $") SET(Mummy_SCS_Revision "$Revision: 599 $") SET(Mummy_SCS_URL "$URL: git://public.kitware.com/mummy.git $") # Use these settings when building with the Msvc compiler: # INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/MsvcMacros.cmake") MSVC_LINK_TO_STATIC_CRT() MSVC80_FORCE_MANIFEST_LINKER_FLAG() MSVC_SUPPRESS_CRT_DEPRECATED_WARNINGS() # All exes and libs should end up in the "bin" directory: # IF(NOT EXECUTABLE_OUTPUT_PATH) SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE INTERNAL "Single output directory for building all executables.") ENDIF(NOT EXECUTABLE_OUTPUT_PATH) IF(NOT LIBRARY_OUTPUT_PATH) SET(LIBRARY_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE INTERNAL "Single output directory for building all libraries.") ENDIF(NOT LIBRARY_OUTPUT_PATH) # Name of the library that clients need to link to for building "export layer" # code that links to the mummy runtime library. This values gets configured # into the MummyConfig variable Mummy_RUNTIME_LINK_LIBRARIES. Clients should # link to it with: # # target_link_libraries(ClientExportLayerLib ${Mummy_RUNTIME_LINK_LIBRARIES}) # IF(WIN32) SET(Mummy_RUNTIME_UNMANAGED_LINK_LIBRARY "Kitware.mummy.Runtime.Unmanaged.lib") ELSE() SET(Mummy_RUNTIME_UNMANAGED_LINK_LIBRARY "libKitware.mummy.Runtime.Unmanaged.so") ENDIF() # Sort configuration types according to the order we'd like to find them in # if multiple ones exist in the build tree and we're looking at mummy from # an external project that is trying to use it. # IF(CMAKE_CONFIGURATION_TYPES) SET( Mummy_CMAKE_CONFIGURATION_TYPES "Release" "MinSizeRel" "RelWithDebInfo" "Debug" ) ELSE(CMAKE_CONFIGURATION_TYPES) SET(Mummy_CMAKE_CONFIGURATION_TYPES) ENDIF(CMAKE_CONFIGURATION_TYPES) # 32-bit build? (CableSwig, gccxml and mummy.exe only get built for 32-bit builds. # The mummy Runtime components get built for both 32-bit and 64-bit builds.) # IF(NOT DEFINED Mummy_BUILD_COMPONENT_CABLESWIG) SET(Mummy_BUILD_COMPONENT_CABLESWIG 1) ENDIF(NOT DEFINED Mummy_BUILD_COMPONENT_CABLESWIG) IF(NOT DEFINED Mummy_BUILD_COMPONENT_MUMMY) SET(Mummy_BUILD_COMPONENT_MUMMY 1) ENDIF(NOT DEFINED Mummy_BUILD_COMPONENT_MUMMY) IF(NOT DEFINED Mummy_BUILD_COMPONENT_MUMMY_RUNTIME) SET(Mummy_BUILD_COMPONENT_MUMMY_RUNTIME 1) ENDIF(NOT DEFINED Mummy_BUILD_COMPONENT_MUMMY_RUNTIME) SET(Mummy_32_BIT 1) IF("${CMAKE_GENERATOR}" MATCHES " Win64$") SET(Mummy_32_BIT 0) ENDIF("${CMAKE_GENERATOR}" MATCHES " Win64$") IF("${CMAKE_SIZEOF_VOID_P}" GREATER 4) SET(Mummy_32_BIT 0) ENDIF("${CMAKE_SIZEOF_VOID_P}" GREATER 4) IF(NOT Mummy_32_BIT) IF(Mummy_64_JUST_BUILD_RUNTIME) SET(Mummy_BUILD_COMPONENT_CABLESWIG 0) SET(Mummy_BUILD_COMPONENT_MUMMY 0) ENDIF(Mummy_64_JUST_BUILD_RUNTIME) ENDIF(NOT Mummy_32_BIT) # Provide mummy and C# settings at the top level so runtime, test and # example sub-projects can use them: # INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/CvsMacros.cmake") INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/FindCsharp.cmake") INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/MummyCMakeMacros.cmake") INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/SvnMacros.cmake") SET(mummy_EXECUTABLE "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/mummy${CMAKE_EXECUTABLE_SUFFIX}") # If the parent dir is named exactly "ActiViz" then create external source # trees as siblings of "ActiViz" - otherwise create them as siblings of # "${CMAKE_CURRENT_SOURCE_DIR}" # GET_FILENAME_COMPONENT(Mummy_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PATH) SET(Mummy_REL_EXPR "..") IF("${Mummy_PARENT_DIR}" MATCHES "/ActiViz$") SET(Mummy_REL_EXPR "../..") ENDIF("${Mummy_PARENT_DIR}" MATCHES "/ActiViz$") GET_FILENAME_COMPONENT(Mummy_EXTERNAL_SOURCE_TREES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${Mummy_REL_EXPR}/mummyExternalSourceTrees" ABSOLUTE) SET(Mummy_CableSwig_CVS_REVISION "-D;2009-06-12 20:00:00 UTC") SET(Mummy_CableSwig_PARENT_DIR "${Mummy_EXTERNAL_SOURCE_TREES_DIR}") SET(Mummy_CableSwig_SOURCE_DIR "${Mummy_CableSwig_PARENT_DIR}/CableSwig") SET(Mummy_CableSwig_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/CableSwigBuild") # Echo selected CMake/configuration settings: # FOREACH(v CMAKE_SIZEOF_VOID_P Mummy_32_BIT Mummy_BUILD_COMPONENT_CABLESWIG Mummy_BUILD_COMPONENT_MUMMY Mummy_BUILD_COMPONENT_MUMMY_RUNTIME Mummy_CableSwig_CVS_REVISION Mummy_EXTERNAL_SOURCE_TREES_DIR Mummy_TESTING_CONFIG_PREFIX ) MESSAGE(STATUS "${v}='${${v}}'") ENDFOREACH(v) SET(Mummy_SOURCE_TREE_IS_SVN_CHECKOUT 0) IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn") SET(Mummy_SOURCE_TREE_IS_SVN_CHECKOUT 1) ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn") # Retrieve current state of the source tree according to svn, # if this source tree is an svn checkout. Otherwise, status # is just empty... # SET(Mummy_SVN_STATUS "") IF(Mummy_SOURCE_TREE_IS_SVN_CHECKOUT) SVN_STATUS("${CMAKE_CURRENT_SOURCE_DIR}" Mummy_SVN_STATUS) ENDIF(Mummy_SOURCE_TREE_IS_SVN_CHECKOUT) IF("${Mummy_SVN_STATUS}" STREQUAL "") SET(Mummy_SVN_STATUS_BRIEF "") SET(Mummy_SVN_STATUS_ENCODED "") ELSE("${Mummy_SVN_STATUS}" STREQUAL "") SET(Mummy_SVN_STATUS_BRIEF " [warning: experimental development build!]") STRING(REGEX REPLACE "\\\\" "/" Mummy_SVN_STATUS_ENCODED "${Mummy_SVN_STATUS}") STRING(REGEX REPLACE "\n" "\\\\n" Mummy_SVN_STATUS_ENCODED "${Mummy_SVN_STATUS_ENCODED}") STRING(REGEX REPLACE "\"" "\\\\\"" Mummy_SVN_STATUS_ENCODED "${Mummy_SVN_STATUS_ENCODED}") ENDIF("${Mummy_SVN_STATUS}" STREQUAL "") # Pull in FindSubversion.cmake to get the Subversion_WC_INFO macro: # SET(Mummy_VERSION_SVN_REVISION "599") # # This value is an artificial number that is simply incremented manually # now after switching to git from svn... Whenever we do "real packaging # releases" this number should be incremented manually until this code # is updated to reflect our shiny, new git repo-ness. IF(Mummy_SOURCE_TREE_IS_SVN_CHECKOUT) SET(Subversion_SVN_EXECUTABLE "${svn_EXECUTABLE}") FIND_PACKAGE(Subversion) IF(Subversion_FOUND) Subversion_WC_INFO("${Mummy_SOURCE_DIR}" Mummy) SET(Mummy_VERSION_SVN_REVISION "${Mummy_WC_LAST_CHANGED_REV}") # Now the following variables are available for use: # MESSAGE("Subversion_VERSION_SVN='${Subversion_VERSION_SVN}'") # MESSAGE("Subversion_LAST_CHANGED_LOG='${Subversion_LAST_CHANGED_LOG}'") # MESSAGE("Mummy_WC_INFO='${Mummy_WC_INFO}'") # MESSAGE("Mummy_WC_URL='${Mummy_WC_URL}'") # MESSAGE("Mummy_WC_REVISION='${Mummy_WC_REVISION}'") # MESSAGE("Mummy_WC_LAST_CHANGED_AUTHOR='${Mummy_WC_LAST_CHANGED_AUTHOR}'") # MESSAGE("Mummy_WC_LAST_CHANGED_REV='${Mummy_WC_LAST_CHANGED_REV}'") # MESSAGE("Mummy_WC_LAST_CHANGED_DATE='${Mummy_WC_LAST_CHANGED_DATE}'") ENDIF(Subversion_FOUND) ENDIF(Mummy_SOURCE_TREE_IS_SVN_CHECKOUT) # After getting svn info and status we can set Mummy_FULL_VERSION_STRING: # SET(Mummy_FULL_VERSION_STRING "mummy version ${Mummy_VERSION_STRING} (revision ${Mummy_VERSION_SVN_REVISION})${Mummy_SVN_STATUS_BRIEF}") # Settings required to use the Cable and gxsys libs: # SET(Mummy_include_dirs "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" "${Mummy_CableSwig_SOURCE_DIR}" "${Mummy_CableSwig_SOURCE_DIR}/Cable" "${Mummy_CableSwig_BINARY_DIR}/Cable" "${Mummy_CableSwig_SOURCE_DIR}/Cable/CxxTypes" "${Mummy_CableSwig_SOURCE_DIR}/Cable/Generators" "${Mummy_CableSwig_SOURCE_DIR}/Cable/Parsers" "${Mummy_CableSwig_BINARY_DIR}/GCC_XML" ) INCLUDE_DIRECTORIES(${Mummy_include_dirs}) # Always true - see Cable/CxxTypes/CMakeLists.txt # ADD_DEFINITIONS(-D_cxx_STATIC) # Also, do not install any Cable headers with mummy installation # (also in Cable/CxxTypes/CMakeLists.txt) # SET(CABLE_NO_INSTALL_FACILITIES 1) # "Near copy" of kwsys related settings from CableSwig/GCC_XML/CMakeLists.txt: # SET(Mummy_save_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) SET(BUILD_SHARED_LIBS 0) #SET(LIBRARY_OUTPUT_PATH ${GCCXML_BINARY_DIR}/KWSys) SET(KWSYS_NAMESPACE gxsys) SET(KWSYS_USE_Process 1) SET(KWSYS_USE_RegularExpression 1) SET(KWSYS_USE_SystemTools 1) SET(KWSYS_HEADER_ROOT "${Mummy_CableSwig_BINARY_DIR}/GCC_XML") #IF("${CMAKE_SYSTEM}" MATCHES "AIX") # mummy does not build on AIX # SET(KWSYS_LFS_DISABLE 1) #ENDIF("${CMAKE_SYSTEM}" MATCHES "AIX") #INCLUDE_DIRECTORIES(${GCCXML_BINARY_DIR}) # done later # Make sure gxsys gets built with CommandLineArguments support: # SET(KWSYS_USE_CommandLineArguments 1) # Always enable and build Testing and Documentation if building as a top # level project. # OPTION(Mummy_RUN_LONG_TESTS "Run mummy tests that take more than a few seconds to run..." ON) IF(Mummy_BUILD_IS_TOP_LEVEL) SET(Mummy_BUILD_EXAMPLES 1) # Avoid the "Continuous, Experimental, Nightly and NightlyMemoryCheck" custom # targets for Visual Studio builds: # IF(CMAKE_GENERATOR MATCHES "Visual Studio") IF(COMMAND SET_PROPERTY) SET_PROPERTY(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1) ENDIF(COMMAND SET_PROPERTY) ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio") INCLUDE(CTest) ENABLE_TESTING() SET(Mummy_BUILD_TESTING 1) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake @ONLY ) ENDIF(Mummy_BUILD_IS_TOP_LEVEL) CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/MummyVersion.h.in" "${CMAKE_CURRENT_BINARY_DIR}/MummyVersion.h" @ONLY ) SET(MummyRC_RC_FILE_NAME "MummyExe.rc") SET(MummyRC_FILE_DESCRIPTION "${Mummy_FULL_VERSION_STRING} - command line executable") SET(MummyRC_ORIGINAL_FILENAME "mummy${CMAKE_EXECUTABLE_SUFFIX}") CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/MummyVersion.rc.in" "${CMAKE_CURRENT_BINARY_DIR}/${MummyRC_RC_FILE_NAME}" @ONLY ) # Enable other projects to use mummy via CMake's FIND_PACKAGE(mummy) # CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/MummyConfig.cmake.in ${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/MummyConfig.cmake @ONLY ) # Configure these files (in addition to having custom build/install rules for # them later) so that doing a find_package(Mummy) down in the "Examples" will # be able to read these files during this CMake configure... # foreach(f FindCsharp.cmake MummyCMakeMacros.cmake) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/${f} ${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/${f} COPYONLY ) endforeach() # Get a "known to be good" CableSwig snapshot: # IF(Mummy_BUILD_COMPONENT_CABLESWIG OR Mummy_BUILD_COMPONENT_MUMMY) SET(Mummy_UPDATE_CABLESWIG 1) IF(NOT Mummy_CableSwig_CVS_REVISION STREQUAL "") IF("${Mummy_CableSwig_PARENT_DIR}/CableSwig/CMakeFiles/cvs-up-args.txt" IS_NEWER_THAN "${CMAKE_CURRENT_BINARY_DIR}/MummyVersion.h") SET(Mummy_UPDATE_CABLESWIG 0) ENDIF("${Mummy_CableSwig_PARENT_DIR}/CableSwig/CMakeFiles/cvs-up-args.txt" IS_NEWER_THAN "${CMAKE_CURRENT_BINARY_DIR}/MummyVersion.h") IF(NOT EXISTS "${Mummy_CableSwig_PARENT_DIR}") SET(Mummy_UPDATE_CABLESWIG 1) ENDIF(NOT EXISTS "${Mummy_CableSwig_PARENT_DIR}") ENDIF(NOT Mummy_CableSwig_CVS_REVISION STREQUAL "") IF(Mummy_UPDATE_CABLESWIG) GET_CVS_SNAPSHOT( "${Mummy_CableSwig_PARENT_DIR}" ":pserver:anonymous:@public.kitware.com:/cvsroot/CableSwig" "CableSwig" "${Mummy_CableSwig_CVS_REVISION}" ) ELSE(Mummy_UPDATE_CABLESWIG) MESSAGE(STATUS "CableSwig snapshot already up to date. Skipping cvs update.") ENDIF(Mummy_UPDATE_CABLESWIG) IF(NOT EXISTS "${Mummy_CableSwig_SOURCE_DIR}/CMakeLists.txt") MESSAGE(FATAL_ERROR "error: CableSwig could not be checked out or updated. Check it out or copy it manually to '${Mummy_CableSwig_SOURCE_DIR}'...") ENDIF(NOT EXISTS "${Mummy_CableSwig_SOURCE_DIR}/CMakeLists.txt") ENDIF(Mummy_BUILD_COMPONENT_CABLESWIG OR Mummy_BUILD_COMPONENT_MUMMY) IF(Mummy_BUILD_COMPONENT_CABLESWIG) ADD_SUBDIRECTORY( "${Mummy_CableSwig_SOURCE_DIR}/Cable" "${Mummy_CableSwig_BINARY_DIR}/Cable" ) ADD_SUBDIRECTORY( "${Mummy_CableSwig_SOURCE_DIR}/GCC_XML/KWSys" "${Mummy_CableSwig_BINARY_DIR}/GCC_XML/KWSys" ) # Remove these CableSwig settings from the CMake GUI when configuring Mummy: # MARK_AS_ADVANCED(BISON_YACC) MARK_AS_ADVANCED(CSWIG_USE_SYSTEM_GCCXML) MARK_AS_ADVANCED(SWIG_BUILD_EXAMPLES) ENDIF(Mummy_BUILD_COMPONENT_CABLESWIG) SET(BUILD_SHARED_LIBS ${Mummy_save_BUILD_SHARED_LIBS}) # Don't do these until after including CableSwig because CableSwig presently # has some level 4 warnings when it builds: # MSVC_FORCE_WARNING_LEVEL("4") #MSVC_TREAT_WARNINGS_AS_ERRORS() MACRO(ADD_CUSTOM_COMMAND_COPYFILE srcFile dstFile) ADD_CUSTOM_COMMAND( OUTPUT "${dstFile}" DEPENDS "${srcFile}" COMMAND ${CMAKE_COMMAND} ARGS -E copy "${srcFile}" "${dstFile}" ) ENDMACRO(ADD_CUSTOM_COMMAND_COPYFILE) IF(Mummy_BUILD_COMPONENT_MUMMY) ADD_LIBRARY(mummyLib STATIC MummyApplication.cxx MummyApplication.h MummyCsharpExportLayerGenerator.cxx MummyCsharpExportLayerGenerator.h MummyCsharpGenerator.cxx MummyCsharpGenerator.h MummyCsharpShadowLayerGenerator.cxx MummyCsharpShadowLayerGenerator.h MummyCsharpUnitTestGenerator.cxx MummyCsharpUnitTestGenerator.h MummyDummyGenerator.cxx MummyDummyGenerator.h MummyGenerator.cxx MummyGenerator.h MummyLineOrientedTextFileReader.cxx MummyLineOrientedTextFileReader.h MummyLog.h MummySettings.cxx MummySettings.h MummyUtilities.cxx MummyUtilities.h "${CMAKE_CURRENT_BINARY_DIR}/MummyVersion.h" ) TARGET_LINK_LIBRARIES(mummyLib "CableGenerators" "CableParsers" "CableExpat" "CxxTypes" "gxsys" ) ADD_EXECUTABLE(mummy MummyMain.cxx "${CMAKE_CURRENT_BINARY_DIR}/MummyExe.rc" ) TARGET_LINK_LIBRARIES(mummy "mummyLib" ) # Add custom build steps to copy these include/share files... # Copy them into the build tree in a location that is mirror # to the install tree location -- this will make our build # tree an exact mirror of our install tree and simplify # the code needed in MummyConfig.cmake (if build tree has # exactly the same structure as install tree, then # MummyConfig.cmake does not need two ways of doing things) # # This will be an OK starategy for mummy because the number # of these files is small and build time will be negligible # for these steps. Do not copy this strategy for a project # with hundreds or more installed files... # ADD_CUSTOM_COMMAND_COPYFILE( "${Mummy_SOURCE_DIR}/Runtime/MummyRuntime.h" "${Mummy_BINARY_DIR}/include/mummy-${Mummy_VERSION_STRING}/MummyRuntime.h" ) ADD_CUSTOM_COMMAND_COPYFILE( "${Mummy_SOURCE_DIR}/CSharpTestDriver.cs.in" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/CSharpTestDriver.cs.in" ) ADD_CUSTOM_COMMAND_COPYFILE( "${Mummy_SOURCE_DIR}/FindCsharp.cmake" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/FindCsharp.cmake" ) ADD_CUSTOM_COMMAND_COPYFILE( "${Mummy_SOURCE_DIR}/MummyCMakeMacros.cmake" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/MummyCMakeMacros.cmake" ) ADD_CUSTOM_COMMAND_COPYFILE( "${Mummy_SOURCE_DIR}/SvnMacros.cmake" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/SvnMacros.cmake" ) ADD_CUSTOM_TARGET( Kitware.mummy.CopyFiles ALL DEPENDS "${Mummy_BINARY_DIR}/include/mummy-${Mummy_VERSION_STRING}/MummyRuntime.h" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/CSharpTestDriver.cs.in" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/FindCsharp.cmake" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/MummyCMakeMacros.cmake" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/SvnMacros.cmake" ) ADD_DEPENDENCIES(mummyLib Kitware.mummy.CopyFiles) # If building 32-bit with Visual Studio, then also build the 64-bit # mummy Runtime underneath this binary tree: # IF(Mummy_32_BIT) IF("${CMAKE_GENERATOR}" MATCHES "Visual Studio" AND NOT "${CMAKE_GENERATOR}" MATCHES "Win64") # MCAB variables are "Mummy Configure and Build" variables... # SET(MCAB_BINARY_DIR "${Mummy_BINARY_DIR}/x64Build") SET(MCAB_SCRIPT "${Mummy_BINARY_DIR}/Kitware.mummy.Build.x64.dir/${CMAKE_CFG_INTDIR}/ConfigureAndBuild.cmake") ADD_CUSTOM_COMMAND( OUTPUT ${MCAB_SCRIPT} COMMAND ${CMAKE_COMMAND} ARGS "-DMCAB_BINARY_DIR:PATH=${MCAB_BINARY_DIR}" "-DMCAB_CONFIG:STRING=${CMAKE_CFG_INTDIR}" "-DMCAB_EXECUTABLE_OUTPUT_PATH:PATH=${EXECUTABLE_OUTPUT_PATH}/x64" "-DMCAB_GENERATOR:STRING=${CMAKE_GENERATOR} Win64" "-DMCAB_LIBRARY_OUTPUT_PATH:PATH=${LIBRARY_OUTPUT_PATH}/x64" "-DMCAB_Mummy_64_JUST_BUILD_RUNTIME:BOOL=ON" "-DMCAB_Mummy_SNKEYFILE:FILEPATH=${Mummy_SNKEYFILE}" "-DMCAB_PROJECT:STRING=Mummy" "-DMCAB_SCRIPT:STRING=${MCAB_SCRIPT}" "-DMCAB_SOURCE_DIR:PATH=${Mummy_SOURCE_DIR}" -P "${Mummy_SOURCE_DIR}/DoConfigureAndBuild.cmake" ) ADD_CUSTOM_TARGET( Kitware.mummy.Build.x64 ALL DEPENDS "${MCAB_SCRIPT}" ) ADD_DEPENDENCIES(mummyLib Kitware.mummy.Build.x64) ENDIF("${CMAKE_GENERATOR}" MATCHES "Visual Studio" AND NOT "${CMAKE_GENERATOR}" MATCHES "Win64") ENDIF(Mummy_32_BIT) ENDIF(Mummy_BUILD_COMPONENT_MUMMY) # Always build the mummy runtime helper dll. Generated code uses mummy::Runtime # and mummy::TypeEntry, so clients must link to this runtime helper dll. # IF(Mummy_BUILD_COMPONENT_MUMMY_RUNTIME) ADD_SUBDIRECTORY(Runtime) ENDIF(Mummy_BUILD_COMPONENT_MUMMY_RUNTIME) IF(Mummy_BUILD_COMPONENT_MUMMY) # Add a dependency on the runtime dll so that the runtime is always # up to date even for targets later in the food chain. # # (That way the Examples can just depend on mummy and they will be # guaranteed to be built *after* the runtime dlls are built...) # # mummy itself does not contain a build-time dependency on the runtime # dlls, but these rules are for the convenience of those who come later. # ADD_DEPENDENCIES(mummy Kitware.mummy.Runtime.Unmanaged) ENDIF(Mummy_BUILD_COMPONENT_MUMMY) # Projects building Mummy that want Mummy's Examples should # SET(Mummy_BUILD_EXAMPLES 1). Also, Examples can only be built # if the mummy component itself is built. (The examples use # the built mummy component...) # IF(Mummy_BUILD_EXAMPLES) IF(Mummy_BUILD_COMPONENT_MUMMY) # When building the Examples as part of the mummy build, enable them to find # MummyConfig.cmake in this build tree: # SET(Mummy_DIR "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}") ADD_SUBDIRECTORY(Examples) ENDIF(Mummy_BUILD_COMPONENT_MUMMY) ENDIF(Mummy_BUILD_EXAMPLES) # Projects building Mummy that want Mummy's Testing should ENABLE_TESTING and # SET(Mummy_BUILD_TESTING 1). Can only build if the mummy component itself # was built. # IF(Mummy_BUILD_TESTING) IF(Mummy_BUILD_COMPONENT_MUMMY) # # Mummy_TESTING_CONFIG_PREFIX may be defined in the CMake cache... # # If so, it will either be "" or something like "Debug/" such that # it can be used in an expression like this: # # ${EXECUTABLE_OUTPUT_PATH}/${Mummy_TESTING_CONFIG_PREFIX}blah.exe # ADD_SUBDIRECTORY(MummyTesting) ENDIF(Mummy_BUILD_COMPONENT_MUMMY) ENDIF(Mummy_BUILD_TESTING) # Build mummy documentation, too. (Only actually builds if doxygen can be # found.) # IF(Mummy_BUILD_COMPONENT_MUMMY) INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/MummyDoxygen.cmake") ENDIF(Mummy_BUILD_COMPONENT_MUMMY) # "make install" rules # IF(Mummy_BUILD_COMPONENT_MUMMY) INSTALL(TARGETS mummy RUNTIME DESTINATION "bin" ) IF(WIN32) # These dll files only get built on Windows, and they are only # in the \${BUILD_TYPE} subdirectory for build systems that use # CMAKE_CONFIGURATION_TYPES: # IF(CMAKE_CONFIGURATION_TYPES) SET(build_type_subdir "/\${BUILD_TYPE}") ELSE(CMAKE_CONFIGURATION_TYPES) SET(build_type_subdir "") ENDIF(CMAKE_CONFIGURATION_TYPES) INSTALL(FILES "${Mummy_BINARY_DIR}/bin${build_type_subdir}/Kitware.mummy.Runtime.dll" DESTINATION "bin" ) IF(MCAB_BINARY_DIR) INSTALL(FILES "${Mummy_BINARY_DIR}/bin/x64${build_type_subdir}/Kitware.mummy.Runtime.dll" "${Mummy_BINARY_DIR}/bin/x64${build_type_subdir}/Kitware.mummy.Runtime.Unmanaged.dll" "${Mummy_BINARY_DIR}/bin/x64${build_type_subdir}/Kitware.mummy.Runtime.Unmanaged.lib" DESTINATION "bin/x64" ) ENDIF(MCAB_BINARY_DIR) ENDIF(WIN32) INSTALL(FILES "${Mummy_BINARY_DIR}/include/mummy-${Mummy_VERSION_STRING}/MummyRuntime.h" DESTINATION "include/mummy-${Mummy_VERSION_STRING}" ) INSTALL(FILES "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/CSharpTestDriver.cs.in" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/FindCsharp.cmake" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/MummyCMakeMacros.cmake" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/MummyConfig.cmake" "${Mummy_BINARY_DIR}/share/mummy-${Mummy_VERSION_STRING}/SvnMacros.cmake" DESTINATION "share/mummy-${Mummy_VERSION_STRING}" ) ENDIF(Mummy_BUILD_COMPONENT_MUMMY) # Build a mummy installer. Only useful if the mummy component itself was built. # IF(Mummy_BUILD_COMPONENT_MUMMY) INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/MummyCPack.cmake") ENDIF(Mummy_BUILD_COMPONENT_MUMMY) MARK_AS_ADVANCED(BUILD_SHARED_LIBS) MARK_AS_ADVANCED(CMAKE_BACKWARDS_COMPATIBILITY) mummy-1.0.3/CSharpTestDriver.cs.in0000644000175000017500000001131512120621217016654 0ustar mathieumathieuclass MummyCSharpTestDriver { public static void Main(string[] args) { try { string test; if (0 == args.Length) { test = GetTestNameInteractively(); } else { test = args[0]; } System.Type t = System.Type.GetType(test + "Class"); if (null == t) { throw new System.ArgumentException(System.String.Format( "error: could not create a Type object for '{0}'...\n\n{1}\n{2}\n{3}\n{4}\n\n{5}\n\n", test + "Class", "Typo?", "Did you follow the C# test driver naming convention?", "Did you add the test to the CMakeLists.txt file?", "Did you reconfigure/rebuild after adding the test?", "Test 'method' name should equal 'file name without extension'... Test 'public class' name should be the same but with 'Class' appended..." )); } System.Reflection.MethodInfo mi = t.GetMethod(test); if (null == mi) { throw new System.ArgumentException(System.String.Format( "error: could not find method named '{0}'", test)); } // Expected method signature is "same as C# Main": returns void // and takes a string array as its one argument... // object[] invArgs = new object[1]; invArgs[0] = args; mi.Invoke(null, invArgs); // Before forced garbage collection, make sure the mummy Runtime // is not holding onto any wrapper objects anymore: // Kitware.mummy.Runtime.Methods.ForceRemoveCallbacks(); Kitware.mummy.Runtime.Methods.ForceClearWrappedObjectsTable(); // Force a garbage collection prior to exiting the test // so that any memory leaks reported are likely to be // *actual* leaks of some sort rather than false reports: // System.GC.Collect(); System.GC.WaitForPendingFinalizers(); // Test finished without throwing any exceptions... // Therefore, it passed. Exit with a zero ExitCode. // System.Environment.ExitCode = 0; } catch(System.Exception exc) { // Catch anything, spit it out to the console so it can be captured // by ctest. Exit with a non-zero ExitCode. // System.Console.Error.WriteLine("================================================================================"); System.Console.Error.WriteLine(""); System.Console.Error.WriteLine("Mummy C# test driver caught System.Exception:"); System.Console.Error.WriteLine(""); System.Console.Error.WriteLine("{0}", exc.ToString()); System.Console.Error.WriteLine(""); System.Console.Error.WriteLine("================================================================================"); System.Console.Error.WriteLine(""); System.Environment.ExitCode = 2345; } } public static string[] GetAvailableTests() { System.Collections.ArrayList testList = new System.Collections.ArrayList(); System.Reflection.Assembly assy = System.Reflection.Assembly.GetExecutingAssembly(); foreach (System.Type et in assy.GetExportedTypes()) { if (et.IsClass) { foreach (System.Reflection.MethodInfo mInfo in et.GetMethods()) { if (et.Name == mInfo.Name + "Class") { testList.Add(mInfo.Name); } } } } return (string[])testList.ToArray(System.Type.GetType("System.String")); } public static string GetTestNameInteractively() { string s = "Available tests:\n"; string[] tests = GetAvailableTests(); int i = 0; foreach (string xyz in tests) { s = System.String.Format("{0} {1}: {2}\n", s, i, xyz); ++i; } s = System.String.Format("{0}To run a test, enter the test number: ", s); System.Console.Write(s); string choice = System.Console.ReadLine(); int choiceNumber = -1; try { choiceNumber = System.Convert.ToInt32(choice); if (choiceNumber < 0 || choiceNumber >= tests.Length) { throw new System.ArgumentOutOfRangeException(System.String.Format( "'{0}' is an invalid test number.\nExiting without running a test.\n\n", choice)); } } catch (System.Exception) { System.Console.Error.Write(System.String.Format( "'{0}' is an invalid test number.\nExiting without running a test.\n\n", choice)); throw; } return tests[choiceNumber]; } } mummy-1.0.3/CTestConfig.cmake0000644000175000017500000000035412120621217015677 0ustar mathieumathieuset(CTEST_PROJECT_NAME "mummy") set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") set(CTEST_DROP_METHOD "http") set(CTEST_DROP_SITE "www.cdash.org") set(CTEST_DROP_LOCATION "/CDash/submit.php?project=mummy") set(CTEST_DROP_SITE_CDASH TRUE) mummy-1.0.3/CTestCustom.cmake.in0000644000175000017500000000157312120621217016355 0ustar mathieumathieu#SET(CTEST_CUSTOM_WARNING_MATCH # ${CTEST_CUSTOM_WARNING_MATCH} # ) #SET(CTEST_CUSTOM_ERROR_MATCH # ${CTEST_CUSTOM_ERROR_MATCH} # ) SET(CTEST_CUSTOM_WARNING_EXCEPTION ${CTEST_CUSTOM_WARNING_EXCEPTION} "(ranlib|libtool).*file.*(backend|cpp).*has no symbols" "arning.*description field.*too big.*try a different debug format" "CableSwig.GCC.gcc.config.i386.i386.md.*warning: operand 1 missing mode" "(insn-peep|loop-doloop|vmsdbgout|xcoffout).*obj.*warning.*no public symbols found.*archive member will be inaccessible" "mummyExternalSourceTrees.CableSwig.Cable.Expat.xmlrole.c.*warning.*RCSId.*defined but not used" ) SET(CTEST_CUSTOM_COVERAGE_EXCLUDE ${CTEST_CUSTOM_COVERAGE_EXCLUDE} ".*CableSwig.*" ".*CMakeFiles.CMakeTmp.*" ".*Modules.CMake.*" ".*Modules.(CheckFunctionExists|TestBigEndian).c$" ".*MummyTesting.(HandCrafted|Simple|SuppressWarnings).*" ) mummy-1.0.3/ConfigureAndBuild.cmake.in0000644000175000017500000000137212120621217017461 0ustar mathieumathieuSET(CTEST_PROJECT_NAME "@MCAB_PROJECT@") SET(CTEST_SOURCE_DIRECTORY "@MCAB_SOURCE_DIR@") SET(CTEST_BINARY_DIRECTORY "@MCAB_BINARY_DIR@") SET(CTEST_CMAKE_GENERATOR "@MCAB_GENERATOR@") SET(CTEST_BUILD_CONFIGURATION "@MCAB_CONFIG@") IF(NOT EXISTS "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt") FILE(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" " EXECUTABLE_OUTPUT_PATH:PATH=@MCAB_EXECUTABLE_OUTPUT_PATH@ LIBRARY_OUTPUT_PATH:PATH=@MCAB_LIBRARY_OUTPUT_PATH@ Mummy_64_JUST_BUILD_RUNTIME:BOOL=@MCAB_Mummy_64_JUST_BUILD_RUNTIME@ Mummy_SNKEYFILE:FILEPATH=@MCAB_Mummy_SNKEYFILE@ ") ENDIF(NOT EXISTS "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt") CTEST_START(Experimental) CTEST_CONFIGURE(BUILD "${CTEST_BINARY_DIRECTORY}") CTEST_BUILD(BUILD "${CTEST_BINARY_DIRECTORY}") mummy-1.0.3/CvsMacros.cmake0000644000175000017500000000405212120621217015426 0ustar mathieumathieuMACRO(GET_CVS_SNAPSHOT gcs_workingdir gcs_cvsroot gcs_cvsmodule gcs_cvsrevisionargs) FIND_PROGRAM(gcs_cvs_EXECUTABLE cvs "C:/Program Files/CVSNT" "C:/Program Files (x86)/CVSNT" "C:/Program Files/TortoiseCVS" "C:/Program Files (x86)/TortoiseCVS" "C:/cygwin/bin" "/usr/bin" "/usr/local/bin" ) IF(NOT gcs_cvs_EXECUTABLE) MESSAGE(FATAL_ERROR "error: cvs is required to retrieve a ${gcs_cvsmodule} snapshot. Please set gcs_cvs_EXECUTABLE to a working copy of cvs.") ENDIF(NOT gcs_cvs_EXECUTABLE) MARK_AS_ADVANCED(gcs_cvs_EXECUTABLE) IF(EXISTS "${gcs_workingdir}/${gcs_cvsmodule}/CVS/Root") MESSAGE(STATUS "Updating ${gcs_cvsmodule} snapshot with '${gcs_cvs_EXECUTABLE}'...") SET(gcs_cvsargs "-d" "${gcs_cvsroot}" "up" "-dAP" ${gcs_cvsrevisionargs}) FILE(APPEND "${gcs_workingdir}/${gcs_cvsmodule}/CMakeFiles/cvs-up-args.txt" "gcs_cvsargs='${gcs_cvsargs}'\n") EXECUTE_PROCESS( COMMAND "${gcs_cvs_EXECUTABLE}" ${gcs_cvsargs} WORKING_DIRECTORY "${gcs_workingdir}/${gcs_cvsmodule}" RESULT_VARIABLE gcs_cvs_rv ) MESSAGE(STATUS "Updating ${gcs_cvsmodule} snapshot with '${gcs_cvs_EXECUTABLE}'... -- done") ELSE(EXISTS "${gcs_workingdir}/${gcs_cvsmodule}/CVS/Root") MESSAGE(STATUS "Checking out ${gcs_cvsmodule} snapshot with '${gcs_cvs_EXECUTABLE}'... (This may take a few minutes...)") SET(gcs_cvsargs "-d" "${gcs_cvsroot}" "co" ${gcs_cvsrevisionargs} "${gcs_cvsmodule}") FILE(WRITE "${gcs_workingdir}/${gcs_cvsmodule}/CMakeFiles/cvs-co-args.txt" "gcs_cvsargs='${gcs_cvsargs}'\n") EXECUTE_PROCESS( COMMAND "${gcs_cvs_EXECUTABLE}" ${gcs_cvsargs} WORKING_DIRECTORY "${gcs_workingdir}" RESULT_VARIABLE gcs_cvs_rv ) MESSAGE(STATUS "Checking out ${gcs_cvsmodule} snapshot with '${gcs_cvs_EXECUTABLE}'... -- done") ENDIF(EXISTS "${gcs_workingdir}/${gcs_cvsmodule}/CVS/Root") IF(NOT "${gcs_cvs_rv}" STREQUAL "0") MESSAGE(SEND_ERROR "error: cvs command returned '${gcs_cvs_rv}'") ENDIF(NOT "${gcs_cvs_rv}" STREQUAL "0") ENDMACRO(GET_CVS_SNAPSHOT) mummy-1.0.3/DoConfigureAndBuild.cmake0000644000175000017500000000132712120621217017337 0ustar mathieumathieuGET_FILENAME_COMPONENT(dir "${CMAKE_CURRENT_LIST_FILE}" PATH) SET(CMAKE_BACKWARDS_COMPATIBILITY ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) FOREACH(v CMAKE_BACKWARDS_COMPATIBILITY CMAKE_CTEST_COMMAND CMAKE_CURRENT_LIST_FILE CMAKE_MAJOR_VERSION CMAKE_MINOR_VERSION dir MCAB_BINARY_DIR MCAB_CONFIG MCAB_EXECUTABLE_OUTPUT_PATH MCAB_GENERATOR MCAB_LIBRARY_OUTPUT_PATH MCAB_Mummy_64_JUST_BUILD_RUNTIME MCAB_Mummy_SNKEYFILE MCAB_PROJECT MCAB_SCRIPT MCAB_SOURCE_DIR ) #MESSAGE("${v}='${${v}}'") ENDFOREACH(v) CONFIGURE_FILE( "${dir}/ConfigureAndBuild.cmake.in" "${MCAB_SCRIPT}" @ONLY ) EXECUTE_PROCESS(COMMAND ${CMAKE_CTEST_COMMAND} -VV -C "${MCAB_CONFIG}" -S "${MCAB_SCRIPT}" ) mummy-1.0.3/Examples/0000755000175000017500000000000012120621217014301 5ustar mathieumathieumummy-1.0.3/Examples/CMakeLists.txt0000644000175000017500000000007112120621217017037 0ustar mathieumathieuSET(Vehicles_BUILD_TESTING 1) ADD_SUBDIRECTORY(Vehicles) mummy-1.0.3/Examples/Vehicles/0000755000175000017500000000000012120621217016043 5ustar mathieumathieumummy-1.0.3/Examples/Vehicles/CMakeLists.txt0000644000175000017500000001035712120621217020611 0ustar mathieumathieuCMAKE_MINIMUM_REQUIRED(VERSION 2.4 FATAL_ERROR) PROJECT(Vehicles) # Determine if we're building Vehicles as a "top level" project. # SET(Vehicles_BUILD_IS_TOP_LEVEL 0) IF("${Vehicles_BINARY_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") SET(Vehicles_BUILD_IS_TOP_LEVEL 1) ENDIF("${Vehicles_BINARY_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/MsvcMacros.cmake") MSVC_FORCE_WARNING_LEVEL("4") #MSVC_TREAT_WARNINGS_AS_ERRORS() MSVC_LINK_TO_STATIC_CRT() MSVC80_FORCE_MANIFEST_LINKER_FLAG() # 32 or 64 bit build? # SET(Vehicles_TARGET_CPU_SIZE "32") IF(CMAKE_CL_64) SET(Vehicles_TARGET_CPU_SIZE "64") ENDIF(CMAKE_CL_64) # Debug or not for the C# layers? # SET(Vehicles_BUILD_CSHARP_DEBUG_DEFAULT OFF) IF("${BUILDNAME}" MATCHES "Debug") SET(Vehicles_BUILD_CSHARP_DEBUG_DEFAULT ON) ENDIF("${BUILDNAME}" MATCHES "Debug") IF("${BUILDNAME}" MATCHES "RelWithDebInfo") SET(Vehicles_BUILD_CSHARP_DEBUG_DEFAULT ON) ENDIF("${BUILDNAME}" MATCHES "RelWithDebInfo") OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON) OPTION(BUILD_TESTING "Build/add tests" ON) SET(Vehicles_INSTALL_TARGETS 0) IF(Vehicles_BUILD_IS_TOP_LEVEL) SET(VEHICLES_INSTALL_PREFIX "${CMAKE_BINARY_DIR} VIP Install" CACHE STRING "") SET(CMAKE_INSTALL_PREFIX "${VEHICLES_INSTALL_PREFIX}" CACHE INTERNAL "" FORCE) SET(Vehicles_INSTALL_TARGETS 1) ENDIF(Vehicles_BUILD_IS_TOP_LEVEL) OPTION(Vehicles_BUILD_CSHARP_DEBUG "Build C# components with '/debug' command line flag" ${Vehicles_BUILD_CSHARP_DEBUG_DEFAULT}) IF(NOT EXECUTABLE_OUTPUT_PATH) SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin" CACHE STRING "") ENDIF(NOT EXECUTABLE_OUTPUT_PATH) IF(NOT LIBRARY_OUTPUT_PATH) SET(LIBRARY_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}" CACHE STRING "") ENDIF(NOT LIBRARY_OUTPUT_PATH) MACRO(DEFINE_KIT kit kit_deps_var) SET(${kit}_classes ${ARGN} CACHE STRING "") SET(${kit}_deps ${${kit_deps_var}} CACHE STRING "") SET(${kit}_source_files "") FOREACH(class ${${kit}_classes}) IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${class}.cxx") SET(${kit}_source_files ${${kit}_source_files} "${CMAKE_CURRENT_SOURCE_DIR}/${class}.cxx" ) ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${class}.cxx") IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${class}.h") SET(${kit}_source_files ${${kit}_source_files} "${CMAKE_CURRENT_SOURCE_DIR}/${class}.h" ) ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${class}.h") ENDFOREACH(class) SET(deffile "${CMAKE_CURRENT_SOURCE_DIR}/${kit}${Vehicles_TARGET_CPU_SIZE}.def") IF(EXISTS "${deffile}") SET(${kit}_source_files ${${kit}_source_files} "${deffile}") ENDIF(EXISTS "${deffile}") SET(${kit}_source_files ${${kit}_source_files} CACHE STRING "") SET(${kit}_include_dirs "${Vehicles_SOURCE_DIR}/${kit}" CACHE STRING "") SET(${kit}_libs "${kit}" CACHE STRING "") MARK_AS_ADVANCED(${kit}_classes) MARK_AS_ADVANCED(${kit}_deps) MARK_AS_ADVANCED(${kit}_source_files) MARK_AS_ADVANCED(${kit}_include_dirs) MARK_AS_ADVANCED(${kit}_libs) ENDMACRO(DEFINE_KIT) MACRO(ECHO_KIT kit) MESSAGE(STATUS "${kit}_classes='${${kit}_classes}'") MESSAGE(STATUS "${kit}_deps='${${kit}_deps}'") MESSAGE(STATUS "${kit}_include_dirs='${${kit}_include_dirs}'") MESSAGE(STATUS "${kit}_libs='${${kit}_libs}'") MESSAGE(STATUS "${kit}_source_files='${${kit}_source_files}'") ENDMACRO(ECHO_KIT) CONFIGURE_FILE( "${Vehicles_SOURCE_DIR}/VehiclesConfig.h.in" "${Vehicles_BINARY_DIR}/VehiclesConfig.h" ) INCLUDE_DIRECTORIES(${Vehicles_SOURCE_DIR}) INCLUDE_DIRECTORIES(${Vehicles_BINARY_DIR}) LINK_DIRECTORIES(${EXECUTABLE_OUTPUT_PATH}) LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH}) MACRO(ADD_KIT kit) INCLUDE_DIRECTORIES("${Vehicles_SOURCE_DIR}/${kit}") SET(Vehicles_kits ${Vehicles_kits} "${kit}") ADD_SUBDIRECTORY("${kit}") #ECHO_KIT("${kit}") ENDMACRO(ADD_KIT) SET(Vehicles_kits "") ADD_KIT(base) ADD_KIT(cars) ADD_KIT(motorcycles) ADD_KIT(suvs) # Always enable and build Testing if building as a top level project. # IF(Vehicles_BUILD_IS_TOP_LEVEL) INCLUDE(CTest) ENABLE_TESTING() SET(Vehicles_BUILD_TESTING 1) ENDIF(Vehicles_BUILD_IS_TOP_LEVEL) IF(Vehicles_BUILD_TESTING) ADD_KIT(tests) ENDIF(Vehicles_BUILD_TESTING) SET(Vehicles_kits ${Vehicles_kits} CACHE STRING "") MARK_AS_ADVANCED(Vehicles_kits) ADD_SUBDIRECTORY(wrappers) mummy-1.0.3/Examples/Vehicles/CTestConfig.cmake0000644000175000017500000000035712120621217021222 0ustar mathieumathieuset(CTEST_PROJECT_NAME "Vehicles") set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT") set(CTEST_DROP_METHOD "http") set(CTEST_DROP_SITE "www.cdash.org") set(CTEST_DROP_LOCATION "/CDash/submit.php?project=mummy") set(CTEST_DROP_SITE_CDASH TRUE) mummy-1.0.3/Examples/Vehicles/MsvcMacros.cmake0000644000175000017500000000350312120621217021123 0ustar mathieumathieuMACRO(APPEND_FLAGS var flags) IF(NOT "${${var}}" MATCHES "${flags}") SET(${var} "${${var}} ${flags}") #MESSAGE(STATUS "INFO: ${var} changed to '${${var}}'") ENDIF(NOT "${${var}}" MATCHES "${flags}") ENDMACRO(APPEND_FLAGS) MACRO(REPLACE_FLAGS var these those) IF("${${var}}" MATCHES "${these}") STRING(REGEX REPLACE "${these}" "${those}" ${var} "${${var}}") #MESSAGE(STATUS "INFO: ${var} changed to '${${var}}'") ENDIF("${${var}}" MATCHES "${these}") ENDMACRO(REPLACE_FLAGS) MACRO(MSVC_FORCE_WARNING_LEVEL level) IF(MSVC) FOREACH(lang C CXX) FOREACH(suffix "" _DEBUG _MINSIZEREL _RELEASE _RELWITHDEBINFO) REPLACE_FLAGS("CMAKE_${lang}_FLAGS${suffix}" "/W[1-4]" "/W${level}") ENDFOREACH(suffix) ENDFOREACH(lang) ENDIF(MSVC) ENDMACRO(MSVC_FORCE_WARNING_LEVEL) MACRO(MSVC_TREAT_WARNINGS_AS_ERRORS) IF(MSVC) APPEND_FLAGS("CMAKE_C_FLAGS" "/WX") APPEND_FLAGS("CMAKE_CXX_FLAGS" "/WX") ENDIF(MSVC) ENDMACRO(MSVC_TREAT_WARNINGS_AS_ERRORS) MACRO(MSVC_LINK_TO_STATIC_CRT) IF(MSVC) FOREACH(lang C CXX) FOREACH(suffix "" _DEBUG _MINSIZEREL _RELEASE _RELWITHDEBINFO) REPLACE_FLAGS("CMAKE_${lang}_FLAGS${suffix}" "/MD" "/MT") ENDFOREACH(suffix) ENDFOREACH(lang) ENDIF(MSVC) ENDMACRO(MSVC_LINK_TO_STATIC_CRT) MACRO(MSVC_LINK_TO_DLL_CRT) IF(MSVC) FOREACH(lang C CXX) FOREACH(suffix "" _DEBUG _MINSIZEREL _RELEASE _RELWITHDEBINFO) REPLACE_FLAGS("CMAKE_${lang}_FLAGS${suffix}" "/MT" "/MD") ENDFOREACH(suffix) ENDFOREACH(lang) ENDIF(MSVC) ENDMACRO(MSVC_LINK_TO_DLL_CRT) MACRO(MSVC80_FORCE_MANIFEST_LINKER_FLAG) IF(MSVC80) APPEND_FLAGS("CMAKE_EXE_LINKER_FLAGS" "/MANIFEST") APPEND_FLAGS("CMAKE_MODULE_LINKER_FLAGS" "/MANIFEST") APPEND_FLAGS("CMAKE_SHARED_LINKER_FLAGS" "/MANIFEST") ENDIF(MSVC80) ENDMACRO(MSVC80_FORCE_MANIFEST_LINKER_FLAG) mummy-1.0.3/Examples/Vehicles/VehiclesConfig.h.in0000644000175000017500000000252512120621217021515 0ustar mathieumathieu#ifndef VehiclesConfig_h #define VehiclesConfig_h #cmakedefine BUILD_SHARED_LIBS #ifdef _WIN32 #ifdef BUILD_SHARED_LIBS #ifdef base_EXPORTS #define base_dll __declspec(dllexport) #else #define base_dll __declspec(dllimport) #endif #ifdef cars_EXPORTS #define cars_dll __declspec(dllexport) #else #define cars_dll __declspec(dllimport) #endif #ifdef motorcycles_EXPORTS #define motorcycles_dll __declspec(dllexport) #else #define motorcycles_dll __declspec(dllimport) #endif #ifdef suvs_EXPORTS #define suvs_dll __declspec(dllexport) #else #define suvs_dll __declspec(dllimport) #endif #ifdef tests_EXPORTS #define tests_dll __declspec(dllexport) #else #define tests_dll __declspec(dllimport) #endif #endif // BUILD_SHARED_LIBS #endif // _WIN32 // If not defined by one of the above blocks, // define as empty: // #ifndef base_dll #define base_dll #endif #ifndef cars_dll #define cars_dll #endif #ifndef motorcycles_dll #define motorcycles_dll #endif #ifndef suvs_dll #define suvs_dll #endif #ifndef tests_dll #define tests_dll #endif // Abstract "types" for 64-bit integers: // #ifdef _MSC_VER #define VehicleInt64 __int64 #define VehicleUInt64 unsigned __int64 #else #define VehicleInt64 long long #define VehicleUInt64 unsigned long long #endif // Include the inline wrapper hints everywhere: // #include "InlineWrapperHints.h" #endif mummy-1.0.3/Examples/Vehicles/base/0000755000175000017500000000000012120621217016755 5ustar mathieumathieumummy-1.0.3/Examples/Vehicles/base/AbstractVehicle.cxx0000644000175000017500000002365612120621217022560 0ustar mathieumathieu#include "AbstractVehicle.h" #include "FuelLevelChanged.h" #include "UnwrappedClass.h" #include // free #include // strdup and strlen #include #include #include #if _MSC_VER >= 1400 #define strdup _strdup #endif AbstractVehicle::AbstractVehicle() { this->VIN = strdup("11223344556677889900"); this->Callback = 0; this->ClientData = 0; //throw std::exception("ERROR: this is the string part of the exception"); this->FuelLevel = 0.0; this->FuelLevelChangedEventInstance = 0; memset(this->InfoArray, 0, sizeof(this->InfoArray)); #if 0 this->RegisteredOwner = "me"; this->m_TextualDescription = "beat up old jalopy"; #endif } AbstractVehicle::~AbstractVehicle() { if (this->VIN) { free(this->VIN); this->VIN = 0; } if (this->FuelLevelChangedEventInstance) { this->FuelLevelChangedEventInstance->Delete(); this->FuelLevelChangedEventInstance = 0; } } void AbstractVehicle::Delete() { delete this; } const char *AbstractVehicle::GetVehicleType() const { return this->VGetVehicleType(); } double AbstractVehicle::GetMileage() const { return this->VGetMileage(); } void AbstractVehicle::SetVIN(const char *vin) { if (this->VIN) { free(this->VIN); } if (vin) { this->VIN = strdup(vin); } else { this->VIN = 0; } } const char *AbstractVehicle::GetVIN() const { return this->VIN ? this->VIN : ""; } unsigned int AbstractVehicle::GetMaxIndex() const { return 9876543; // 9,876,543 } void AbstractVehicle::TSetValue(const unsigned int index, const int val) { if (index > GetMaxIndex()) { throw std::exception();//"ERROR: index greater than GetMaxIndex() result"); } if (this->Callback) { std::ostringstream oss; oss << "Unmanaged code: " << this << ", 1, " << this->ClientData << ", " << &val << std::endl; std::cerr << oss.str().c_str(); (*this->Callback)(this, 1, this->ClientData, reinterpret_cast(&val)); } (void) val; } int AbstractVehicle::TGetValue(const unsigned int index) const { if (index > GetMaxIndex()) { throw std::exception();//"ERROR: index greater than GetMaxIndex() result"); } return 33; } void AbstractVehicle::TSetStringValue(const unsigned int index, const char *val) { if (index > GetMaxIndex()) { throw std::exception();//"ERROR: index greater than GetMaxIndex() result"); } if (this->Callback) { std::ostringstream oss; oss << "Unmanaged code: " << this << ", 2, " << this->ClientData << ", " << val << std::endl; std::cerr << oss.str().c_str(); (*this->Callback)(this, 2, this->ClientData, reinterpret_cast(val)); } (void) val; } const char *AbstractVehicle::TGetStringValue(const unsigned int index) const { if (index > GetMaxIndex()) { throw std::exception();//"ERROR: index greater than GetMaxIndex() result"); } return "StringValue is 33 and a third"; } void AbstractVehicle::TSetDoubleValue(const unsigned int index, const double val) { if (index > GetMaxIndex()) { throw std::exception();//"ERROR: index greater than GetMaxIndex() result"); } if (this->Callback) { std::ostringstream oss; oss << "Unmanaged code: " << this << ", 3, " << this->ClientData << ", " << &val << std::endl; std::cerr << oss.str().c_str(); (*this->Callback)(this, 3, this->ClientData, reinterpret_cast(&val)); } (void) val; } double AbstractVehicle::TGetDoubleValue(const unsigned int index) const { if (index > GetMaxIndex()) { throw std::exception();//"ERROR: index greater than GetMaxIndex() result"); } return 33.0 + 1.0/3.0; } void AbstractVehicle::TSetObjectValue(const unsigned int index, const AbstractVehicle *val) { if (index > GetMaxIndex()) { throw std::exception();//"ERROR: index greater than GetMaxIndex() result"); } if (this->Callback) { std::ostringstream oss; oss << "Unmanaged code: " << this << ", 4, " << this->ClientData << ", " << val << std::endl; std::cerr << oss.str().c_str(); (*this->Callback)(this, 4, this->ClientData, reinterpret_cast(val)); } (void) val; } const AbstractVehicle *AbstractVehicle::TGetObjectValue(const unsigned int index) const { if (index > GetMaxIndex()) { throw std::exception();//"ERROR: index greater than GetMaxIndex() result"); } static int TGetObjectValueCounter = 0; ++TGetObjectValueCounter; // Alternate between returning valid pointers and NULL pointers // for complete branch coverage in the export layer... (Call multiple // times sequentially from the wrapped side for complete coverage...) // if (0 != TGetObjectValueCounter%2) { return 0; } return this; } void AbstractVehicle::TSetCallback(AVCallback f, void *clientdata) { this->Callback = f; this->ClientData = clientdata; } AbstractVehicle::AVCallback AbstractVehicle::TGetCallback() const { return this->Callback; } void* AbstractVehicle::TGetClientData() const { return this->ClientData; } void AbstractVehicle::SetFuelLevel(double level) { if (this->FuelLevel != level) { double oldLevel = this->FuelLevel; this->FuelLevel = level; if (this->FuelLevelChangedEventInstance) { FuelLevelChangedEventArgs* data = FuelLevelChangedEventArgs::New(); data->SetOldLevel(oldLevel); data->SetLevel(level); this->FuelLevelChangedEventInstance->Invoke(this, data); // intentional mem leak for now - since adding TheTable, duplicate pointer // values get messed up with non-ref-counted systems... doesn't matter for // VTK or other ref-count-based object hierarchies... but does for us... // so live with this small mem-leak for now: // data->Delete(); } } } double AbstractVehicle::GetFuelLevel() const { return this->FuelLevel; } FuelLevelChanged *AbstractVehicle::TGetFuelLevelChangedEvent() const { if (0 == this->FuelLevelChangedEventInstance) { this->FuelLevelChangedEventInstance = FuelLevelChanged::New(); } return this->FuelLevelChangedEventInstance; } void AbstractVehicle::SetInfoArray(const float *info) { memcpy(this->InfoArray, info, sizeof(this->InfoArray)); } const float* AbstractVehicle::GetInfoArray() const { return this->InfoArray; } int AbstractVehicle::TGetInfoArrayLength() const { return sizeof(this->InfoArray)/sizeof(this->InfoArray[0]); } float* AbstractVehicle::InfoArrayBase() { return this->InfoArray; } void AbstractVehicle::TSetInfoArrayElementUnchecked(int i, float f) { this->InfoArray[i] = f; } float AbstractVehicle::TGetInfoArrayElementUnchecked(int i) const { return this->InfoArray[i]; } void AbstractVehicle::TSetInfoArrayElementChecked(int i, float f) { if (i>=0 && iTGetInfoArrayLength()) { this->InfoArray[i] = f; } else { throw new std::exception(); } } float AbstractVehicle::TGetInfoArrayElementChecked(int i) const { if (i>=0 && iTGetInfoArrayLength()) { return this->InfoArray[i]; } else { throw new std::exception(); } } VehicleDescriptor AbstractVehicle::TGetDescriptor() const { VehicleDescriptor desc; desc.AMarker = 12345; desc.BoolTest1 = true; desc.BoolTest2 = false; desc.c1 = 0x11; desc.ColorCode = 55; desc.d1 = 222222222222.222222222222; desc.f1 = 333333.333333f; desc.i1 = 0x44444444; desc.i64 = 0x5555555555555555LL; desc.l1 = 0x66666666; desc.MileageEstimate = 21.21f; desc.NumberOfCylinders = 4; desc.NumberOfDoors = 3; desc.s1 = 0x7777; desc.uc1 = 0x88; desc.ui1 = 0x99999999; desc.ui64 = 0xAAAAAAAAAAAAAAAAULL; desc.ul1 = 0xBBBBBBBB; desc.us1 = 0xDDDD; desc.enumMfgID = VehicleDescriptor::Honda; desc.ZMarker = 67890; return desc; } void AbstractVehicle::TSetDescriptor(VehicleDescriptor desc) { VehicleDescriptor desc2 = desc; desc2.ZMarker = desc2.ZMarker; } void AbstractVehicle::TSetDescriptorRef(VehicleDescriptor &desc) { VehicleDescriptor desc2 = desc; desc2.ZMarker = desc2.ZMarker; } void AbstractVehicle::TSetDescriptorConstRef(const VehicleDescriptor &desc) { VehicleDescriptor desc2 = desc; desc2.ZMarker = desc2.ZMarker; } int AbstractVehicle::TGet_BTX_ETX_Int() const { return 0; } int AbstractVehicle::Get_iwhExclude_Int() const { return 0; } bool AbstractVehicle::TGetHasLicensePlate() const { return this->HasLicensePlate; } void AbstractVehicle::TSetHasLicensePlate(bool hasLicensePlate) { this->HasLicensePlate = hasLicensePlate; } bool AbstractVehicle::GetRegistered() const { return this->Registered; } void AbstractVehicle::SetRegistered(bool registered) { this->Registered = registered; } #if 0 void AbstractVehicle::AppendToTextualDescription(const SillyString& text) { this->m_TextualDescription += "\n"; this->m_TextualDescription += "\n"; this->m_TextualDescription += text; } SillyString AbstractVehicle::TextualDescription() const { return this->m_TextualDescription; } SillyString AbstractVehicle::GetRegisteredOwner() const { return this->RegisteredOwner; } void AbstractVehicle::SetRegisteredOwner(const SillyString& owner) { this->RegisteredOwner = owner; } #endif UnwrappedClass* AbstractVehicle::YouCannotCallThisMethodFromTheWrappedLayer() { return new UnwrappedClass; } void AbstractVehicle::TSetManufacturerID(VehicleDescriptor::ManufacturerID mid) { VehicleDescriptor desc; desc.enumMfgID = mid; } VehicleDescriptor::ManufacturerID AbstractVehicle::TGetManufacturerID() { return VehicleDescriptor::Ford; } void AbstractVehicle::MethodWithBoolRefArg(bool &arg) { static int MethodWithBoolRefArg_Counter = 0; ++MethodWithBoolRefArg_Counter; // Alternate between "returning" true, false and unmodified // for complete branch coverage in the export layer... (Call multiple // times sequentially from the wrapped side for complete coverage...) // switch (MethodWithBoolRefArg_Counter%3) { case 0: arg = true; break; case 1: arg = false; break; default: break; } } mummy-1.0.3/Examples/Vehicles/base/AbstractVehicle.h0000644000175000017500000001510212120621217022170 0ustar mathieumathieu#ifndef _AbstractVehicle_h #define _AbstractVehicle_h #include "VehiclesConfig.h" #include "FuelLevelChanged.h" #include "SillyString.h" #include "VehicleDescriptor.h" class UnwrappedClass; //---------------------------------------------------------------------------- /// /// Root class of the Vehicles example class hierarchy. /// class base_dll AbstractVehicle { public: //-------------------------------------------------------------------------- /// /// Disposal method. Concrete subclasses are created via factory methods /// (static methods with no parameters that return the created object type /// and are named "New"). All instances created via a factory method must /// eventually be disposed of with a call to Delete. /// virtual void Delete(); //-------------------------------------------------------------------------- /// /// Get the type of the Vehicle. /// /// Vehicle type as a string. iwhPropGet const char *GetVehicleType() const; //-------------------------------------------------------------------------- /// /// Get the average mileage (miles per gallon) of the Vehicle. /// /// Mileage measured in miles per gallon. iwhPropGet double GetMileage() const; //-------------------------------------------------------------------------- /// /// Set the Vehicle ID number. /// /// The Vehicle ID number as a string. iwhPropSet void SetVIN(const char *vin); //-------------------------------------------------------------------------- /// /// Get the Vehicle ID number. /// /// The Vehicle ID number as a string. iwhPropGet const char *GetVIN() const; // Value accessors: //-------------------------------------------------------------------------- iwhPropGet unsigned int GetMaxIndex() const; //-------------------------------------------------------------------------- // Integers: virtual void TSetValue(const unsigned int index, const int val); virtual int TGetValue(const unsigned int index) const; //-------------------------------------------------------------------------- // Strings: virtual void TSetStringValue(const unsigned int index, const char *val); virtual const char *TGetStringValue(const unsigned int index) const; //-------------------------------------------------------------------------- // Doubles: virtual void TSetDoubleValue(const unsigned int index, const double val); virtual double TGetDoubleValue(const unsigned int index) const; //-------------------------------------------------------------------------- // Objects: virtual void TSetObjectValue(const unsigned int index, const AbstractVehicle *val); virtual const AbstractVehicle *TGetObjectValue(const unsigned int index) const; //-------------------------------------------------------------------------- // Event proof of concept: #ifdef _WIN32 #define AVCB_CC __stdcall #else #define AVCB_CC #endif typedef void (AVCB_CC *AVCallback)(AbstractVehicle *sender, unsigned long eid, void *clientdata, const void *calldata); virtual void TSetCallback(AVCallback f, void *clientdata); virtual AVCallback TGetCallback() const; virtual void* TGetClientData() const; //-------------------------------------------------------------------------- // More object oriented event proof of concept: iwhPropSet void SetFuelLevel(double level); iwhPropGet double GetFuelLevel() const; virtual iwhEvent FuelLevelChanged *TGetFuelLevelChangedEvent() const; //-------------------------------------------------------------------------- // Array access testing: #define InfoArraySize 37 iwhPropSet void SetInfoArray(iwhArraySize(37) const float *info); iwhPropGet iwhArraySize(37) const float* GetInfoArray() const; virtual int TGetInfoArrayLength() const; virtual float* InfoArrayBase(); virtual void TSetInfoArrayElementUnchecked(int i, float f); virtual float TGetInfoArrayElementUnchecked(int i) const; virtual void TSetInfoArrayElementChecked(int i, float f); virtual float TGetInfoArrayElementChecked(int i) const; //-------------------------------------------------------------------------- // Return-struct-by-value test: virtual VehicleDescriptor TGetDescriptor() const; virtual void TSetDescriptor(VehicleDescriptor desc); virtual void TSetDescriptorRef(VehicleDescriptor &desc); virtual void TSetDescriptorConstRef(const VehicleDescriptor &desc); //-------------------------------------------------------------------------- // Pass/return enum test: void TSetManufacturerID(VehicleDescriptor::ManufacturerID mid); VehicleDescriptor::ManufacturerID TGetManufacturerID(); //BTX virtual int TGet_BTX_ETX_Int() const; //ETX //-------------------------------------------------------------------------- virtual iwhExclude int Get_iwhExclude_Int() const; //-------------------------------------------------------------------------- // bool method and property test: virtual bool TGetHasLicensePlate() const; virtual void TSetHasLicensePlate(bool hasLicensePlate); virtual iwhPropGet bool GetRegistered() const; virtual iwhPropSet void SetRegistered(bool registered); //-------------------------------------------------------------------------- // string method and property test: #if 0 virtual void AppendToTextualDescription(const SillyString& text); virtual SillyString TextualDescription() const; virtual iwhPropGet SillyString GetRegisteredOwner() const; virtual iwhPropSet void SetRegisteredOwner(const SillyString& owner); #endif //-------------------------------------------------------------------------- // exclude UnwrappedClass test: virtual UnwrappedClass* YouCannotCallThisMethodFromTheWrappedLayer(); //-------------------------------------------------------------------------- // "bool &" arg test: virtual void MethodWithBoolRefArg(bool &arg); //-------------------------------------------------------------------------- protected: AbstractVehicle(); virtual ~AbstractVehicle(); virtual double VGetMileage() const = 0; virtual const char *VGetVehicleType() const = 0; //-------------------------------------------------------------------------- private: char *VIN; AVCallback Callback; void *ClientData; double FuelLevel; mutable FuelLevelChanged *FuelLevelChangedEventInstance; float InfoArray[InfoArraySize]; bool HasLicensePlate; bool Registered; #if 0 SillyString RegisteredOwner; SillyString m_TextualDescription; #endif }; #endif mummy-1.0.3/Examples/Vehicles/base/AbstractVehicleEvent.h0000644000175000017500000000041312120621217023171 0ustar mathieumathieu#ifndef _ABSTRACTVEHICLEEVENT_H #define _ABSTRACTVEHICLEEVENT_H #include "VehiclesConfig.h" #include "SenderDataEvent.h" template class AbstractVehicleEvent : public SenderDataEvent { }; #endif // _ABSTRACTVEHICLEEVENT_H mummy-1.0.3/Examples/Vehicles/base/BlatMobile.cxx0000644000175000017500000000546212120621217021522 0ustar mathieumathieu#include "BlatMobile.h" #include void BlatMobile::CycleTurbo(BlatMobile* bm) { std::cerr << "C++ BlatMobile::CycleTurbo() called..." << std::endl; if (bm) { std::cerr << "Calling ActivateTurboBoost from C++ BlatMobile::CycleTurbo()..." << std::endl; bm->ActivateTurboBoost(); std::cerr << "Calling DeactivateTurboBoost from C++ BlatMobile::CycleTurbo()..." << std::endl; bm->DeactivateTurboBoost(); } else { std::cerr << "NULL BlatMobile, cannot call ActivateTurboBoost or DeactivateTurboBoost..." << std::endl; } } BlatMobile* BlatMobile::Create() { BlatMobile* rcv = new BlatMobile; return rcv; } void BlatMobile::Destroy() { this->DecrRefCount(); } void BlatMobile::IncrRefCount() { ++m_RefCount; } void BlatMobile::DecrRefCount() { --m_RefCount; if (0 == m_RefCount) { delete this; } } unsigned int BlatMobile::GetRefCount() const { return m_RefCount; } void BlatMobile::ActivateTurboBoost() { std::cerr << "C++ BlatMobile::ActivateTurboBoost() called..." << std::endl; } void BlatMobile::DeactivateTurboBoost() { std::cerr << "C++ BlatMobile::DeactivateTurboBoost() called..." << std::endl; } void BlatMobile::VUnsignedChar(unsigned char arg) { unsigned char local = arg; std::cerr << local << std::endl; } void BlatMobile::VUnsignedShort(unsigned short arg) { unsigned short local = arg; std::cerr << local << std::endl; } void BlatMobile::VUnsignedInt(unsigned int arg) { unsigned int local = arg; std::cerr << local << std::endl; } void BlatMobile::VUnsignedLong(unsigned long arg) { unsigned long local = arg; std::cerr << local << std::endl; } void BlatMobile::VUnsignedInt64(VehicleUInt64 arg) { VehicleUInt64 local = arg; std::cerr << local << std::endl; } void BlatMobile::VChar(char arg) { char local = arg; std::cerr << local << std::endl; } void BlatMobile::VShort(short arg) { short local = arg; std::cerr << local << std::endl; } void BlatMobile::VInt(int arg) { int local = arg; std::cerr << local << std::endl; } void BlatMobile::VLong(long arg) { long local = arg; std::cerr << local << std::endl; } void BlatMobile::VInt64(VehicleInt64 arg) { VehicleInt64 local = arg; std::cerr << local << std::endl; } void BlatMobile::VBool(bool arg) { bool local = arg; std::cerr << local << std::endl; } void BlatMobile::VFloat(float arg) { float local = arg; std::cerr << local << std::endl; } void BlatMobile::VDouble(double arg) { double local = arg; std::cerr << local << std::endl; } void BlatMobile::VVoidPointer(void* arg) { void* local = arg; std::cerr << local << std::endl; } void BlatMobile::VObjectPointer(BlatMobile* arg) { BlatMobile* local = arg; std::cerr << local << std::endl; } BlatMobile::BlatMobile() { m_RefCount = 0; this->IncrRefCount(); } BlatMobile::~BlatMobile() { } mummy-1.0.3/Examples/Vehicles/base/BlatMobile.h0000644000175000017500000000245712120621217021150 0ustar mathieumathieu#ifndef _BlatMobile_h #define _BlatMobile_h #include "VehiclesConfig.h" // BlatMobile is a "yet to be documented" example class... // This class is used to test/demonstrate the "shadow class" // feature of mummy... class base_dll BlatMobile { public: static void CycleTurbo(BlatMobile* bm); static BlatMobile* Create(); virtual void Destroy(); void IncrRefCount(); void DecrRefCount(); iwhPropGet unsigned int GetRefCount() const; virtual void ActivateTurboBoost(); virtual void DeactivateTurboBoost(); // Use all supported data types to get full coverage of the // shadow layer generator: // virtual void VUnsignedChar(unsigned char arg); virtual void VUnsignedShort(unsigned short arg); virtual void VUnsignedInt(unsigned int arg); virtual void VUnsignedLong(unsigned long arg); virtual void VUnsignedInt64(VehicleUInt64 arg); virtual void VChar(char arg); virtual void VShort(short arg); virtual void VInt(int arg); virtual void VLong(long arg); virtual void VInt64(VehicleInt64 arg); virtual void VBool(bool arg); virtual void VFloat(float arg); virtual void VDouble(double arg); virtual void VVoidPointer(void* arg); virtual void VObjectPointer(BlatMobile* arg); protected: BlatMobile(); virtual ~BlatMobile(); private: unsigned int m_RefCount; }; #endif mummy-1.0.3/Examples/Vehicles/base/CMakeLists.txt0000644000175000017500000000125712120621217021522 0ustar mathieumathieuSET(deps "") DEFINE_KIT( "base" deps "AbstractVehicle" "BlatMobile" "FuelLevelChanged" "FuelLevelChangedEventArgs" "Oops" "RefCountedVehicle" "SignatureSeries" "SimpleVehicle" "Vehicle" "VehicleDescriptor" ) # Extra files (not wrapped, or force to show up in VS project UI, for example): SET(base_source_files ${base_source_files} "AbstractVehicleEvent.h" "InlineWrapperHints.h" "SenderDataEvent.h" "SillyString.cxx" "SillyString.h" "UnwrappedClass.cxx" "UnwrappedClass.h" ) ADD_LIBRARY(base ${base_source_files}) IF(Vehicles_INSTALL_TARGETS) INSTALL(TARGETS base RUNTIME DESTINATION "." LIBRARY DESTINATION ".") ENDIF(Vehicles_INSTALL_TARGETS) mummy-1.0.3/Examples/Vehicles/base/FuelLevelChanged.h0000644000175000017500000000227312120621217022267 0ustar mathieumathieu#ifndef _FUELLEVELCHANGED_H #define _FUELLEVELCHANGED_H #include "AbstractVehicleEvent.h" // parent class #include "FuelLevelChangedEventArgs.h" // args class // This is for gccxml attributes testing/development, // it's not just random madness: // gxa(a1) typedef gxa(a2) long gxa(a3) MyNonClassLong gxa(a4); class iwhEvent FuelLevelChanged : public AbstractVehicleEvent { public: // More gccxml attributes testing/development: // gxa(b1) typedef gxa(b2) long gxa(b3) MyLong gxa(b4); gxa(l1) MyLong ReturnMyLong() { return (MyLong) 10; } MyNonClassLong ReturnMyNonClassLong() { return (MyNonClassLong) 11; } // The real stuff of this class: // typedef void (SDE_CC *Handler)(AbstractVehicle* sender, FuelLevelChangedEventArgs* data); unsigned int AddHandler(Handler of) { return (unsigned int) attach(of); } void RemoveHandler(unsigned int ofid) { detach((EventHandlerId) ofid); } static FuelLevelChanged* New() { return new FuelLevelChanged; } virtual void Delete() { delete this; } protected: FuelLevelChanged() { } virtual ~FuelLevelChanged() { } }; #endif // _FUELLEVELCHANGED_H mummy-1.0.3/Examples/Vehicles/base/FuelLevelChangedEventArgs.h0000644000175000017500000000141612120621217024104 0ustar mathieumathieu#ifndef _FUELLEVELCHANGEDEVENTARGS_H #define _FUELLEVELCHANGEDEVENTARGS_H #include "VehiclesConfig.h" // FuelLevelChangedEventArgs is a "yet to be documented" example class... class base_dll FuelLevelChangedEventArgs { public: iwhPropSet void SetOldLevel(double d) { this->OldLevel = d; } iwhPropGet double GetOldLevel() const { return this->OldLevel; } iwhPropSet void SetLevel(double d) { this->Level = d; } iwhPropGet double GetLevel() const { return this->Level; } static FuelLevelChangedEventArgs* New() { return new FuelLevelChangedEventArgs; } virtual void Delete() { delete this; } protected: FuelLevelChangedEventArgs() {} virtual ~FuelLevelChangedEventArgs() {} private: double OldLevel; double Level; }; #endif // _FUELLEVELCHANGEDEVENTARGS_H mummy-1.0.3/Examples/Vehicles/base/InlineWrapperHints.h0000644000175000017500000001472712120621217022726 0ustar mathieumathieu#ifndef _InlineWrappingHints_h #define _InlineWrappingHints_h // All inline wrapping hint macros are prefixed with "iwh" // // If being "compiled" by gccxml, use the gccxml attribute: // #ifdef __GCCXML__ #define IWH_USE_GCCXML_ATTRIBUTE #endif // Documentation on gccxml attributes can be found by running gccxml --help. // Source for that documentation is in "GXFront/gxDocumentation.cxx" // #ifdef IWH_USE_GCCXML_ATTRIBUTE #define gxa(x) __attribute((gccxml(#x))) #else #define gxa(x) #endif //---------------------------------------------------------------------------- /// /// Array size hint. Used to indicate that a C++ pointer-to-fundamental-type /// is a fixed-and-known-at-compile-time size. Parameter to this hint should /// be the size of the array in number of elements. /// The array size hint is only valid on method return types and on method /// parameter types. /// #define iwhArraySize(s) gxa(iwhArraySize##s) //---------------------------------------------------------------------------- /// /// The "already ref counted" hint. Used to indicate that an object pointer /// returned from a method is already ref counted and that an eventual /// UnRegister call is required by the caller. /// The counted hint is only valid on method return types. /// #define iwhCounted gxa(iwhCounted) //---------------------------------------------------------------------------- /// /// Method event hint. Used to indicate that a C++ method is an "event get" /// method. Typically such a method returns a pointer to a nested event /// instance. Methods marked with this hint get transformed into C# event /// members. /// This hint is only valid on method return types. /// #define iwhEvent gxa(iwhEvent) //---------------------------------------------------------------------------- /// /// Exclude from wrapping hint. Used to prevent an otherwise-wrappable method /// from being wrapped. /// This hint is only valid on methods. /// #define iwhExclude gxa(iwhExclude) //---------------------------------------------------------------------------- /// /// Derive the wrapped class from the named interface, if the named interface /// is one that is known/has meaning in the target language. This is used, /// for example, to impart derivation knowledge for IEnumerable to collection /// classes and IEnumerator to enumerator classes in C#. The C++ class /// definition must have methods in it that satisfy the interface /// requirements when wrapped into the target language. /// This hint is only valid on class types. /// #define iwhImplementsInterface(i) gxa(iwhImplementsInterface##i) //---------------------------------------------------------------------------- /// /// Map this class to the given type. For example, "iwhMapToType(string)" is /// used to map C++ string-like classes into native C# strings. /// This hint is only valid on class types. /// #define iwhMapToType(t) gxa(iwhMapToType##t) //---------------------------------------------------------------------------- /// /// Hint that indicates to suppress public field get/set generation. Used to /// enable writing field accessors manually for C# structs. /// This hint is only valid on class types that also have a iwhUtility hint. /// #define iwhNoFieldAccess gxa(iwhNoFieldAccess) //---------------------------------------------------------------------------- /// /// Hint that indicates to wrap a method as a "property get" if that notion /// has meaning in the target language. If not, wrap as a regular method. /// This hint is only valid on methods. /// #define iwhPropGet gxa(iwhPropGet) //---------------------------------------------------------------------------- /// /// Hint that indicates to wrap a method as a "property set" if that notion /// has meaning in the target language. If not, wrap as a regular method. /// This hint is only valid on methods. /// #define iwhPropSet gxa(iwhPropSet) //---------------------------------------------------------------------------- /// /// Call the named method on an instance of a C++ string-like class to get a /// temporary "char*" that can be used to marshal a copy of the string to the /// target wrapped language. /// This hint is only valid on class types that also have a /// iwhMapToType(string) hint. /// #define iwhStringMethod(m) gxa(iwhStringMethod##m) //---------------------------------------------------------------------------- /// /// Exists for testing the attribute mechanism without actually assigning an /// attribute that means something to an entity. /// #define iwhTestIWH gxa(iwhTestIWH) //---------------------------------------------------------------------------- /// /// Designates a class as a "utility" class. Utility classes get wrapped into /// C# as structs. Methods of such classes are not wrapped, only "plain old /// data" data members. /// The utility hint is only valid on class definitions. /// #define iwhUtility gxa(iwhUtility) //---------------------------------------------------------------------------- // For now, disable this one warning when building the mummy "export layer" // cxx files... C4190 is "C-linkage specified, but returns UDT which is // incompatible with C". The docs for this warning say it doesn't matter as // long as the caller is built with C++, but I'm not 100% certain how the // PInvoke layer from the .NET side of the fence actually calls into the // export layer when a class/struct is returned by value. // // Here are the Microsoft docs for this warning: // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/C4190.asp // // But we need to use extern "C" to avoid the automatic name mangling that // occurs when not using it... (So that the actual name of the export is the // same as the name of the exported function, and the PInvoke/DllImport layer // in C# can find it using that name.) So, the point is to avoid the name // mangling, not to be able to call *all* of these functions from "C" code... // // So, the cause of 4190 is using *both* extern "C" and returning class // instances by value. It's unclear to me at this point what the best // permanent resolution for eliminating this warning is... // // For now, simply suppress it until we figure out if it's truly important // in our situation... // #ifdef MUMMY_EXPORT_LAYER_CXX #ifdef _MSC_VER #pragma warning ( disable : 4190 ) #endif #endif #endif mummy-1.0.3/Examples/Vehicles/base/Oops.cxx0000644000175000017500000000064212120621217020423 0ustar mathieumathieu#include "Oops.h" Oops::Oops(const char* description) { if (description) { this->m_Description = description; } } Oops::~Oops() { } Oops* Oops::Clone() { return this->CloneInternal(); } void Oops::Delete() { delete this; } const char* Oops::Description() { return this->m_Description.c_str(); } Oops* Oops::CloneInternal() { Oops* oops = new Oops(this->m_Description.c_str()); return oops; } mummy-1.0.3/Examples/Vehicles/base/Oops.h0000644000175000017500000000145212120621217020050 0ustar mathieumathieu#ifndef _Oops_h #define _Oops_h #include "VehiclesConfig.h" #include // Yeah-yeah-yeah-... // #if defined(_MSC_VER) #pragma warning(disable:4251) /* class needs to have dll-interface to be used by clients */ #endif // This is the sample exception class... class base_dll Oops { public: // Constructor/destructor: Oops(const char* description); virtual ~Oops(); // Exception classes need a clone method: Oops* Clone(); // Exception classes need a disposal method: void Delete(); // Exception classes need some wrappable way to extract information // out of them: // const char* Description(); protected: virtual Oops* CloneInternal(); private: std::string m_Description; // unimplemented : can only be instantiated by the public ctor or Clone Oops(); }; #endif mummy-1.0.3/Examples/Vehicles/base/RefCountedVehicle.cxx0000644000175000017500000000630012120621217023036 0ustar mathieumathieu#include "RefCountedVehicle.h" #include RefCountedVehicle* RefCountedVehicle::Create() { RefCountedVehicle* rcv = new RefCountedVehicle; rcv->IncrRefCount(0); return rcv; } void RefCountedVehicle::Destroy() { this->DecrRefCount(0); } void RefCountedVehicle::IncrRefCount(void*) { ++m_RefCount; } void RefCountedVehicle::DecrRefCount(void*) { --m_RefCount; if (0 == m_RefCount) { delete this; } } unsigned int RefCountedVehicle::GetRefCount() const { return m_RefCount; } const RefCountedVehicle* RefCountedVehicle::GetThisVehicle() const { ++m_CallCounter; // Alternate between returning valid pointers and NULL pointers // for complete branch coverage in the export layer... (Call multiple // times sequentially from the wrapped side for complete coverage...) // if (0 != m_CallCounter%2) { return 0; } return this; } RefCountedVehicle* RefCountedVehicle::GetThatVehicle() const { ++m_CallCounter; // Alternate between returning valid pointers and NULL pointers // for complete branch coverage in the export layer... (Call multiple // times sequentially from the wrapped side for complete coverage...) // if (0 != m_CallCounter%2) { return 0; } return RefCountedVehicle::Create(); } RefCountedVehicle* RefCountedVehicle::GetTheOtherVehicle() const { ++m_CallCounter; // Alternate between returning valid pointers and NULL pointers // for complete branch coverage in the export layer... (Call multiple // times sequentially from the wrapped side for complete coverage...) // if (0 != m_CallCounter%2) { return 0; } if (0 == m_OtherVehicle) { m_OtherVehicle = RefCountedVehicle::Create(); } return m_OtherVehicle; } //---------------------------------------------------------------------------- // These methods are non-iwhCounted-hint methods that are aliases for the // iwhCounted-hint method GetThatVehicle... We achieve the same effect // as having the hint without modifying the C++ header or source by // adding the method names to the MummySettings.xml countedMethodsRegex // attribute... RefCountedVehicle* RefCountedVehicle::GetThatVehicleAlias() const { return this->GetThatVehicle(); } RefCountedVehicle* RefCountedVehicle::GetThatVehicleByAnyOtherName() const { return this->GetThatVehicle(); } //---------------------------------------------------------------------------- //RefCountedVehicle* RefCountedVehicle::GetNoHint() const //{ // return 0; //} //void RefCountedVehicle::SetThis() //{ //} int RefCountedVehicle::NumberOfConstructorCalls = 0; int RefCountedVehicle::NumberOfDestructorCalls = 0; RefCountedVehicle::RefCountedVehicle() { ++NumberOfConstructorCalls; m_RefCount = 0; m_OtherVehicle = 0; m_CallCounter = 0; } RefCountedVehicle::~RefCountedVehicle() { ++NumberOfDestructorCalls; if (m_OtherVehicle) { m_OtherVehicle->Destroy(); } } void RefCountedVehicle::Check() { if (NumberOfConstructorCalls != NumberOfDestructorCalls) { std::cerr << "error: RefCountedVehicle::Check ctor/dtor mismatch - mem leak?" << std::endl; } } // Intentional no-op. // Exists only to test BTX/ETX style exclusion. // void RefCountedVehicle::MethodExcludedByBTXETX() { } mummy-1.0.3/Examples/Vehicles/base/RefCountedVehicle.h0000644000175000017500000000461212120621217022467 0ustar mathieumathieu#ifndef _RefCountedVehicle_h #define _RefCountedVehicle_h #include "VehiclesConfig.h" // RefCountedVehicle is a "yet to be documented" example class... class base_dll RefCountedVehicle { public: static RefCountedVehicle* Create(); virtual void Destroy(); virtual void IncrRefCount(void* cookie); virtual void DecrRefCount(void* cookie); virtual iwhPropGet unsigned int GetRefCount() const; // Description: // These methods all return a RefCountedVehicle. Each one returns a // different sort of RefCountedVehicle. We return a this, a counted // "that" Vehicle, and a non-counted (contained) other vehicle. // The iwhCounted hint tells mummy that GetThatVehicle returns an // instance that is already ref-counted. A missing hint tells mummy // that the returned object is not ref-counted. Given this information, // mummy generates appropriate ref-counting code where needed. iwhPropGet const RefCountedVehicle* GetThisVehicle() const; iwhPropGet iwhCounted RefCountedVehicle* GetThatVehicle() const; iwhPropGet RefCountedVehicle* GetTheOtherVehicle() const; //---------------------------------------------------------------------------- /// /// Methods to test iwhCounted/countedMethodsRegex equivalence /// /// /// These methods are non-iwhCounted-hint methods that are aliases for the /// iwhCounted-hint method GetThatVehicle... We achieve the same effect /// as having the hint without modifying the C++ header or source by /// adding the method names to the MummySettings.xml countedMethodsRegex /// attribute... /// iwhPropGet RefCountedVehicle* GetThatVehicleAlias() const; iwhPropGet RefCountedVehicle* GetThatVehicleByAnyOtherName() const; //RefCountedVehicle* GetNoHint() const; //void SetThis(); // This method is commented with "XML 'special' characters" & stuff in order // to increase coverage results for the < EncodeStringForXml > function. static void Check(); //BTX // This method will not be wrapped because of the //BTX //ETX VTK-style // wrapper exclusion comment markers. static void MethodExcludedByBTXETX(); //ETX protected: RefCountedVehicle(); virtual ~RefCountedVehicle(); private: static int NumberOfConstructorCalls; static int NumberOfDestructorCalls; unsigned int m_RefCount; mutable RefCountedVehicle* m_OtherVehicle; mutable unsigned int m_CallCounter; }; #endif mummy-1.0.3/Examples/Vehicles/base/SenderDataEvent.h0000644000175000017500000000517312120621217022150 0ustar mathieumathieu#ifndef _SENDERDATAEVENT_H #define _SENDERDATAEVENT_H #ifdef _WIN32 #define SDE_CC __stdcall #else #define SDE_CC #endif //---------------------------------------------------------------------------- template class EventHandler { public: virtual void notify(SenderT sender, DataT data) = 0; virtual ~EventHandler() { } }; //---------------------------------------------------------------------------- template class InstanceEventHandler : public EventHandler { typedef void (ListenerT::*PtrMember)(SenderT, DataT); ListenerT* m_object; PtrMember m_member; public: InstanceEventHandler(ListenerT* object, PtrMember member) : m_object(object), m_member(member) { } void notify(SenderT sender, DataT data) { (m_object->*m_member)(sender, data); } }; //---------------------------------------------------------------------------- template class CallbackEventHandler : public EventHandler { typedef void (SDE_CC *CallbackT)(SenderT, DataT); CallbackT Callback; public: CallbackEventHandler(CallbackT callback) : Callback(callback) { } void notify(SenderT sender, DataT data) { (*Callback)(sender, data); } }; //---------------------------------------------------------------------------- typedef unsigned int EventHandlerId; #include class AbstractVehicle; //---------------------------------------------------------------------------- template class SenderDataEvent { typedef std::map *> HandlersMap; HandlersMap Handlers; EventHandlerId NextHandlerId; public: SenderDataEvent() : NextHandlerId(1) {} template EventHandlerId attach(ListenerT* object, void (ListenerT::*member)(SenderT, DataT)) { Handlers[NextHandlerId] = new InstanceEventHandler(object, member); NextHandlerId++; return NextHandlerId-1; } EventHandlerId attach(void (SDE_CC *callback)(SenderT, DataT)) { Handlers[NextHandlerId] = new CallbackEventHandler(callback); NextHandlerId++; return NextHandlerId-1; } bool detach(EventHandlerId id) { typename HandlersMap::iterator it = Handlers.find(id); if (it == Handlers.end()) return false; delete it->second; Handlers.erase(it); return true; } void Invoke(SenderT sender, DataT data) { typename HandlersMap::iterator it = Handlers.begin(); for(; it != Handlers.end(); it++) { it->second->notify(sender, data); } } }; #endif mummy-1.0.3/Examples/Vehicles/base/SignatureSeries.cxx0000644000175000017500000000611012120621217022613 0ustar mathieumathieu#include "SignatureSeries.h" #include "Oops.h" #include #define SS_IMPLEMENT_METHODS(type, type_name) \ void SignatureSeries::Method_##type_name##_param_plain(type arg) \ { \ this->m_##type_name = arg; \ std::cerr << arg << std::endl; \ } \ \ void SignatureSeries::Method_##type_name##_param_const(const type arg) \ { \ this->m_##type_name = arg; \ std::cerr << arg << std::endl; \ } \ \ void SignatureSeries::Method_##type_name##_param_ref(type& arg) \ { \ this->m_##type_name = arg; \ std::cerr << arg << " (via reference " << &arg << ")" << std::endl; \ arg = (type) 0; \ } \ \ void SignatureSeries::Method_##type_name##_param_constref(const type& arg) \ { \ this->m_##type_name = arg; \ std::cerr << arg << " (via reference " << &arg << ")" << std::endl; \ } \ \ void SignatureSeries::Method_##type_name##_param_datapointer(type* arg) \ { \ this->m_##type_name = (type)(arg ? *arg : 999); \ std::cerr << this->m_##type_name << " (via pointer " << arg << ")" << std::endl; \ } \ \ void SignatureSeries::Method_##type_name##_param_constdatapointer(const type* arg) \ { \ this->m_##type_name = (type)(arg ? *arg : 888); \ std::cerr << this->m_##type_name << " (via pointer " << arg << ")" << std::endl; \ } \ \ void SignatureSeries::Method_##type_name##_param_dataconstpointer(type* const arg) \ { \ this->m_##type_name = (type)(arg ? *arg : 777); \ std::cerr << this->m_##type_name << " (via pointer " << arg << ")" << std::endl; \ } \ \ void SignatureSeries::Method_##type_name##_param_constdataconstpointer(const type* const arg) \ { \ this->m_##type_name = (type)(arg ? *arg : 666); \ std::cerr << this->m_##type_name << " (via pointer " << arg << ")" << std::endl; \ } \ \ type SignatureSeries::Method_##type_name##_return_plain() \ { \ return this->m_##type_name; \ } \ \ const type SignatureSeries::Method_##type_name##_return_const() \ { \ return this->m_##type_name; \ } \ \ type& SignatureSeries::Method_##type_name##_return_ref() \ { \ return this->m_##type_name; \ } \ \ const type& SignatureSeries::Method_##type_name##_return_constref() \ { \ return this->m_##type_name; \ } \ \ type* SignatureSeries::Method_##type_name##_return_datapointer() \ { \ return &this->m_##type_name; \ } \ \ const type* SignatureSeries::Method_##type_name##_return_constdatapointer() \ { \ return &this->m_##type_name; \ } \ \ type* const SignatureSeries::Method_##type_name##_return_dataconstpointer() \ { \ return &this->m_##type_name; \ } \ \ const type* const SignatureSeries::Method_##type_name##_return_constdataconstpointer() \ { \ return &this->m_##type_name; \ } SignatureSeries::SignatureSeries() { this->m_int = 1; } SignatureSeries::~SignatureSeries() { } SS_IMPLEMENT_METHODS(int, int); //SS_IMPLEMENT_METHODS(unsigned int, unsigned_int); void SignatureSeries::ThrowExceptionOnPurpose(const char *text) { throw Oops(text); } mummy-1.0.3/Examples/Vehicles/base/SignatureSeries.h0000644000175000017500000000310612120621217022242 0ustar mathieumathieu#ifndef _SignatureSeries_h #define _SignatureSeries_h #include "VehiclesConfig.h" // SignatureSeries is a "yet to be documented" example class... #define SS_DECLARE_METHODS(type, type_name) \ public: \ void Method_##type_name##_param_plain(type arg); \ void Method_##type_name##_param_const(const type arg); \ void Method_##type_name##_param_ref(type& arg); \ void Method_##type_name##_param_constref(const type& arg); \ void Method_##type_name##_param_datapointer(type* arg); \ void Method_##type_name##_param_constdatapointer(const type* arg); \ void Method_##type_name##_param_dataconstpointer(type* const arg); \ void Method_##type_name##_param_constdataconstpointer(const type* const arg); \ type Method_##type_name##_return_plain(); \ const type Method_##type_name##_return_const(); \ type& Method_##type_name##_return_ref(); \ const type& Method_##type_name##_return_constref(); \ type* Method_##type_name##_return_datapointer(); \ const type* Method_##type_name##_return_constdatapointer(); \ type* const Method_##type_name##_return_dataconstpointer(); \ const type* const Method_##type_name##_return_constdataconstpointer(); \ private: \ type m_##type_name; \ public: class base_dll SignatureSeries { public: SignatureSeries(); virtual ~SignatureSeries(); // Try each of "plain" "ref" "pointer" "const ref" and "const pointer" // as parameter type and as return type for each fundamental data type: // SS_DECLARE_METHODS(int, int); //SS_DECLARE_METHODS(unsigned int, unsigned_int); void ThrowExceptionOnPurpose(const char *text); }; #endif mummy-1.0.3/Examples/Vehicles/base/SillyString.cxx0000644000175000017500000000055412120621217021770 0ustar mathieumathieu#include "SillyString.h" #if 0 SillyString::SillyString() : stl_string() { } SillyString::SillyString(const value_type* s) : stl_string(s) { } SillyString::SillyString(const value_type* s, size_type n) : stl_string(s, n) { } SillyString::SillyString(const stl_string& s, size_type pos, size_type n) : stl_string(s, pos, n) { } #endif mummy-1.0.3/Examples/Vehicles/base/SillyString.h0000644000175000017500000000330312120621217021410 0ustar mathieumathieu#ifndef _SillyString_h #define _SillyString_h #if 0 #include "VehiclesConfig.h" #include // http://en.wikipedia.org/wiki/Silly_string // // SillyString is a "yet to be documented" example class... // This class is used to test/demonstrate the "map to native // C# string" feature of mummy... (via the two iwh* hints // used here): // Disable selected MSVC compiler warning messages #if defined(_MSC_VER) #if defined(BUILD_SHARED_LIBS) #pragma warning(disable:4251) /* class needs to have dll-interface to be used by clients */ //#pragma message(" info: disabled warning 4251...") #pragma warning(disable:4275) /* non dll-interface class ... used as base for dll-interface class */ #endif #endif class iwhMapToType(string) iwhStringMethod(c_str) base_dll SillyString : public std::string { public: // The original string type typedef std::string stl_string; public: // String member types typedef stl_string::value_type value_type; typedef stl_string::pointer pointer; typedef stl_string::reference reference; typedef stl_string::const_reference const_reference; typedef stl_string::size_type size_type; typedef stl_string::difference_type difference_type; typedef stl_string::iterator iterator; typedef stl_string::const_iterator const_iterator; typedef stl_string::reverse_iterator reverse_iterator; typedef stl_string::const_reverse_iterator const_reverse_iterator; // SillyString constructors SillyString(); SillyString(const value_type* s); SillyString(const value_type* s, size_type n); SillyString(const stl_string& s, size_type pos = 0, size_type n = npos); }; #endif #endif mummy-1.0.3/Examples/Vehicles/base/SimpleVehicle.cxx0000644000175000017500000000032512120621217022232 0ustar mathieumathieu#include "SimpleVehicle.h" SimpleVehicle::SimpleVehicle() { } SimpleVehicle::~SimpleVehicle() { } int SimpleVehicle::SimpleMethod() { return 0; } SimpleVehicle* SimpleVehicle::ObjectMethod() { return 0; } mummy-1.0.3/Examples/Vehicles/base/SimpleVehicle.h0000644000175000017500000000044712120621217021664 0ustar mathieumathieu#ifndef _SimpleVehicle_h #define _SimpleVehicle_h #include "VehiclesConfig.h" // SimpleVehicle is a "yet to be documented" example class... class base_dll SimpleVehicle { public: SimpleVehicle(); virtual ~SimpleVehicle(); int SimpleMethod(); SimpleVehicle* ObjectMethod(); }; #endif mummy-1.0.3/Examples/Vehicles/base/StructOf12Bytes.h0000644000175000017500000000054212120621217022052 0ustar mathieumathieu#ifndef _StructOf12Bytes_h #define _StructOf12Bytes_h #include "VehiclesConfig.h" // This is a "yet to be documented" example class... class iwhUtility base_dll StructOf12Bytes { public: //-------------------------------------------------------------------------- /// /// Fields /// int Data; double Data2; }; #endif mummy-1.0.3/Examples/Vehicles/base/StructOf16Bytes.h0000644000175000017500000000055712120621217022064 0ustar mathieumathieu#ifndef _StructOf16Bytes_h #define _StructOf16Bytes_h #include "VehiclesConfig.h" // This is a "yet to be documented" example class... class iwhUtility base_dll StructOf16Bytes { public: //-------------------------------------------------------------------------- /// /// Fields /// int Data; double Data2; int Data3; }; #endif mummy-1.0.3/Examples/Vehicles/base/StructOf1Byte.h0000644000175000017500000000051512120621217021605 0ustar mathieumathieu#ifndef _StructOf1Byte_h #define _StructOf1Byte_h #include "VehiclesConfig.h" // This is a "yet to be documented" example class... class iwhUtility base_dll StructOf1Byte { public: //-------------------------------------------------------------------------- /// /// Fields /// bool Data; }; #endif mummy-1.0.3/Examples/Vehicles/base/StructOf2Bytes.h0000644000175000017500000000052112120621217021766 0ustar mathieumathieu#ifndef _StructOf2Bytes_h #define _StructOf2Bytes_h #include "VehiclesConfig.h" // This is a "yet to be documented" example class... class iwhUtility base_dll StructOf2Bytes { public: //-------------------------------------------------------------------------- /// /// Fields /// short Data; }; #endif mummy-1.0.3/Examples/Vehicles/base/StructOf4Bytes.h0000644000175000017500000000051712120621217021775 0ustar mathieumathieu#ifndef _StructOf4Bytes_h #define _StructOf4Bytes_h #include "VehiclesConfig.h" // This is a "yet to be documented" example class... class iwhUtility base_dll StructOf4Bytes { public: //-------------------------------------------------------------------------- /// /// Fields /// int Data; }; #endif mummy-1.0.3/Examples/Vehicles/base/StructOf8Bytes.h0000644000175000017500000000053412120621217022000 0ustar mathieumathieu#ifndef _StructOf8Bytes_h #define _StructOf8Bytes_h #include "VehiclesConfig.h" // This is a "yet to be documented" example class... class iwhUtility base_dll StructOf8Bytes { public: //-------------------------------------------------------------------------- /// /// Fields /// int Data; int Data2; }; #endif mummy-1.0.3/Examples/Vehicles/base/UnwrappedClass.cxx0000644000175000017500000000015112120621217022431 0ustar mathieumathieu#include "UnwrappedClass.h" UnwrappedClass::UnwrappedClass() { } UnwrappedClass::~UnwrappedClass() { } mummy-1.0.3/Examples/Vehicles/base/UnwrappedClass.h0000644000175000017500000000053312120621217022062 0ustar mathieumathieu#ifndef _UnwrappedClass_h #define _UnwrappedClass_h #include "VehiclesConfig.h" // UnwrappedClass is a "yet to be documented" example class... // This class is used to test/demonstrate the "exclude a class // from wrapping" feature of mummy... class base_dll UnwrappedClass { public: UnwrappedClass(); virtual ~UnwrappedClass(); }; #endif mummy-1.0.3/Examples/Vehicles/base/Vehicle.cxx0000644000175000017500000000037612120621217021066 0ustar mathieumathieu#include "Vehicle.h" Vehicle *Vehicle::New() { return new Vehicle; } Vehicle::Vehicle() { } Vehicle::~Vehicle() { } const char *Vehicle::VGetVehicleType() const { return "GenericVehicle"; } double Vehicle::VGetMileage() const { return -1.0; } mummy-1.0.3/Examples/Vehicles/base/Vehicle.h0000644000175000017500000000054112120621217020505 0ustar mathieumathieu#ifndef _Vehicle_h #define _Vehicle_h #include "AbstractVehicle.h" // Vehicle is a "yet to be documented" example class... class base_dll Vehicle : public AbstractVehicle { public: static Vehicle *New(); protected: Vehicle(); virtual ~Vehicle(); virtual const char *VGetVehicleType() const; virtual double VGetMileage() const; }; #endif mummy-1.0.3/Examples/Vehicles/base/VehicleDescriptor.h0000644000175000017500000000175312120621217022552 0ustar mathieumathieu#ifndef _VehicleDescriptor_h #define _VehicleDescriptor_h #include "VehiclesConfig.h" // VehicleDescriptor is a "yet to be documented" example class... class iwhUtility base_dll VehicleDescriptor { public: //-------------------------------------------------------------------------- /// /// Test "enum" wrapping /// enum ManufacturerID { Unknown, Ford = 1001, GM, Chrysler, BMW, Honda, Nissan, Toyota, EtcEtcEtc }; //-------------------------------------------------------------------------- /// /// Fields /// int ZMarker; int ColorCode; float MileageEstimate; bool BoolTest1; int NumberOfDoors; int NumberOfCylinders; bool BoolTest2; char c1; unsigned char uc1; short s1; unsigned short us1; int i1; unsigned int ui1; long l1; unsigned long ul1; float f1; double d1; VehicleInt64 i64; VehicleUInt64 ui64; ManufacturerID enumMfgID; int AMarker; }; #endif mummy-1.0.3/Examples/Vehicles/base/base32.def0000644000175000017500000000000012120621217020502 0ustar mathieumathieumummy-1.0.3/Examples/Vehicles/base/base64.def0000644000175000017500000000000012120621217020507 0ustar mathieumathieumummy-1.0.3/Examples/Vehicles/cars/0000755000175000017500000000000012120621217016773 5ustar mathieumathieumummy-1.0.3/Examples/Vehicles/cars/AbstractCar.cxx0000644000175000017500000000024012120621217021704 0ustar mathieumathieu#include "AbstractCar.h" AbstractCar::AbstractCar() { } AbstractCar::~AbstractCar() { } const char *AbstractCar::VGetVehicleType() const { return "Car"; } mummy-1.0.3/Examples/Vehicles/cars/AbstractCar.h0000644000175000017500000000047112120621217021337 0ustar mathieumathieu#ifndef _AbstractCar_h #define _AbstractCar_h #include "AbstractVehicle.h" // AbstractCar is a "yet to be documented" example class... class cars_dll AbstractCar : public AbstractVehicle { public: AbstractCar(); virtual ~AbstractCar(); protected: virtual const char *VGetVehicleType() const; }; #endif mummy-1.0.3/Examples/Vehicles/cars/CMakeLists.txt0000644000175000017500000000050712120621217021535 0ustar mathieumathieuSET(deps "base") DEFINE_KIT( "cars" deps "AbstractCar" "Mustang" ) ADD_LIBRARY(cars ${cars_source_files}) IF(Vehicles_INSTALL_TARGETS) INSTALL(TARGETS cars RUNTIME DESTINATION "." LIBRARY DESTINATION ".") ENDIF(Vehicles_INSTALL_TARGETS) FOREACH(d ${deps}) TARGET_LINK_LIBRARIES(cars "${${d}_libs}") ENDFOREACH(d) mummy-1.0.3/Examples/Vehicles/cars/Mustang.cxx0000644000175000017500000000114212120621217021133 0ustar mathieumathieu#include "Mustang.h" Mustang *Mustang::New() { return new Mustang; } Mustang::Mustang() { } Mustang::~Mustang() { } double Mustang::VGetMileage() const { return 6.28; } //int Mustang::TestDefaultArgsWarning1(int arg1, int arg2) //{ // return 0; //} //int Mustang::TestDefaultArgsWarning2(int arg1, int arg2, int arg3) //{ // return 0; //} int Mustang::main(int, char* []) { return 0; } int Mustang::VirtualMainPlus(double, int, char* [], long) { return 0; } int Mustang::NonVirtualMain(int, char* []) { return 0; } int Mustang::StillWontBeWrapped(int, char* [], char* []) { return 0; } mummy-1.0.3/Examples/Vehicles/cars/Mustang.h0000644000175000017500000000123112120621217020557 0ustar mathieumathieu#ifndef _Mustang_h #define _Mustang_h #include "AbstractCar.h" // Mustang is a "yet to be documented" example class... class cars_dll Mustang : public AbstractCar { public: static Mustang *New(); // int TestDefaultArgsWarning1(int arg1, int arg2 = 2); // int TestDefaultArgsWarning2(int arg1, int arg2 = 2, int arg3 = 3); static int main(int argc, char* argv[]); virtual int VirtualMainPlus(double threshold, int argc, char* argv[], long flag); int NonVirtualMain(int argc, char* argv[]); int StillWontBeWrapped(int argc, char* argv[], char* argz[]); protected: Mustang(); virtual ~Mustang(); virtual double VGetMileage() const; }; #endif mummy-1.0.3/Examples/Vehicles/cars/cars32.def0000644000175000017500000000000012120621217020536 0ustar mathieumathieumummy-1.0.3/Examples/Vehicles/cars/cars64.def0000644000175000017500000000000012120621217020543 0ustar mathieumathieumummy-1.0.3/Examples/Vehicles/motorcycles/0000755000175000017500000000000012120621217020406 5ustar mathieumathieumummy-1.0.3/Examples/Vehicles/motorcycles/CMakeLists.txt0000644000175000017500000000054412120621217023151 0ustar mathieumathieuSET(deps "base") DEFINE_KIT( "motorcycles" deps "GenericMotorCycle" ) ADD_LIBRARY(motorcycles ${motorcycles_source_files}) IF(Vehicles_INSTALL_TARGETS) INSTALL(TARGETS motorcycles RUNTIME DESTINATION "." LIBRARY DESTINATION ".") ENDIF(Vehicles_INSTALL_TARGETS) FOREACH(d ${deps}) TARGET_LINK_LIBRARIES(motorcycles "${${d}_libs}") ENDFOREACH(d) mummy-1.0.3/Examples/Vehicles/motorcycles/GenericMotorCycle.cxx0000644000175000017500000000053712120621217024514 0ustar mathieumathieu#include "GenericMotorCycle.h" GenericMotorCycle *GenericMotorCycle::New() { return new GenericMotorCycle; } GenericMotorCycle::GenericMotorCycle() { } GenericMotorCycle::~GenericMotorCycle() { } const char *GenericMotorCycle::VGetVehicleType() const { return "MotorCycle"; } double GenericMotorCycle::VGetMileage() const { return 70.71; } mummy-1.0.3/Examples/Vehicles/motorcycles/GenericMotorCycle.h0000644000175000017500000000065612120621217024143 0ustar mathieumathieu#ifndef _GenericMotorCycle_h #define _GenericMotorCycle_h #include "AbstractVehicle.h" // GenericMotorCycle is a "yet to be documented" example class... class motorcycles_dll GenericMotorCycle : public AbstractVehicle { public: static GenericMotorCycle *New(); protected: GenericMotorCycle(); virtual ~GenericMotorCycle(); virtual const char *VGetVehicleType() const; virtual double VGetMileage() const; }; #endif mummy-1.0.3/Examples/Vehicles/motorcycles/motorcycles32.def0000644000175000017500000000000012120621217023564 0ustar mathieumathieumummy-1.0.3/Examples/Vehicles/motorcycles/motorcycles64.def0000644000175000017500000000000012120621217023571 0ustar mathieumathieumummy-1.0.3/Examples/Vehicles/suvs/0000755000175000017500000000000012120621217017043 5ustar mathieumathieumummy-1.0.3/Examples/Vehicles/suvs/CMakeLists.txt0000644000175000017500000000047212120621217021606 0ustar mathieumathieuSET(deps "base") DEFINE_KIT( "suvs" deps "GenericSUV" ) ADD_LIBRARY(suvs ${suvs_source_files}) IF(Vehicles_INSTALL_TARGETS) INSTALL(TARGETS suvs RUNTIME DESTINATION "." LIBRARY DESTINATION ".") ENDIF(Vehicles_INSTALL_TARGETS) FOREACH(d ${deps}) TARGET_LINK_LIBRARIES(suvs "${${d}_libs}") ENDFOREACH(d) mummy-1.0.3/Examples/Vehicles/suvs/GenericSUV.cxx0000644000175000017500000000042112120621217021536 0ustar mathieumathieu#include "GenericSUV.h" GenericSUV *GenericSUV::New() { return new GenericSUV; } GenericSUV::GenericSUV() { } GenericSUV::~GenericSUV() { } const char *GenericSUV::VGetVehicleType() const { return "SUV"; } double GenericSUV::VGetMileage() const { return 13.0; } mummy-1.0.3/Examples/Vehicles/suvs/GenericSUV.h0000644000175000017500000000056612120621217021175 0ustar mathieumathieu#ifndef _GenericSUV_h #define _GenericSUV_h #include "AbstractVehicle.h" // GenericSUV is a "yet to be documented" example class... class suvs_dll GenericSUV : public AbstractVehicle { public: static GenericSUV *New(); protected: GenericSUV(); virtual ~GenericSUV(); virtual const char *VGetVehicleType() const; virtual double VGetMileage() const; }; #endif mummy-1.0.3/Examples/Vehicles/suvs/suvs32.def0000644000175000017500000000000012120621217020656 0ustar mathieumathieumummy-1.0.3/Examples/Vehicles/suvs/suvs64.def0000644000175000017500000000000012120621217020663 0ustar mathieumathieumummy-1.0.3/Examples/Vehicles/tests/0000755000175000017500000000000012120621217017205 5ustar mathieumathieumummy-1.0.3/Examples/Vehicles/tests/CMakeLists.txt0000644000175000017500000000242412120621217021747 0ustar mathieumathieuSET(deps "base" "cars" "motorcycles" "suvs") DEFINE_KIT( "tests" deps "TestAllVehicles" "TestCallback" "TestPerformance" "TestPerformanceArrayAccess" ) ADD_LIBRARY(tests ${tests_source_files}) IF(Vehicles_INSTALL_TARGETS) INSTALL(TARGETS tests RUNTIME DESTINATION "." LIBRARY DESTINATION ".") ENDIF(Vehicles_INSTALL_TARGETS) FOREACH(d ${deps}) TARGET_LINK_LIBRARIES(tests "${${d}_libs}") ENDFOREACH(d) INCLUDE_DIRECTORIES(${tests_include_dirs}) FOREACH(test ${tests_classes}) CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/TestMain.cxx.in" "${CMAKE_CURRENT_BINARY_DIR}/${test}Main.cxx" @ONLY ) ADD_EXECUTABLE(${test} "${CMAKE_CURRENT_BINARY_DIR}/${test}Main.cxx") IF(Vehicles_INSTALL_TARGETS) INSTALL(TARGETS ${test} RUNTIME DESTINATION ".") ENDIF(Vehicles_INSTALL_TARGETS) TARGET_LINK_LIBRARIES(${test} tests) IF(EXECUTABLE_OUTPUT_PATH) SET(exefile ${EXECUTABLE_OUTPUT_PATH}/${test}) ELSE(EXECUTABLE_OUTPUT_PATH) SET(exefile ${test}) ENDIF(EXECUTABLE_OUTPUT_PATH) IF(Mummy_RUN_LONG_TESTS) ADD_TEST(${test} "${exefile}") ELSE(Mummy_RUN_LONG_TESTS) IF("${test}" STREQUAL "TestAllVehicles") ADD_TEST(${test} "${exefile}") ENDIF("${test}" STREQUAL "TestAllVehicles") ENDIF(Mummy_RUN_LONG_TESTS) ENDFOREACH(test) mummy-1.0.3/Examples/Vehicles/tests/TestAllVehicles.cxx0000644000175000017500000000346212120621217022771 0ustar mathieumathieu#include "TestAllVehicles.h" #include "Vehicle.h" #include "Mustang.h" #include "GenericMotorCycle.h" #include "GenericSUV.h" #include "RefCountedVehicle.h" #include "UnwrappedClass.h" #include int PrintAbstractVehicle(const char *context, AbstractVehicle *av) { std::cerr << "context: " << context << std::endl; std::cerr << " av: " << av << std::endl; std::cerr << " GetVIN: " << (char*)(av->GetVIN() ? av->GetVIN() : "(null)") << std::endl; std::cerr << " GetVehicleType: " << av->GetVehicleType() << std::endl; std::cerr << " GetMileage: " << av->GetMileage() << std::endl; std::cerr << std::endl; return 0; } int TestAllVehicles::Main(int argc, char* argv[]) { int err = 0; // 0 == no error std::cerr << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << std::endl; std::cerr << "Begin TestAllVehicles::Main" << std::endl; Vehicle* vn = Vehicle::New(); Vehicle& v1 = *vn; PrintAbstractVehicle("Vehicle", &v1); Mustang* mn = Mustang::New(); Mustang& v2 = *mn; v2.SetVIN("non-default special VIN"); PrintAbstractVehicle("Mustang", &v2); v2.StillWontBeWrapped(argc, argv, argv); GenericMotorCycle* mc3 = GenericMotorCycle::New(); GenericMotorCycle& v3 = *mc3; v3.SetVIN(0); PrintAbstractVehicle("GenericMotorCycle", &v3); GenericSUV* sn = GenericSUV::New(); GenericSUV& v4 = *sn; v4.SetVIN(0); PrintAbstractVehicle("GenericSUV", &v4); std::cerr << "Calling RefCountedVehicle methods..." << std::endl; RefCountedVehicle* rcv = RefCountedVehicle::Create(); rcv->MethodExcludedByBTXETX(); rcv->Destroy(); rcv = 0; UnwrappedClass* uwc = v4.YouCannotCallThisMethodFromTheWrappedLayer(); delete uwc; v1.Delete(); v2.Delete(); v3.Delete(); v4.Delete(); std::cerr << "End TestAllVehicles::Main" << std::endl; return err; } mummy-1.0.3/Examples/Vehicles/tests/TestAllVehicles.h0000644000175000017500000000071012120621217022407 0ustar mathieumathieu#ifndef _TestAllVehicles_h #define _TestAllVehicles_h #include "VehiclesConfig.h" // TestAllVehicles is a "yet to be documented" example class... class tests_dll TestAllVehicles { public: static int Main(int argc, char *argv[]); private: // intentionally unimplemented to prevent instantiating and copying: TestAllVehicles(); TestAllVehicles(const TestAllVehicles& other); TestAllVehicles& operator=(const TestAllVehicles& other); }; #endif mummy-1.0.3/Examples/Vehicles/tests/TestCallback.cxx0000644000175000017500000001104312120621217022264 0ustar mathieumathieu#include "TestCallback.h" #include "Vehicle.h" #include "FuelLevelChanged.h" #include void SDE_CC TheCallback(AbstractVehicle *sender, unsigned long eid, void *clientdata, const void *calldata) { std::cerr << "TheCallback" << std::endl; std::cerr << " sender: " << sender << std::endl; std::cerr << " eid: " << eid << std::endl; std::cerr << " clientdata: " << clientdata << std::endl; std::cerr << " calldata: " << calldata << std::endl; if (calldata) { if (1 == eid) { std::cerr << " interpreted calldata: '" << * (const int *) calldata << "'" << std::endl; } if (2 == eid) { std::cerr << " interpreted calldata: '" << (const char *) calldata << "'" << std::endl; } if (3 == eid) { std::cerr << " interpreted calldata: '" << * (const double *) calldata << "'" << std::endl; } if (4 == eid) { std::cerr << " interpreted calldata: '" << ((AbstractVehicle *) calldata)->GetVIN() << "'" << std::endl; } } } void SDE_CC GlobalFuelLevelChangedCallback(AbstractVehicle* sender, FuelLevelChangedEventArgs* data) { std::cerr << "GlobalFuelLevelChangedCallback" << std::endl; std::cerr << " VIN: " << sender->GetVIN() << std::endl; std::cerr << " oldlevel: " << data->GetOldLevel() << std::endl; std::cerr << " level: " << data->GetLevel() << std::endl; } void TestCallback::FuelLevelChangedCallback(AbstractVehicle* sender, FuelLevelChangedEventArgs* data) { std::cerr << "TestCallback::FuelLevelChangedCallback" << std::endl; std::cerr << " VIN: " << sender->GetVIN() << std::endl; std::cerr << " oldlevel: " << data->GetOldLevel() << std::endl; std::cerr << " level: " << data->GetLevel() << std::endl; } TestCallback::TestCallback() { } TestCallback::~TestCallback() { } int TestCallback::Main(int argc, char *argv[]) { int err = 0; // 0 == no error std::cerr << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << std::endl; std::cerr << "Begin TestCallback::Main" << std::endl; int ai = 0; for (ai= 0; aiattach(&tcb1, &TestCallback::FuelLevelChangedCallback); unsigned int h2id = v1.TGetFuelLevelChangedEvent()->attach(GlobalFuelLevelChangedCallback); v1.SetFuelLevel(0.75); v1.SetFuelLevel(0.75); v1.SetFuelLevel(1.0); v1.SetFuelLevel(1.0); v1.SetFuelLevel(1.0); // Call these "I exist only for gccxml testing of signatures and attributes" // methods just to improve coverage results: // v1.TGetFuelLevelChangedEvent()->ReturnMyLong(); v1.TGetFuelLevelChangedEvent()->ReturnMyNonClassLong(); v1.TGetFuelLevelChangedEvent()->detach(h1id); v1.TGetFuelLevelChangedEvent()->detach(h2id); v1.Delete(); std::cerr << "End TestCallback::Main" << std::endl; return err; } mummy-1.0.3/Examples/Vehicles/tests/TestCallback.h0000644000175000017500000000134412120621217021714 0ustar mathieumathieu#ifndef _TestCallback_h #define _TestCallback_h #include "VehiclesConfig.h" class AbstractVehicle; class FuelLevelChangedEventArgs; // TestCallback is a "yet to be documented" example class... class tests_dll TestCallback { public: static iwhTestIWH int Main(int argc, char *argv[]); protected: // protected constructor/destructor means only instantiable from within Main: TestCallback(); virtual ~TestCallback(); // protected means it won't be wrapped: virtual void FuelLevelChangedCallback(AbstractVehicle* sender, FuelLevelChangedEventArgs* data); private: // intentionally unimplemented to prevent copying: TestCallback(const TestCallback& other); TestCallback& operator=(const TestCallback& other); }; #endif mummy-1.0.3/Examples/Vehicles/tests/TestMain.cxx.in0000644000175000017500000000013512120621217022061 0ustar mathieumathieu#include "@test@.h" int main(int argc, char *argv[]) { return @test@::Main(argc, argv); } mummy-1.0.3/Examples/Vehicles/tests/TestPerformance.cxx0000644000175000017500000000475012120621217023040 0ustar mathieumathieu#include "TestPerformance.h" #include "Vehicle.h" #include #ifdef _WIN32 #include // WIN32 SDK GetTickCount function #else unsigned int GetTickCount() { std::cerr << "warning: fake GetTickCount used - timing results are not correct...\n"; return 0; } #endif #define TicksPerSecond 1000 void ReportTiming(const char *s, unsigned int ts, unsigned int count) { std::cerr << "\n"; std::cerr << "Unmanaged Code Performance Results:\n"; std::cerr << " data type: " << s << "\n"; std::cerr << " seconds: " << ((double)ts / (double)TicksPerSecond) << "\n"; //std::cerr << " ticks: " << ts << "\n"; std::cerr << " count: " << count << "\n"; //std::cerr << " ticks per operation: " << ((double)ts/(double)count) << "\n"; std::cerr << " operations per second: " << ((double)count / (((double)ts / (double)TicksPerSecond))) << "\n"; std::cerr << "\n"; } int TestPerformance::Main(int /*argc*/, char * /*argv*/ []) { int err = 0; // 0 == no error unsigned int ts = 0; unsigned int begin = 0; std::cerr << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << std::endl; std::cerr << "Begin TestPerformance::Main" << std::endl; Vehicle *vn = Vehicle::New(); Vehicle& v1 = *vn; unsigned int i = 0; unsigned int maxi = v1.GetMaxIndex(); std::cerr << "Set/GetValue loop..." << std::endl; begin = GetTickCount(); for (i= 0; i #ifdef _WIN32 #include // WIN32 SDK GetTickCount function #else extern unsigned int GetTickCount(); #endif #define TicksPerSecond 1000 static void ReportTiming(const char *s, unsigned int ts, unsigned int count) { std::cerr << "\n"; std::cerr << "Unmanaged Code Performance Results:\n"; std::cerr << " data type: " << s << "\n"; std::cerr << " seconds: " << ((double)ts / (double)TicksPerSecond) << "\n"; //std::cerr << " ticks: " << ts << "\n"; std::cerr << " count: " << count << "\n"; //std::cerr << " ticks per operation: " << ((double)ts/(double)count) << "\n"; std::cerr << " operations per second: " << ((double)count / (((double)ts / (double)TicksPerSecond))) << "\n"; std::cerr << "\n"; } float multiplyByTwo(float f); int TestPerformanceArrayAccess::Main(int /*argc*/, char * /*argv*/ []) { int err = 0; // 0 == no error unsigned int ts = 0; unsigned int begin = 0; std::cerr << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << std::endl; std::cerr << "Begin TestPerformanceArrayAccess::Main" << std::endl; std::cerr << std::endl; Vehicle *vn = Vehicle::New(); Vehicle& v1 = *vn; unsigned int i = 0; unsigned int maxi = 10*v1.GetMaxIndex(); const unsigned int length = v1.TGetInfoArrayLength(); float *af = v1.InfoArrayBase(); float lf = 0.0; std::cerr << "Direct C++ array write access 'af[i] = lf' loop..." << std::endl; begin = GetTickCount(); for (i= 0; i mummy-1.0.3/Examples/Vehicles/wrappers/csharpmummy/TestMain.cs.in0000644000175000017500000000020412120621217024727 0ustar mathieumathieuusing System; namespace Vehicles { class @test@Exe { public static void Main(string[] args) { @test@.Main(args); } } } mummy-1.0.3/Examples/Vehicles/wrappers/csharpmummy/WrappedException.cs.in0000644000175000017500000000316612120621217026476 0ustar mathieumathieuusing System; using System.Runtime.InteropServices; // DllImport and HandleRef both live here //---------------------------------------------------------------------------- // The namespace name used here should match the _cable_::package value // listed in the gccxml input files... namespace Vehicles { public class WrappedException : Kitware.mummy.Runtime.WrappedException { //------------------------------------------------------------------------ // For each _cable_::group listed in any gccxml input file (the .cxx.in // files that get configured and then sent through gccxml) there needs to // be a const string variable here that names the export-layer dll from // which a class's export layer functions are exported... // // For example, for a group = "vtkCommon" there needs to be a variable // named @CMAKE_SHARED_LIBRARY_PREFIX@vtkCommonEL_dll and its value needs to be the actual name of the // dll file that it represents... (which is either @CMAKE_SHARED_LIBRARY_PREFIX@vtkEL@CMAKE_SHARED_LIBRARY_SUFFIX@ or // @CMAKE_SHARED_LIBRARY_PREFIX@vtkCommonEL@CMAKE_SHARED_LIBRARY_SUFFIX@ depending on if you build one big export layer dll or // one for each kit...) //------------------------------------------------------------------------ //------------------------------------------------------------------------ @MV_EXPORTLAYER_DLL_VARIABLES@ //------------------------------------------------------------------------ protected WrappedException(IntPtr rawCppThis, bool callDisposalMethod, bool strong) : base(rawCppThis, callDisposalMethod, strong) { } } } mummy-1.0.3/Examples/Vehicles/wrappers/csharpmummy/WrappedObject.cs.in0000644000175000017500000000315512120621217025744 0ustar mathieumathieuusing System; using System.Runtime.InteropServices; // DllImport and HandleRef both live here //---------------------------------------------------------------------------- // The namespace name used here should match the _cable_::package value // listed in the gccxml input files... namespace Vehicles { public class WrappedObject : Kitware.mummy.Runtime.WrappedObject { //------------------------------------------------------------------------ // For each _cable_::group listed in any gccxml input file (the .cxx.in // files that get configured and then sent through gccxml) there needs to // be a const string variable here that names the export-layer dll from // which a class's export layer functions are exported... // // For example, for a group = "vtkCommon" there needs to be a variable // named @CMAKE_SHARED_LIBRARY_PREFIX@vtkCommonEL_dll and its value needs to be the actual name of the // dll file that it represents... (which is either @CMAKE_SHARED_LIBRARY_PREFIX@vtkEL@CMAKE_SHARED_LIBRARY_SUFFIX@ or // @CMAKE_SHARED_LIBRARY_PREFIX@vtkCommonEL@CMAKE_SHARED_LIBRARY_SUFFIX@ depending on if you build one big export layer dll or // one for each kit...) //------------------------------------------------------------------------ //------------------------------------------------------------------------ @MV_EXPORTLAYER_DLL_VARIABLES@ //------------------------------------------------------------------------ protected WrappedObject(IntPtr rawCppThis, bool callDisposalMethod, bool strong) : base(rawCppThis, callDisposalMethod, strong) { } } } mummy-1.0.3/Examples/Vehicles/wrappers/csharpmummy/extra.cs.in0000644000175000017500000000114112120621217024327 0ustar mathieumathieu//---------------------------------------------------------------------------- // // This hand-crafted version is no longer necessary as of May 8, 2007 since // mummy automatically wraps "C++ main style param pairs" now... // //---------------------------------------------------------------------------- // // [DllImport("tests", EntryPoint = "@test@_Main")] // static extern int @test@_Main(int argc, [In, Out] string[] argv); // // public static void Main(string[] args) // { // @test@_Main(args.Length, args); // } // //---------------------------------------------------------------------------- mummy-1.0.3/Examples/Vehicles/wrappers/csharpmummy/gccxml.cxx.in0000644000175000017500000000041712120621217024663 0ustar mathieumathieu#include "@header@" #ifdef CABLE_CONFIGURATION namespace _cable_ { const char* const package = "Vehicles"; const char* const package_version = "0.3.1"; const char* const group = "@kit@"; namespace wrappers { typedef @cxxclass@ @cxxclass@_W; } } #endif mummy-1.0.3/FindCsharp.cmake0000644000175000017500000000526212120621217015553 0ustar mathieumathieuFILE(TO_CMAKE_PATH "$ENV{WINDIR}" windir) SET(framework_version "$ENV{FrameworkVersion}") # Prefer v2 of the .NET Framework when both v2 and v3.5 are installed...: # (older, wiser, more stable...) # SET(csc_search_paths "${windir}/Microsoft.NET/Framework/v2.0.50727" "${windir}/Microsoft.NET/Framework/v3.5" "${windir}/Microsoft.NET/Framework/v3.0" ) # ...if using the VS2008 generator, prefer v3.5: # IF(CMAKE_GENERATOR MATCHES "Visual Studio 9 2008") SET(csc_search_paths "${windir}/Microsoft.NET/Framework/v3.5" "${windir}/Microsoft.NET/Framework/v3.0" "${windir}/Microsoft.NET/Framework/v2.0.50727" ) ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 9 2008") # ...if using the VS2010 generator, prefer v4.0: # IF(CMAKE_GENERATOR MATCHES "Visual Studio 10") SET(csc_search_paths "${windir}/Microsoft.NET/Framework/v4.0.30128" "${windir}/Microsoft.NET/Framework/v3.5" "${windir}/Microsoft.NET/Framework/v3.0" "${windir}/Microsoft.NET/Framework/v2.0.50727" ) ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 10") FIND_PROGRAM(csc_EXECUTABLE "csc" ${csc_search_paths} "${windir}/Microsoft.NET/Framework/${framework_version}" "${windir}/Microsoft.NET/Framework/v1.1.4322" "${windir}/Microsoft.NET/Framework/v1.0.3705" NO_DEFAULT_PATH ) IF(NOT csc_EXECUTABLE) FIND_PROGRAM(csc_EXECUTABLE NAMES "csc" "gmcs") ENDIF(NOT csc_EXECUTABLE) FIND_PROGRAM(mono_EXECUTABLE "mono") GET_FILENAME_COMPONENT(csc_DIR "${csc_EXECUTABLE}" PATH) SET(CSC_ACCEPTS_PLATFORM_FLAG 0) SET(CSC_COMPILES_PARTIAL_CLASSES 0) IF(csc_EXECUTABLE) EXECUTE_PROCESS(COMMAND "${csc_EXECUTABLE}" "/?" OUTPUT_VARIABLE CSC_HELP) IF("${CSC_HELP}" MATCHES "/platform:") SET(CSC_ACCEPTS_PLATFORM_FLAG 1) SET(CSC_COMPILES_PARTIAL_CLASSES 1) ENDIF("${CSC_HELP}" MATCHES "/platform:") ENDIF(csc_EXECUTABLE) IF(NOT DEFINED CSC_PLATFORM_FLAG) SET(CSC_PLATFORM_FLAG "") IF(CSC_ACCEPTS_PLATFORM_FLAG) SET(CSC_PLATFORM_FLAG "/platform:x86") IF("${CMAKE_SIZEOF_VOID_P}" GREATER 4) SET(CSC_PLATFORM_FLAG "/platform:x64") ENDIF("${CMAKE_SIZEOF_VOID_P}" GREATER 4) ENDIF(CSC_ACCEPTS_PLATFORM_FLAG) ENDIF(NOT DEFINED CSC_PLATFORM_FLAG) IF(NOT DEFINED CSC_DEBUG_FLAG) SET(CSC_DEBUG_FLAG "") IF("${CMAKE_BUILD_TYPE}" MATCHES "Debug|RelWithDebInfo") SET(CSC_DEBUG_FLAG "/debug") ENDIF("${CMAKE_BUILD_TYPE}" MATCHES "Debug|RelWithDebInfo") IF("${BUILDNAME}" MATCHES "Debug|RelWithDebInfo") SET(CSC_DEBUG_FLAG "/debug") ENDIF("${BUILDNAME}" MATCHES "Debug|RelWithDebInfo") IF("${CMAKE_BINARY_DIR}" MATCHES "Debug|RelWithDebInfo") SET(CSC_DEBUG_FLAG "/debug") ENDIF("${CMAKE_BINARY_DIR}" MATCHES "Debug|RelWithDebInfo") ENDIF(NOT DEFINED CSC_DEBUG_FLAG) mummy-1.0.3/MsvcMacros.cmake0000644000175000017500000000412212120621217015601 0ustar mathieumathieuMACRO(APPEND_FLAGS var flags) IF(NOT "${${var}}" MATCHES "${flags}") SET(${var} "${${var}} ${flags}") #MESSAGE(STATUS "INFO: ${var} changed to '${${var}}'") ENDIF(NOT "${${var}}" MATCHES "${flags}") ENDMACRO(APPEND_FLAGS) MACRO(REPLACE_FLAGS var these those) IF("${${var}}" MATCHES "${these}") STRING(REGEX REPLACE "${these}" "${those}" ${var} "${${var}}") #MESSAGE(STATUS "INFO: ${var} changed to '${${var}}'") ENDIF("${${var}}" MATCHES "${these}") ENDMACRO(REPLACE_FLAGS) MACRO(MSVC_FORCE_WARNING_LEVEL level) IF(MSVC) FOREACH(lang C CXX) FOREACH(suffix "" _DEBUG _MINSIZEREL _RELEASE _RELWITHDEBINFO) REPLACE_FLAGS("CMAKE_${lang}_FLAGS${suffix}" "/W[1-4]" "/W${level}") ENDFOREACH(suffix) ENDFOREACH(lang) ENDIF(MSVC) ENDMACRO(MSVC_FORCE_WARNING_LEVEL) MACRO(MSVC_TREAT_WARNINGS_AS_ERRORS) IF(MSVC) APPEND_FLAGS("CMAKE_C_FLAGS" "/WX") APPEND_FLAGS("CMAKE_CXX_FLAGS" "/WX") ENDIF(MSVC) ENDMACRO(MSVC_TREAT_WARNINGS_AS_ERRORS) MACRO(MSVC_LINK_TO_STATIC_CRT) IF(MSVC) FOREACH(lang C CXX) FOREACH(suffix "" _DEBUG _MINSIZEREL _RELEASE _RELWITHDEBINFO) REPLACE_FLAGS("CMAKE_${lang}_FLAGS${suffix}" "/MD" "/MT") ENDFOREACH(suffix) ENDFOREACH(lang) ENDIF(MSVC) ENDMACRO(MSVC_LINK_TO_STATIC_CRT) MACRO(MSVC_LINK_TO_DLL_CRT) IF(MSVC) FOREACH(lang C CXX) FOREACH(suffix "" _DEBUG _MINSIZEREL _RELEASE _RELWITHDEBINFO) REPLACE_FLAGS("CMAKE_${lang}_FLAGS${suffix}" "/MT" "/MD") ENDFOREACH(suffix) ENDFOREACH(lang) ENDIF(MSVC) ENDMACRO(MSVC_LINK_TO_DLL_CRT) MACRO(MSVC80_FORCE_MANIFEST_LINKER_FLAG) IF(MSVC80) APPEND_FLAGS("CMAKE_EXE_LINKER_FLAGS" "/MANIFEST") APPEND_FLAGS("CMAKE_MODULE_LINKER_FLAGS" "/MANIFEST") APPEND_FLAGS("CMAKE_SHARED_LINKER_FLAGS" "/MANIFEST") ENDIF(MSVC80) ENDMACRO(MSVC80_FORCE_MANIFEST_LINKER_FLAG) MACRO(MSVC_SUPPRESS_CRT_DEPRECATED_WARNINGS) IF(MSVC) ADD_DEFINITIONS("-D_CRT_NONSTDC_NO_DEPRECATE") ADD_DEFINITIONS("-D_CRT_SECURE_NO_DEPRECATE") ADD_DEFINITIONS("-D_SCL_SECURE_NO_DEPRECATE") ENDIF(MSVC) ENDMACRO(MSVC_SUPPRESS_CRT_DEPRECATED_WARNINGS) mummy-1.0.3/MummyApplication.cxx0000644000175000017500000003751612120621217016553 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyApplication.cxx 506 2010-07-27 15:30:53Z david.cole $ // // $Author: david.cole $ // $Date: 2010-07-27 11:30:53 -0400 (Tue, 27 Jul 2010) $ // $Revision: 506 $ // // Copyright (C) 2006-2009 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyApplication.h" #include "MummyCsharpGenerator.h" #include "MummyCsharpExportLayerGenerator.h" #include "MummyCsharpShadowLayerGenerator.h" #include "MummyCsharpUnitTestGenerator.h" #include "MummyLog.h" #include "MummySettings.h" #include "cableClass.h" #include "cableClassType.h" #include "cableContext.h" #include "cableMethod.h" #include "cableNamespace.h" #include "cableSourceRepresentation.h" #include "cableTypedef.h" #include "cableVariable.h" #include "cableXMLSourceParser.h" #include "cxxFundamentalType.h" #include "gxsys/ios/fstream" #include "gxsys/ios/iostream" #include "gxsys/ios/sstream" #include "gxsys/stl/map" #include "gxsys/stl/set" #include "gxsys/stl/string" #include "string.h" // strlen //---------------------------------------------------------------------------- MummyApplication::MummyApplication() { this->Settings = 0; } //---------------------------------------------------------------------------- MummyApplication::~MummyApplication() { } //---------------------------------------------------------------------------- int MummyApplication::Main(int argc, char *argv[]) { int err = 0; MummySettings settings; this->SetSettings(&settings); err = settings.Initialize(argc, argv); if (!err && settings.ShouldRun()) { cable::SourceRepresentation::Pointer sr = BuildSourceRepresentation(); err = ProcessSource(sr); } this->SetSettings(0); return GetFirstErrorValue(); } //---------------------------------------------------------------------------- MummySettings* MummyApplication::GetSettings() { return this->Settings; } //---------------------------------------------------------------------------- void MummyApplication::SetSettings(MummySettings* settings) { this->Settings = settings; } //---------------------------------------------------------------------------- cable::SourceRepresentation* MummyApplication::BuildSourceRepresentation() { const char* inFileName = this->GetSettings()->GetGccxmlFileName(); if (!inFileName || (0 == strlen(inFileName))) { LogError(me_InvalidArg, << "Must specify valid --gccxml-file (use --help for options)."); return 0; } LogVerboseInfo(<< "Using --gccxml-file '" << inFileName << "'"); // Open the XML input file produced by GCC-XML. gxsys_ios::ifstream inFile(inFileName, std::ios_base::in|std::ios_base::binary); if (!inFile) { LogError(me_CouldNotOpen, << "Could not open GCC-XML output: " << inFileName); return 0; } // Parse the XML input file. cable::XMLSourceParser::Pointer parser = cable::XMLSourceParser::New(); parser->SetStream(&inFile); if(!parser->Parse()) { LogError(me_CouldNotParse, << "Could not parse GCC-XML output: " << inFileName); return 0; } parser->SetStream(0); inFile.close(); // Get the parsed source representation. return parser->GetSourceRepresentation(); } //---------------------------------------------------------------------------- int MummyApplication::ProcessSource(cable::SourceRepresentation* sr) { int err = 0; if (!sr) { LogError(me_InvalidArg, << "MummyApplication::ProcessSource"); return me_InvalidArg; } gxsys_stl::string s; const cable::Namespace* gns = sr->GetGlobalNamespace(); // Look inside the _cable_ namespace for a wrappers namespace // and classes within: // cable::Context::Iterator lower = gns->LowerBound("_cable_"); cable::Context::Iterator upper = gns->UpperBound("_cable_"); cable::Namespace* cns = 0; if (lower != upper) { cns = cable::Namespace::SafeDownCast(*lower); } if (!cns) { LogError(me_UnexpectedGccxmlInput, << "MummyApplication::ProcessSource"); return me_UnexpectedGccxmlInput; } // Give the settings object a chance to read package, packageVersion // and group info out of the source rep: // err = this->GetSettings()->ProcessSource(sr); // Collect up all the classes to be wrapped: // gxsys_stl::map TypedefLookup; gxsys_stl::set ClassesToBeIncluded; const cable::Namespace* wns = 0; cable::Context::Iterator wlower = cns->LowerBound("wrappers"); cable::Context::Iterator wupper = cns->UpperBound("wrappers"); if (wlower != wupper) { wns = cable::Namespace::SafeDownCast(*wlower); } if (!wns) { LogError(me_UnexpectedGccxmlInput, << "MummyApplication::ProcessSource"); return me_UnexpectedGccxmlInput; } for (cable::Context::Iterator w = wns->Begin(); w != wns->End(); ++w) { cable::Typedef* td = cable::Typedef::SafeDownCast(*w); if(td) { const cable::ClassType* ct = cable::ClassType::SafeDownCast(td->GetType()); if(ct) { const cable::Class* c = ct->GetClass(); TypedefLookup.insert(gxsys_stl::make_pair(c, td)); ClassesToBeIncluded.insert(c); } } } // Wrap 'em: // for (gxsys_stl::set::iterator i = ClassesToBeIncluded.begin(); !err && i != ClassesToBeIncluded.end(); ++i) { const cable::Class* c = *i; //cable::Typedef* td = 0; //gxsys_stl::map::iterator tdi = // TypedefLookup.find(c); //if(tdi != TypedefLookup.end()) // { // td = tdi->second; // } err = this->ProcessClass(sr, c); } return err; } //---------------------------------------------------------------------------- int MummyApplication::ProcessClass(cable::SourceRepresentation* sr, const cable::Class* c) { int err = 0; if (!ValidateBaseClasses(c)) { LogError(me_CouldNotValidate, << "ValidateBaseClasses failed for class '" << c->GetName() << "'"); return me_CouldNotValidate; } if (!this->GetSettings()->ClassIsWrappable(c)) { LogError(me_CouldNotWrap, << "ClassIsWrappable returned false for class '" << c->GetName() << "'"); return me_CouldNotWrap; } MummyCsharpGenerator csg; gxsys_ios::ostringstream ossCS; csg.SetSettings(this->GetSettings()); csg.SetSourceRepresentation(sr); csg.SetStream(&ossCS); csg.SetTargetClass(c); csg.Generate(); MummyCsharpExportLayerGenerator cselg; gxsys_ios::ostringstream ossEL; cselg.SetCsharpGenerator(&csg); cselg.SetSettings(this->GetSettings()); cselg.SetSourceRepresentation(sr); cselg.SetStream(&ossEL); cselg.SetTargetClass(c); cselg.Generate(); if (this->GetSettings()->GetUseShadow(c)) { MummyCsharpShadowLayerGenerator csslg; csslg.SetCsharpGenerator(&csg); csslg.SetSettings(this->GetSettings()); csslg.SetSourceRepresentation(sr); csslg.SetStream(&ossEL); csslg.SetTargetClass(c); csslg.Generate(); } MummyCsharpUnitTestGenerator csutg; gxsys_ios::ostringstream ossUT; csutg.SetCsharpGenerator(&csg); csutg.SetSettings(this->GetSettings()); csutg.SetSourceRepresentation(sr); csutg.SetStream(&ossUT); csutg.SetTargetClass(c); csutg.Generate(); WriteToFile(this->GetSettings()->GetCsharpFileName(c).c_str(), ossCS.str().c_str()); LogVerboseInfo("Wrote file: " << this->GetSettings()->GetCsharpFileName(c)); WriteToFile(this->GetSettings()->GetExportLayerFileName(c).c_str(), ossEL.str().c_str()); LogVerboseInfo("Wrote file: " << this->GetSettings()->GetExportLayerFileName(c)); // Not yet ready for prime time: // WriteToFile(this->GetSettings()->GetCsharpUnitTestFileName(c).c_str(), ossUT.str().c_str()); // LogVerboseInfo("Wrote file: " << this->GetSettings()->GetCsharpUnitTestFileName(c)); return err; } /// \page roadmap mummy Road Map (Prioritized ToDo List) /// /// /// // // // // P1 // // // /// /// \todo move the MethodInstance data structures inside the C# generator class... /// /// \todo search for generated "C" style comments : indicator /// of "wrapped stuff edge cases"... /// /// \todo make sure that delegates are wrappable function pointer typedefs, /// not just public function pointer typedefs /// /// \todo address IntPtr \<--\> I4 issue for 64-bit builds: /// mummy need to generate different code for 64-bit? /// generate code that determines IntPtr size at runtime? /// /// \todo error/warning stack: treat warnings as errors, suppress *all* warnings... /// /// \todo consolidate GetEnumerationTypeString and GetWrappedEnumName /// /// \todo IsReservedMethodName need any more work? /// /// /// // // // // P2 // // // /// /// \todo perfect delegate signature generation /// /// \todo eliminate \ near-copy of code in delegate generation block /// /// \todo eliminate hard-coded 4100/4099 numbers /// /// \todo wrap static methods in iwhUtility classes (there's no reason why we /// shouldn't / couldn't...) /// /// \todo make enum only classes "root" C# classes -- no need to inherit from /// /// \todo perfect the BTX ETX exclusion mechanism (multiple HeaderFileReader /// objects for parent classes too) for "equivalent to the other wrappers" /// VTK wrapping... /// /// \todo add hint detection for special method (factory, disposal, /// register, unRegister) designation /// /// \todo add KWStyle analysis dashboard of source code /// /// \todo enable wrapping deprecated methods? would anybody want this? /// (right now they are always excluded from wrapping) /// /// \todo how to wrap smart pointers smartly? how does ITK/Java do it? /// /// /// // // // // P3 // // // /// /// \todo more build info cached in executable : resource of text output: /// cvs status of CableSwig/CMakeLists.txt, svn info (for revision of /// mummy source directory), build environment, development environment /// version (VS, gcc/cl version), platform environment /// /// \todo shadow classes : another way to implement them besides IDispatch?? /// existing implementation should really only provide overrides of the methods /// directly in the class itself /// depending on parent classes could introduce wrapper dependencies we don't want /// if the generation of supporting code is conditional based on whether the class /// being wrapped is a shadow or not /// /// \todo get rid of trailing whitespace in documentation comment blocks?? /// /// \todo remove unnecessary comment blocks (saved/old code, now unneeded) /// /// \todo web page / html documentation /// /// \todo document all code (at least all classes and methods) /// point to MummyApplication::ProcessClass as main entry point of interest /// document all possible MummySettings.xml values /// /// \todo document assumptions made of hand-crafted base class of generated /// classes: /// WrappedObject /// IDisposable /// destructor /// GetCallDisposalMethod /// GetCppThis /// ClearCppThis /// etc. /// /// \todo document "event assumptions"... /// /// \todo write a blurb about performance tests for direct C# array access /// that explains it requires use of the unsafe C# keyword and use of /// the /unsafe compiler command line flag // // // DONE // // // // get rid of "ref" args for things like "double*" and "int*" where // we do not know how much memory the thing points to... Translate to an // array if size is known, otherwise, translate to IntPtr -- only use // "ref" for "double&" (actual reference-type args...) // configure or generate an AssemblyInfo.cs with version number info in it // for each managed dll... // pull in VTK hints file (similar to inline hint iwhArraySize) // hand-craft(?) VTK events // "install" // identify all methods that require the iwhCounted hint because they // return objects that have already been registered (anything "like" // a factory method) // flesh out C# keywords table to include *all* C# keywords // Make getters const -- add warnings to mummy for void/non-const getters... // (added mw_PropGetReturnsVoid and mw_PropGetNotConst) // hint to remove "property get/set or just set" code from *some* generated C# // structs?? -- iwhNoFieldAccess -- (add the hint, then write gets/sets // manually...) // other Session Manager ModelCreated/Deleting events (namespace qualification // required...) // handle NULL object pointer return values from methods properly // test infrastructure work : mummy wrapping of "main" style funcs // recognize argc/argv param pairs and transform to a single string[] param in // the C# method (automatic "main" wrapping...) -- if name is "main" transform // to "Main"?? // handle Register/UnRegister properly // turn warnings back on // add "iwhPropGet/iwhPropSet needed?" for "^[gGsS]et" methods warning // warning suppression code, so we can ignore the many, many warnings // from wrapping VTK while still keeping them for other code bases... // make header file header blocks uniform -- update copyright everywhere: // header and source file leading comment blocks // re-structuring (table of all objects, one-to-one map, // methodology for removing objects from table, a working "KeepAlive" strategy) // table stuff and other incidentals while I'm in there... // consistently log errors when functions that return type strings encounter // an unknown type // make sure wrapped reference args work at runtime - done in SignatureSeries // example class // search for any generated "ERROR_" chunks //---------------------------------------------------------------------------- /// \mainpage mummy - Wrapper Generator /// mummy is a command line executable that generates C# wrappers from gccxml /// output. A C# class is generated to wrap the wrappable class named in the /// gccxml output. Settings to control the wrapping are given inline directly /// in the class header file or in the MummySettings.xml input file. /// /// mummy transfers comment blocks in the source code as XML documentation /// comments. If they are already XML documentation comments, as indicated by /// the presence of \ or \ in the comment block, then they /// are simply copied over as is. If not, they are surrounded by \ /// and \ tags to indicate to doxygen that the comment block is the /// detailed description block. /// /// The following table shows XML documentation tags and their doxygen and /// JavaDoc equivalents: /// /// \verbatim /// XML documentation doxygen command equivalent Javadoc comment tag equivalent /// ================================================== ========================== =============================== /// \detail None /// \brief None /// name \author name @author name /// description None @deprecated description /// text None @exception exception-class text /// text \param paramname text @param paramname text /// text \return text @return text /// \ref typename @see typename /// \sa typename::member @see typename#member /// property-description None @value property-description /// text None @version text /// \endverbatim /// /// Sources: /// /// http://msdn2.microsoft.com/en-us/library/fzdc5d5k%28VS.80%29.aspx /// /// http://www.stack.nl/~dimitri/doxygen/xmlcmds.html /// /// Full doxygen manual: /// /// http://www.stack.nl/~dimitri/doxygen/manual.html /// /// \author David Cole mummy-1.0.3/MummyApplication.h0000644000175000017500000000576212120621217016176 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyApplication.h // // Author(s) : David Cole // // Copyright (C) 2006-2007 Kitware, Inc. //---------------------------------------------------------------------------- #include "MummyUtilities.h" // first mummy include for root classes namespace cable { class Class; class SourceRepresentation; } class MummySettings; //---------------------------------------------------------------------------- /// /// Mummy's main entry point object. /// class MummyApplication { public: MummyApplication(); virtual ~MummyApplication(); //-------------------------------------------------------------------------- /// /// "Command line style" entry point. /// Run "mummy --help" from a command prompt to see command line options. /// The console application simply instantiates a MummyApplication object /// and delegates to this method. /// /// The number of command line arguments in argv. /// Array of command line arguments, indexed from 0 to argc-1. /// Exit status. 0 means success. virtual int Main(int argc, char *argv[]); //-------------------------------------------------------------------------- /// /// Get the associated settings object. /// /// Associated MummySettings object. virtual MummySettings* GetSettings(); //-------------------------------------------------------------------------- /// /// Set the associated settings object. /// /// MummySettings object virtual void SetSettings(MummySettings* settings); //-------------------------------------------------------------------------- /// /// Builds an object model "source representation" from the input file /// produced by gccxml. /// /// The source representation. virtual cable::SourceRepresentation* BuildSourceRepresentation(); //-------------------------------------------------------------------------- /// /// Processes the source representation to initialize some settings and /// determine what class to wrap. /// /// A valid "source representation" object model. /// Return status. 0 means success. virtual int ProcessSource(cable::SourceRepresentation* sr); //-------------------------------------------------------------------------- /// /// Processes the class to wrap and generates appropriate output files based /// on the generators used. /// /// A valid "source representation" object model. /// The class to wrap. /// Return status. 0 means success. virtual int ProcessClass(cable::SourceRepresentation* sr, const cable::Class* c); private: MummySettings* Settings; }; mummy-1.0.3/MummyCMakeMacros.cmake0000644000175000017500000003122512120621217016702 0ustar mathieumathieuMACRO(ADD_CSHARP_EXECUTABLE ace_ExeName ace_DependentTargets ace_References ace_LinkResources ace_SnkFile) IF("${ARGN}" STREQUAL "") MESSAGE(FATAL_ERROR "ADD_CSHARP_EXECUTABLE requires at least one optional argument.") ENDIF("${ARGN}" STREQUAL "") IF(DEFINED MUMMY_ADD_CSHARP_SRCDIR) SET(ace_SrcDir "${MUMMY_ADD_CSHARP_SRCDIR}") ELSE() SET(ace_SrcDir "${CMAKE_CURRENT_SOURCE_DIR}") ENDIF() IF(DEFINED MUMMY_ADD_CSHARP_BINDIR) SET(ace_BinDir "${MUMMY_ADD_CSHARP_BINDIR}") ELSE() SET(ace_BinDir "${CMAKE_CURRENT_BINARY_DIR}") ENDIF() SET(ace_ExeDir "${ace_BinDir}/${CMAKE_CFG_INTDIR}") IF(CMAKE_RUNTIME_OUTPUT_DIRECTORY) SET(ace_ExeDir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}") ELSEIF(EXECUTABLE_OUTPUT_PATH) SET(ace_ExeDir "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}") ENDIF() SET(ace_CscRefs "") SET(ace_CMakeRefs "") FOREACH(ace_r ${ace_References}) SET(ace_rr "${ace_r}") IF(NOT "${ace_rr}" MATCHES "^System\\.") IF(NOT "${ace_rr}" MATCHES "/") SET(ace_rr "${ace_ExeDir}/${ace_rr}") ENDIF(NOT "${ace_rr}" MATCHES "/") IF(NOT "${ace_rr}" MATCHES "dll$") SET(ace_rr "${ace_rr}.dll") ENDIF(NOT "${ace_rr}" MATCHES "dll$") SET(ace_CMakeRefs ${ace_CMakeRefs} "${ace_rr}") ENDIF(NOT "${ace_rr}" MATCHES "^System\\.") IF(WIN32) STRING(REGEX REPLACE "/" "\\\\" ace_rr "${ace_rr}") ENDIF(WIN32) SET(ace_CscRefs ${ace_CscRefs} "/reference:${ace_rr}") ENDFOREACH(ace_r) SET(ace_CscLinkResourceArgs "") FOREACH(ace_lr ${ace_LinkResources}) SET(ace_item "${ace_lr}") IF(NOT "${ace_item}" MATCHES "/") SET(ace_item "${ace_ExeDir}/${ace_item}") ENDIF(NOT "${ace_item}" MATCHES "/") IF(WIN32) STRING(REGEX REPLACE "/" "\\\\" ace_item "${ace_item}") ENDIF(WIN32) SET(ace_CscLinkResourceArgs ${ace_CscLinkResourceArgs} "/linkresource:${ace_item}") ENDFOREACH(ace_lr) SET(ace_CscArgs "") FOREACH(ace_f ${ARGN}) SET(ace_CscArgs "${ace_CscArgs}\"${ace_f}\"\n") ENDFOREACH(ace_f) SET(ace_CscOut "${ace_ExeDir}/${ace_ExeName}.exe") SET(ace_CscDoc "${ace_ExeDir}/${ace_ExeName}.xml") IF(WIN32) STRING(REGEX REPLACE "/" "\\\\" ace_CscArgs "${ace_CscArgs}") STRING(REGEX REPLACE "/" "\\\\" ace_CscOut "${ace_CscOut}") STRING(REGEX REPLACE "/" "\\\\" ace_CscDoc "${ace_CscDoc}") ENDIF(WIN32) IF(CMAKE_CONFIGURATION_TYPES AND DEFINED MUMMY_ADD_CSHARP_CONFIG) STRING(REPLACE "${CMAKE_CFG_INTDIR}" "${MUMMY_ADD_CSHARP_CONFIG}" ace_CscLinkResourceArgs "${ace_CscLinkResourceArgs}") FOREACH(ace_f ${ace_CscLinkResourceArgs}) SET(ace_CscArgs "${ace_CscArgs}\"${ace_f}\"\n") ENDFOREACH(ace_f) SET(ace_CscLinkResourceArgs "") ENDIF() IF(NOT "${ace_SnkFile}" STREQUAL "") SET(ace_f "${ace_SnkFile}") IF(WIN32) STRING(REGEX REPLACE "/" "\\\\" ace_f "${ace_f}") ENDIF(WIN32) # If the keyfile name ends in ".pub.snk" then it's a public key # half of a strong name signature and we should add the "delaysign" # flag. Otherwise, assume it's a full key pair for a strong name # signature and just specify the keyfile. # IF(ace_f MATCHES "\\.pub\\.snk$") SET(ace_CscArgs "${ace_CscArgs}/delaysign+\n") ENDIF(ace_f MATCHES "\\.pub\\.snk$") SET(ace_CscArgs "${ace_CscArgs}/keyfile:\"${ace_f}\"\n") ENDIF(NOT "${ace_SnkFile}" STREQUAL "") SET(CscArgs ${ace_CscArgs}) CONFIGURE_FILE( "${ace_SrcDir}/CscArgs.txt.in" "${ace_BinDir}/${ace_ExeName}.CscArgs.txt" @ONLY ) IF(csc_EXECUTABLE) ADD_CUSTOM_COMMAND( OUTPUT "${ace_ExeDir}/${ace_ExeName}.exe" DEPENDS ${ARGN} "${ace_BinDir}/${ace_ExeName}.CscArgs.txt" ${ace_CMakeRefs} COMMAND ${csc_EXECUTABLE} ARGS ${CSC_DEBUG_FLAG} ${CSC_PLATFORM_FLAG} "/out:${ace_CscOut}" "/doc:${ace_CscDoc}" "/target:exe" ${ace_CscLinkResourceArgs} ${ace_CscRefs} "@${ace_BinDir}/${ace_ExeName}.CscArgs.txt" COMMENT "Building C# executable '${ace_ExeName}'..." ) ADD_CUSTOM_TARGET( "${ace_ExeName}" ALL DEPENDS "${ace_ExeDir}/${ace_ExeName}.exe" ) IF(NOT "${ace_DependentTargets}" STREQUAL "") ADD_DEPENDENCIES("${ace_ExeName}" ${ace_DependentTargets}) ENDIF(NOT "${ace_DependentTargets}" STREQUAL "") ENDIF(csc_EXECUTABLE) ENDMACRO(ADD_CSHARP_EXECUTABLE) MACRO(ADD_CSHARP_LIBRARY acl_LibName acl_DependentTargets acl_References acl_LinkResources acl_SnkFile) IF("${ARGN}" STREQUAL "") MESSAGE(FATAL_ERROR "ADD_CSHARP_LIBRARY requires at least one optional argument.") ENDIF("${ARGN}" STREQUAL "") IF(DEFINED MUMMY_ADD_CSHARP_SRCDIR) SET(acl_SrcDir "${MUMMY_ADD_CSHARP_SRCDIR}") ELSE() SET(acl_SrcDir "${CMAKE_CURRENT_SOURCE_DIR}") ENDIF() IF(DEFINED MUMMY_ADD_CSHARP_BINDIR) SET(acl_BinDir "${MUMMY_ADD_CSHARP_BINDIR}") ELSE() SET(acl_BinDir "${CMAKE_CURRENT_BINARY_DIR}") ENDIF() SET(acl_ExeDir "${acl_BinDir}/${CMAKE_CFG_INTDIR}") IF(CMAKE_RUNTIME_OUTPUT_DIRECTORY) SET(acl_ExeDir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}") ELSEIF(EXECUTABLE_OUTPUT_PATH) SET(acl_ExeDir "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}") ENDIF() SET(acl_CscRefs "") SET(acl_CMakeRefs "") FOREACH(acl_r ${acl_References}) SET(acl_rr "${acl_r}") IF(NOT "${acl_rr}" MATCHES "^System\\.") IF(NOT "${acl_rr}" MATCHES "/") SET(acl_rr "${acl_ExeDir}/${acl_rr}") ENDIF(NOT "${acl_rr}" MATCHES "/") IF(NOT "${acl_rr}" MATCHES "dll$") SET(acl_rr "${acl_rr}.dll") ENDIF(NOT "${acl_rr}" MATCHES "dll$") SET(acl_CMakeRefs ${acl_CMakeRefs} "${acl_rr}") ENDIF(NOT "${acl_rr}" MATCHES "^System\\.") IF(WIN32) STRING(REGEX REPLACE "/" "\\\\" acl_rr "${acl_rr}") ENDIF(WIN32) SET(acl_CscRefs ${acl_CscRefs} "/reference:${acl_rr}") ENDFOREACH(acl_r) SET(acl_CscLinkResourceArgs "") FOREACH(acl_lr ${acl_LinkResources}) SET(acl_item "${acl_lr}") IF(NOT "${acl_item}" MATCHES "/") SET(acl_item "${acl_ExeDir}/${acl_item}") ENDIF(NOT "${acl_item}" MATCHES "/") IF(WIN32) STRING(REGEX REPLACE "/" "\\\\" acl_item "${acl_item}") ENDIF(WIN32) SET(acl_CscLinkResourceArgs ${acl_CscLinkResourceArgs} "/linkresource:${acl_item}") ENDFOREACH(acl_lr) SET(acl_CscArgs "") FOREACH(acl_f ${ARGN}) SET(acl_CscArgs "${acl_CscArgs}\"${acl_f}\"\n") ENDFOREACH(acl_f) SET(acl_CscOut "${acl_ExeDir}/${acl_LibName}.dll") SET(acl_CscDoc "${acl_ExeDir}/${acl_LibName}.xml") IF(WIN32) STRING(REGEX REPLACE "/" "\\\\" acl_CscArgs "${acl_CscArgs}") STRING(REGEX REPLACE "/" "\\\\" acl_CscOut "${acl_CscOut}") STRING(REGEX REPLACE "/" "\\\\" acl_CscDoc "${acl_CscDoc}") ENDIF(WIN32) IF(CMAKE_CONFIGURATION_TYPES AND DEFINED MUMMY_ADD_CSHARP_CONFIG) STRING(REPLACE "${CMAKE_CFG_INTDIR}" "${MUMMY_ADD_CSHARP_CONFIG}" acl_CscLinkResourceArgs "${acl_CscLinkResourceArgs}") FOREACH(acl_f ${acl_CscLinkResourceArgs}) SET(acl_CscArgs "${acl_CscArgs}\"${acl_f}\"\n") ENDFOREACH() SET(acl_CscLinkResourceArgs "") ENDIF() IF(NOT "${acl_SnkFile}" STREQUAL "") SET(acl_f "${acl_SnkFile}") IF(WIN32) STRING(REGEX REPLACE "/" "\\\\" acl_f "${acl_f}") ENDIF(WIN32) # If the keyfile name ends in ".pub.snk" then it's a public key # half of a strong name signature and we should add the "delaysign" # flag. Otherwise, assume it's a full key pair for a strong name # signature and just specify the keyfile. # IF(acl_f MATCHES "\\.pub\\.snk$") SET(acl_CscArgs "${acl_CscArgs}/delaysign+\n") ENDIF(acl_f MATCHES "\\.pub\\.snk$") SET(acl_CscArgs "${acl_CscArgs}/keyfile:\"${acl_f}\"\n") ENDIF(NOT "${acl_SnkFile}" STREQUAL "") SET(CscArgs ${acl_CscArgs}) CONFIGURE_FILE( "${acl_SrcDir}/CscArgs.txt.in" "${acl_BinDir}/${acl_LibName}.CscArgs.txt" @ONLY ) IF(csc_EXECUTABLE) ADD_CUSTOM_COMMAND( OUTPUT "${acl_ExeDir}/${acl_LibName}.dll" DEPENDS ${ARGN} "${acl_BinDir}/${acl_LibName}.CscArgs.txt" ${acl_CMakeRefs} COMMAND ${csc_EXECUTABLE} ARGS ${CSC_DEBUG_FLAG} ${CSC_PLATFORM_FLAG} "/out:${acl_CscOut}" "/doc:${acl_CscDoc}" "/target:library" ${acl_CscLinkResourceArgs} ${acl_CscRefs} "@${acl_BinDir}/${acl_LibName}.CscArgs.txt" COMMENT "Building C# library '${acl_LibName}'..." ) ADD_CUSTOM_TARGET( "${acl_LibName}" ALL DEPENDS "${acl_ExeDir}/${acl_LibName}.dll" ) IF(NOT "${acl_DependentTargets}" STREQUAL "") ADD_DEPENDENCIES("${acl_LibName}" ${acl_DependentTargets}) ENDIF(NOT "${acl_DependentTargets}" STREQUAL "") ENDIF(csc_EXECUTABLE) ENDMACRO(ADD_CSHARP_LIBRARY) MACRO(ADD_CSHARP_TEST testname) IF(mono_EXECUTABLE) ADD_TEST(${testname} ${mono_EXECUTABLE} ${ARGN}) ELSE(mono_EXECUTABLE) ADD_TEST(${testname} ${ARGN}) ENDIF(mono_EXECUTABLE) ENDMACRO(ADD_CSHARP_TEST) MACRO(ADD_EXPORTLAYER_LIBRARY ael_WrappedLibName ael_DependentLibs) IF("${ARGN}" STREQUAL "") MESSAGE(FATAL_ERROR "ADD_EXPORTLAYER_LIBRARY requires at least one optional argument.") ENDIF("${ARGN}" STREQUAL "") ADD_LIBRARY( "${ael_WrappedLibName}.Unmanaged" SHARED ${ARGN} ) TARGET_LINK_LIBRARIES("${ael_WrappedLibName}.Unmanaged" ${ael_DependentLibs}) ADD_DEPENDENCIES("${ael_WrappedLibName}.Unmanaged" "${ael_WrappedLibName}") ENDMACRO(ADD_EXPORTLAYER_LIBRARY) MACRO(WRAP_CLASSES_FOR_CSHARP wcfc_WrappedLibName wcfc_DependentTargets wcfc_DependentLibs) IF("${ARGN}" STREQUAL "") MESSAGE(FATAL_ERROR "WRAP_CLASSES_FOR_CSHARP requires at least one optional argument.") ENDIF("${ARGN}" STREQUAL "") SET(wcfc_SrcDir "${CMAKE_CURRENT_SOURCE_DIR}") SET(wcfc_BinDir "${CMAKE_CURRENT_BINARY_DIR}") CONFIGURE_FILE( "${wcfc_SrcDir}/MummySettings.xml.in" "${wcfc_BinDir}/xml/${wcfc_WrappedLibName}.MummySettings.xml" @ONLY ) CONFIGURE_FILE( "${wcfc_SrcDir}/WrappedObject.cs.in" "${wcfc_BinDir}/csharp/${wcfc_WrappedLibName}.WrappedObject.cs" @ONLY ) MAKE_DIRECTORY("${wcfc_BinDir}/export-layer") SET(wcfc_CsharpFiles "${wcfc_BinDir}/csharp/${wcfc_WrappedLibName}.WrappedObject.cs") SET(wcfc_ExportLayerFiles "") SET(wcfc_GccxmlIncludes "") FOREACH(instruction ${ARGN}) IF("${instruction}" MATCHES "(.+),(.+)") STRING(REGEX REPLACE "(.+),(.+)" "\\1" wcfc_Class "${instruction}") STRING(REGEX REPLACE "(.+),(.+)" "\\2" wcfc_Header "${instruction}") ELSE("${instruction}" MATCHES "(.+),(.+)") MESSAGE(FATAL_ERROR "WRAP_CLASSES_FOR_CSHARP arg instruction='${instruction}' does not match expected regular expression. Optional arguments to WRAP_CLASSES_FOR_CSHARP should follow the pattern 'class,header'...") ENDIF("${instruction}" MATCHES "(.+),(.+)") STRING(REGEX REPLACE "::" "_" wcfc_FileBaseName "${wcfc_Class}") IF("${wcfc_Class}" MATCHES "^.*::([^:]+)$") STRING(REGEX REPLACE "^.*::([^:]+)$" "\\1" wcfc_ClassName "${wcfc_Class}") ELSE("${wcfc_Class}" MATCHES "^.*::([^:]+)$") SET(wcfc_ClassName "${wcfc_Class}") ENDIF("${wcfc_Class}" MATCHES "^.*::([^:]+)$") SET(wcfc_GccxmlFile "${wcfc_BinDir}/xml/${wcfc_FileBaseName}.xml") SET(wcfc_CsharpFile "${wcfc_BinDir}/csharp/${wcfc_FileBaseName}.cs") SET(wcfc_ExportLayerFile "${wcfc_BinDir}/export-layer/${wcfc_FileBaseName}EL.cxx") CONFIGURE_FILE( "${wcfc_SrcDir}/gccxml.cxx.in" "${wcfc_BinDir}/xml/${wcfc_FileBaseName}_gccxml.cxx" @ONLY ) ADD_CUSTOM_COMMAND( OUTPUT ${wcfc_GccxmlFile} COMMAND ${gccxml_EXECUTABLE} ARGS -fxml=${wcfc_GccxmlFile} -fxml-start=_cable_ ${wcfc_GccxmlIncludes} -DCABLE_CONFIGURATION --gccxml-compiler ${CMAKE_CXX_COMPILER} ${wcfc_BinDir}/xml/${wcfc_FileBaseName}_gccxml.cxx DEPENDS ${wcfc_BinDir}/xml/${wcfc_FileBaseName}_gccxml.cxx ${wcfc_Header} ${gccxml_EXECUTABLE} ) ADD_CUSTOM_COMMAND( OUTPUT ${wcfc_CsharpFile} ${wcfc_ExportLayerFile} COMMAND ${mummy_EXECUTABLE} ARGS --settings-file ${wcfc_BinDir}/xml/${wcfc_WrappedLibName}.MummySettings.xml --gccxml-file ${wcfc_GccxmlFile} --csharp-file ${wcfc_CsharpFile} --export-layer-file ${wcfc_ExportLayerFile} DEPENDS ${wcfc_BinDir}/xml/${wcfc_WrappedLibName}.MummySettings.xml ${wcfc_GccxmlFile} ${mummy_EXECUTABLE} ) SET(wcfc_CsharpFiles ${wcfc_CsharpFiles} "${wcfc_CsharpFile}") SET(wcfc_ExportLayerFiles ${wcfc_ExportLayerFiles} "${wcfc_ExportLayerFile}") ENDFOREACH(instruction) ADD_CSHARP_LIBRARY(${wcfc_WrappedLibName} ${wcfc_DependentTargets} "" "" "" ${wcfc_CsharpFiles}) ADD_EXPORTLAYER_LIBRARY(${wcfc_WrappedLibName} ${wcfc_DependentLibs} "${wcfc_ExportLayerFiles}") ENDMACRO(WRAP_CLASSES_FOR_CSHARP) mummy-1.0.3/MummyCPack.cmake0000644000175000017500000000361012120621217015533 0ustar mathieumathieuSET(CPACK_PACKAGE_VERSION_MAJOR "${Mummy_VERSION_MAJOR}") SET(CPACK_PACKAGE_VERSION_MINOR "${Mummy_VERSION_MINOR}") SET(CPACK_PACKAGE_VERSION_PATCH "${Mummy_VERSION_PATCH}") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "mummy ${Mummy_VERSION_MAJOR}.${Mummy_VERSION_MINOR}.${Mummy_VERSION_PATCH}") SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${CPACK_PACKAGE_INSTALL_DIRECTORY} - the incredible C# wrapper generator") SET(CPACK_PACKAGE_VENDOR "Kitware") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/MummyLicense.txt") SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/MummyLicense.txt") SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mummy-${Mummy_VERSION_MAJOR}.${Mummy_VERSION_MINOR}.${Mummy_VERSION_PATCH}.${Mummy_VERSION_SVN_REVISION}") IF(NOT DEFINED CPACK_SYSTEM_NAME) SET(CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}) ENDIF(NOT DEFINED CPACK_SYSTEM_NAME) IF(${CPACK_SYSTEM_NAME} MATCHES Windows) IF(CMAKE_CL_64) SET(CPACK_SYSTEM_NAME win64-${CMAKE_SYSTEM_PROCESSOR}) ELSE(CMAKE_CL_64) SET(CPACK_SYSTEM_NAME win32-${CMAKE_SYSTEM_PROCESSOR}) ENDIF(CMAKE_CL_64) ENDIF(${CPACK_SYSTEM_NAME} MATCHES Windows) IF(NOT DEFINED CPACK_PACKAGE_FILE_NAME) SET(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}-${CPACK_SYSTEM_NAME}") ENDIF(NOT DEFINED CPACK_PACKAGE_FILE_NAME) IF(WIN32) # NSI does not handle unix paths properly. Use Windows style path separator: # SET(icon_file "${Mummy_SOURCE_DIR}/TODO-create-a-cool-icon.bmp") # STRING(REGEX REPLACE "/" "\\\\" icon_file "${icon_file}") # SET(CPACK_PACKAGE_ICON "${icon_file}") SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") SET(CPACK_NSIS_HELP_LINK "http://www.kitware.com") SET(CPACK_NSIS_URL_INFO_ABOUT "http://www.kitware.com") SET(CPACK_NSIS_CONTACT "kitware@kitware.com") SET(CPACK_GENERATOR "NSIS") SET(CPACK_SOURCE_GENERATOR "${CPACK_GENERATOR}") ENDIF(WIN32) INCLUDE(CPack) mummy-1.0.3/MummyConfig.cmake.in0000644000175000017500000000641712120621217016374 0ustar mathieumathieu# Set Mummy_DIR to the directory containing this file for FIND_PACKAGE(Mummy) # to work automatically... # GET_FILENAME_COMPONENT(Mummy_CONFIG_FILE "${CMAKE_CURRENT_LIST_FILE}" ABSOLUTE) GET_FILENAME_COMPONENT(Mummy_CONFIG_DIR "${Mummy_CONFIG_FILE}" PATH) GET_FILENAME_COMPONENT(Mummy_BASE_DIR "${Mummy_CONFIG_DIR}/../.." ABSOLUTE) # A mummy build-tree OR install-tree should look like this: # # ${Mummy_BASE_DIR} # --bin # ----*.dll # ----*.exe # ----*.lib # --include # ----mummy-@Mummy_VERSION_MAJOR@.@Mummy_VERSION_MINOR@.@Mummy_VERSION_PATCH@ # ------*.h # --share # ----mummy-@Mummy_VERSION_MAJOR@.@Mummy_VERSION_MINOR@.@Mummy_VERSION_PATCH@ # ------mummyConfig.cmake <--- this file is Mummy_CONFIG_FILE SET(Mummy_VERSION_MAJOR "@Mummy_VERSION_MAJOR@") SET(Mummy_VERSION_MINOR "@Mummy_VERSION_MINOR@") SET(Mummy_VERSION_PATCH "@Mummy_VERSION_PATCH@") SET(Mummy_VERSION_SVN_REVISION "@Mummy_VERSION_SVN_REVISION@") SET(Mummy_VERSION_STRING "@Mummy_VERSION_STRING@") SET(Mummy_32_BIT "@Mummy_32_BIT@") # If "mummy" does not exist in "bin" then find the first one that # does exist in a configuration type subdir of "bin." # Mummy_CMAKE_CONFIGURATION_TYPES is a list of possible configuration # types in "recommended" order. First existing one found wins. # SET(Mummy_CMAKE_BUILD_TYPE "@CMAKE_BUILD_TYPE@") SET(Mummy_CMAKE_CONFIGURATION_TYPES "@Mummy_CMAKE_CONFIGURATION_TYPES@") IF(NOT mummy_EXECUTABLE) SET(mummy_EXECUTABLE "${Mummy_BASE_DIR}/bin/mummy@CMAKE_EXECUTABLE_SUFFIX@") ENDIF() IF(NOT EXISTS "${mummy_EXECUTABLE}") FOREACH(Mummy_CONFIGURATION_TYPE ${Mummy_CMAKE_CONFIGURATION_TYPES}) IF(NOT EXISTS "${mummy_EXECUTABLE}") IF(EXISTS "${Mummy_BASE_DIR}/bin/${Mummy_CONFIGURATION_TYPE}/mummy@CMAKE_EXECUTABLE_SUFFIX@") SET(mummy_EXECUTABLE "${Mummy_BASE_DIR}/bin/${Mummy_CONFIGURATION_TYPE}/mummy@CMAKE_EXECUTABLE_SUFFIX@") ENDIF() ENDIF() ENDFOREACH() ENDIF() # Set these two variables based on the value of mummy_EXECUTABLE so that # the BIN_DIR and LIB_DIR vars match the selected mummy_EXECUTABLE. Since # mummy_EXECUTABLE is set as a cache variable, an end user may choose a # new mummy executable and then do another configure. Make sure mummy DIR # vars are empty for a mummy in "bin" and match the selected config for # a mummy in a config-based build tree... # SET(Mummy_CONFIG_DIR_SUFFIX "") SET(Mummy_SELECTED_CONFIGURATION "") IF("${mummy_EXECUTABLE}" MATCHES ".*/bin/([^/]+)/mummy.*") STRING(REGEX REPLACE ".*/bin/([^/]+)/mummy.*" "\\1" Mummy_SELECTED_CONFIGURATION "${mummy_EXECUTABLE}" ) ENDIF() IF(Mummy_SELECTED_CONFIGURATION) SET(Mummy_CONFIG_DIR_SUFFIX "/${Mummy_SELECTED_CONFIGURATION}") ENDIF() # Set all else based on Mummy_BASE_DIR and Mummy_CONFIG_DIR_SUFFIX: # SET(Mummy_BIN_DIR "${Mummy_BASE_DIR}/bin${Mummy_CONFIG_DIR_SUFFIX}" ) IF(Mummy_32_BIT) SET(Mummy_BIN_x64_DIR "${Mummy_BASE_DIR}/bin/x64${Mummy_CONFIG_DIR_SUFFIX}" ) ELSE() SET(Mummy_BIN_x64_DIR "${Mummy_BASE_DIR}/bin${Mummy_CONFIG_DIR_SUFFIX}" ) ENDIF() SET(Mummy_INCLUDE_DIRS "${Mummy_BASE_DIR}/include/mummy-${Mummy_VERSION_STRING}" ) SET(Mummy_RUNTIME_LINK_LIBRARIES "${Mummy_BIN_DIR}/@Mummy_RUNTIME_UNMANAGED_LINK_LIBRARY@" ) SET(mummy_EXECUTABLE "${mummy_EXECUTABLE}" CACHE FILEPATH "FILEPATH to mummy@CMAKE_EXECUTABLE_SUFFIX@") mummy-1.0.3/MummyCsharpExportLayerGenerator.cxx0000644000175000017500000007320612120621217021572 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyCsharpExportLayerGenerator.cxx 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2006-2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyCsharpExportLayerGenerator.h" #include "MummyCsharpGenerator.h" #include "MummyLog.h" #include "MummySettings.h" #include "cableClass.h" #include "cableClassType.h" #include "cableConstructor.h" #include "cableFunctionType.h" #include "cableMethod.h" #include "cablePointerType.h" #include "cableReferenceType.h" #include "cxxCvQualifiedType.h" #include "cxxFunctionType.h" #include "cxxPointerType.h" #include "cxxType.h" #include "gxsys/stl/set" #include "gxsys/SystemTools.hxx" //---------------------------------------------------------------------------- MummyCsharpExportLayerGenerator::MummyCsharpExportLayerGenerator() { this->CsharpGenerator = 0; } //---------------------------------------------------------------------------- MummyCsharpExportLayerGenerator::~MummyCsharpExportLayerGenerator() { } //---------------------------------------------------------------------------- bool MummyCsharpExportLayerGenerator::GenerateWrappers() { this->EmitClassForExportLayer(*GetStream(), GetTargetClass()); return false; } //---------------------------------------------------------------------------- MummyCsharpGenerator* MummyCsharpExportLayerGenerator::GetCsharpGenerator() { return this->CsharpGenerator; } //---------------------------------------------------------------------------- void MummyCsharpExportLayerGenerator::SetCsharpGenerator(MummyCsharpGenerator* generator) { this->CsharpGenerator = generator; } //---------------------------------------------------------------------------- //bool MummyCsharpExportLayerGenerator::FundamentalTypeIsWrappable(const cable::Type* t) //{ // return this->GetCsharpGenerator()->FundamentalTypeIsWrappable(t); //} //---------------------------------------------------------------------------- //bool MummyCsharpExportLayerGenerator::TypeIsWrappable(const cable::Type* t) //{ // return this->GetCsharpGenerator()->TypeIsWrappable(t); //} //---------------------------------------------------------------------------- //bool MummyCsharpExportLayerGenerator::FunctionTypeIsWrappable(const cable::FunctionType* ft) //{ // return this->GetCsharpGenerator()->FunctionTypeIsWrappable(ft); //} //---------------------------------------------------------------------------- //bool MummyCsharpExportLayerGenerator::MethodIsWrappable(const cable::Method* m, const cable::Context::Access& access) //{ // return this->GetCsharpGenerator()->MethodIsWrappable(m, access); //} //---------------------------------------------------------------------------- //bool MummyCsharpExportLayerGenerator::ClassIsWrappable(const cable::Class* c) //{ // return this->GetCsharpGenerator()->ClassIsWrappable(c); //} //---------------------------------------------------------------------------- const char *MummyCsharpExportLayerGenerator::GetArgName(cable::FunctionType *ftype, unsigned int i) { return this->GetCsharpGenerator()->GetArgName(ftype, i); } //---------------------------------------------------------------------------- gxsys_stl::string MummyCsharpExportLayerGenerator::GetExportLayerFunctionName(const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname) { return this->GetCsharpGenerator()->GetExportLayerFunctionName(c, m, mname); } //---------------------------------------------------------------------------- gxsys_stl::string GetExportLayerActualType(cable::Type *t, bool stripConst) { gxsys_stl::string s(t->GetCxxType().GetName()); if (stripConst) { s = t->GetCxxType().GetType()->GenerateName("", false, false); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string GetExportLayerMappedType(cable::Type *t, bool stripConst) { gxsys_stl::string s; if (HasMapToType(t)) { // 't' should be either a class or a reference to a class... // cable::Class* c = 0; if (cable::Type::ClassTypeId == t->GetTypeId()) { c = cable::ClassType::SafeDownCast(t)->GetClass(); } else if (cable::Type::ReferenceTypeId == t->GetTypeId()) { c = cable::ClassType::SafeDownCast( cable::ReferenceType::SafeDownCast(t)->GetTarget())->GetClass(); } if (c) { s = ExtractMapToType(c); } // Abstract "string" type translates to "const char*" in the export layer: // if (s == "string") { if (stripConst) { s = "char*"; } else { s = "const char*"; } } else { s = "ERROR_unknown_mapped_to_type_or_null_class_type_in_the_export_layer"; LogError(me_InternalError, << s.c_str()); } } else { s = GetExportLayerActualType(t, stripConst); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummyCsharpExportLayerGenerator::GetArgTypeAndNameString(cable::Type *argType, const char *name, bool stripConst) { gxsys_stl::string s; if ((argType->GetTypeId() == cable::Type::PointerTypeId) && (cable::PointerType::SafeDownCast(argType)->GetTarget()->GetTypeId() == cable::Type::FunctionTypeId) ) { if (EquivalentTypedefNameExists(this->GetTargetClass(), cable::FunctionType::SafeDownCast(cable::PointerType::SafeDownCast(argType)->GetTarget()), s)) { s = gxsys_stl::string(GetFullyQualifiedNameForCPlusPlus(this->GetTargetClass())) + "::" + s; } else { s = "ERROR - cannot generate argTypeAndName string for function pointer - add a typedef for the function pointer..."; LogError(me_InternalError, << s.c_str()); } } else { s = GetExportLayerMappedType(argType, stripConst); } if (name) { s += " "; s += name; } return s; } //---------------------------------------------------------------------------- void MummyCsharpExportLayerGenerator::EmitClassMethodDeclarationForExportLayer(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, bool emitExceptionParams) { gxsys_stl::string cname(GetFullyQualifiedNameForCPlusPlus(c)); gxsys_stl::string s; cable::FunctionType *ft = m->GetFunctionType(); unsigned int cArgs = ft->GetNumberOfArguments(); unsigned int cArgsEmitted = 0; unsigned int i = 0; cable::Type *retType = ft->GetReturns(); cable::Type *argType = 0; cable::Class* cByRefClass = 0; // Extern "C": Emit(os, "extern \"C\" "); // Export declspec: Emit(os, "MUMMY_DLL_EXPORT\n"); // Special case "new" and "delete" -- the rest are strictly according to the // method definition as given by 'm'... // if (mname == "new") { // Return type: Emit(os, cname.c_str()); Emit(os, "* "); // Exported function name: Emit(os, GetExportLayerFunctionName(c, m, mname).c_str()); Emit(os, "(unsigned int* mteStatus, unsigned int* mteIndex, unsigned int* rawRefCount"); cArgsEmitted += 3; if (emitExceptionParams) { Emit(os, ", unsigned int* mteExceptionIndex, void** clonedException"); cArgsEmitted += 2; } Emit(os, ")\n"); } else if (mname == "delete") { // Return type: Emit(os, "void"); Emit(os, " "); // Exported function name: Emit(os, GetExportLayerFunctionName(c, m, mname).c_str()); Emit(os, "("); Emit(os, cname.c_str()); Emit(os, "* pThis"); cArgsEmitted += 1; if (emitExceptionParams) { Emit(os, ", unsigned int* mteExceptionIndex, void** clonedException"); cArgsEmitted += 2; } Emit(os, ")\n"); } else { // Return type: Emit(os, GetArgTypeAndNameString(retType, 0, false).c_str()); Emit(os, " "); // Exported function name: Emit(os, GetExportLayerFunctionName(c, m, mname).c_str()); // Open args: Emit(os, "("); // The "this" arg: if (!m->GetStatic()) { Emit(os, cname.c_str()); Emit(os, "* pThis"); cArgsEmitted += 1; if (cArgs!=0) { Emit(os, ", "); } } // The real args: for (i= 0; iGetArgument(i); // Utility classes get marshalled as copies across the boundary from C# // even if in C++ they are & (byref) arguments... So they need to be // declared as just plain old stack-based by value arguments here. // cByRefClass = 0; if (cable::Type::ReferenceTypeId == argType->GetTypeId()) { cable::ClassType* classType = cable::ClassType::SafeDownCast( cable::ReferenceType::SafeDownCast(argType)->GetTarget()); if (classType) { cByRefClass = classType->GetClass(); } } if (cByRefClass && IsUtilityClass(cByRefClass)) { Emit(os, GetFullyQualifiedNameForCPlusPlus(cByRefClass).c_str()); Emit(os, " "); Emit(os, GetArgName(ft, i)); } else { Emit(os, GetArgTypeAndNameString(argType, GetArgName(ft, i), false).c_str()); } cArgsEmitted += 1; if (iGetSettings()->FindClassWrappingSettings(cname.c_str(), &cws)) { LogError(me_NoClassWrappingSettings, << "error: no ClassWrappingSettings for class " << cname.c_str()); } EmitIndent(os, indent); Emit(os, "if (0 != rv)\n"); EmitIndent(os, indent+1); Emit(os, "{\n"); gxsys_stl::string registerMethod = cws.registerMethod; gxsys_stl::string registerBaseClass = cws.registerBaseClass; gxsys_stl::string getRefCountMethod = cws.getRefCountMethod; gxsys_stl::string getMummyTypeEntryMethod = cws.getMummyTypeEntryMethod; gxsys_stl::string setMummyTypeEntryMethod = cws.setMummyTypeEntryMethod; if (!registerMethod.empty()) { EmitIndent(os, indent+1); Emit(os, registerBaseClass.c_str()); Emit(os, "* ro = ("); Emit(os, registerBaseClass.c_str()); Emit(os, "*) (void*) rv;\n"); } if (!registerMethod.empty() && !getMummyTypeEntryMethod.empty()) { // If object supports MummyTypeEntry caching: // EmitIndent(os, indent+1); Emit(os, "Kitware::mummy::TypeEntry* entry = ro->"); Emit(os, getMummyTypeEntryMethod.c_str()); Emit(os, "();\n"); EmitIndent(os, indent+1); Emit(os, "if (!entry)\n"); EmitIndent(os, indent+2); Emit(os, "{\n"); EmitIndent(os, indent+2); Emit(os, "entry = Kitware::mummy::Runtime::GetTypeEntry((void*) rv, typeid(*ro).name());\n"); EmitIndent(os, indent+2); Emit(os, "ro->"); Emit(os, setMummyTypeEntryMethod.c_str()); Emit(os, "(entry);\n"); EmitIndent(os, indent+2); Emit(os, "*mteStatus = 1;\n"); EmitIndent(os, indent+2); Emit(os, "}\n"); EmitIndent(os, indent+1); Emit(os, "else\n"); EmitIndent(os, indent+2); Emit(os, "{\n"); EmitIndent(os, indent+2); Emit(os, "*mteStatus = 2;\n"); EmitIndent(os, indent+2); Emit(os, "}\n"); } else { // ...otherwise always call Runtime::GetTypeEntry: // EmitIndent(os, indent+1); Emit(os, "Kitware::mummy::TypeEntry* entry = Kitware::mummy::Runtime::GetTypeEntry(\n"); EmitIndent(os, indent+2); Emit(os, "(void*) rv, typeid(*"); if (!registerMethod.empty()) { // Prefer "ro" (if we have it) to "rv" simply because // typeid(*obj).name() is really really stupid. // Emit(os, "ro"); } else { Emit(os, "rv"); } Emit(os, ").name());\n"); EmitIndent(os, indent+1); Emit(os, "*mteStatus = 0;\n"); } // So here we always have an entry: // EmitIndent(os, indent+1); Emit(os, "*mteIndex = entry->GetIndex();\n"); if (!registerMethod.empty() && !getRefCountMethod.empty()) { EmitIndent(os, indent+1); Emit(os, "*rawRefCount = (unsigned int) ro->"); Emit(os, getRefCountMethod.c_str()); Emit(os, ";\n"); } else { EmitIndent(os, indent+1); Emit(os, "*rawRefCount = (unsigned int) -86;\n"); } EmitIndent(os, indent+1); Emit(os, "}\n"); } //---------------------------------------------------------------------------- void MummyCsharpExportLayerGenerator::EmitClassMethodForExportLayer(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname) { gxsys_stl::string cname(GetFullyQualifiedNameForCPlusPlus(c)); cable::FunctionType *ft = m->GetFunctionType(); unsigned int cArgs = ft->GetNumberOfArguments(); unsigned int i = 0; unsigned int indent = 1; cable::Type *retType = ft->GetReturns(); cable::PointerType::Pointer fakeRetType; bool voidReturn = false; bool mappedReturnType = false; bool emitExceptionBlock = false; gxsys_stl::string rvTypeStr; bool needsInit = false; gxsys_stl::string initExpression; ClassWrappingSettings cws; if (!this->GetSettings()->FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { LogError(me_NoClassWrappingSettings, << "error: no ClassWrappingSettings for class " << GetFullyQualifiedNameForCPlusPlus(c).c_str()); } emitExceptionBlock = !cws.exceptionBaseClass.empty(); // If mname is "new" fake retType: // if (mname == "new") { fakeRetType = cable::PointerType::New(); fakeRetType->SetTarget(c->GetClassType()); fakeRetType->CreateCxxType(this->GetSourceRepresentation()->GetTypeSystem()); retType = fakeRetType; } // Is there a return value? Do we need to map/transform it to a different type? // if (IsVoid(retType)) { voidReturn = true; } else if (HasMapToType(retType)) { mappedReturnType = true; } // Declaration: EmitClassMethodDeclarationForExportLayer(os, c, m, mname, emitExceptionBlock); // Open body: Emit(os, "{\n"); // Declare return value "rv": if (!voidReturn) { if (cable::Type::ReferenceTypeId == retType->GetTypeId()) { rvTypeStr = gxsys_stl::string("ref<") + GetArgTypeAndNameString( cable::ReferenceType::SafeDownCast(retType)->GetTarget(), 0, false) + ">"; needsInit = false; } else if (mappedReturnType) { rvTypeStr = GetArgTypeAndNameString(retType, 0, true); needsInit = true; initExpression = "cast"; // david.cole::fix -- this works for the only mapped type we currently // support ("string" / "const char*") -- it needs to be generalized // to generate correct code if we ever introduce more mapped types... } else { rvTypeStr = GetArgTypeAndNameString(retType, 0, true); needsInit = true; initExpression = GetCPlusPlusZeroInitializerExpression(retType); } EmitIndent(os); Emit(os, rvTypeStr.c_str()); Emit(os, " rv"); if (needsInit) { if (initExpression == "memset") { Emit(os, ";\n"); EmitIndent(os); Emit(os, "memset(&rv, 0, sizeof(rv))"); } else if (initExpression == "cast") { Emit(os, " = ("); Emit(os, rvTypeStr.c_str()); Emit(os, ") 0"); } else { Emit(os, " = "); Emit(os, initExpression.c_str()); } } Emit(os, ";"); Emit(os, "\n"); Emit(os, "\n"); } // Open exception try block: if (emitExceptionBlock) { EmitIndent(os); Emit(os, "try\n"); EmitIndent(os); Emit(os, "{\n"); indent++; } // Delegate the call to the real underlying object: EmitIndent(os, indent); if (!voidReturn) { if (mappedReturnType) { Emit(os, GetExportLayerActualType(retType, true).c_str()); Emit(os, " rvmi = "); } else { Emit(os, "rv = "); } } // Special case "new" and "delete" -- the rest are strictly according to the // method definition as given by 'm'... // if (mname == "new") { Emit(os, "new "); Emit(os, cname.c_str()); Emit(os, ";"); Emit(os, "\n"); } else if (mname == "delete") { Emit(os, "delete pThis;"); Emit(os, "\n"); } else { if (!m->GetStatic()) { Emit(os, "pThis->"); } else { Emit(os, cname.c_str()); Emit(os, "::"); } Emit(os, mname.c_str()); Emit(os, "("); for (i= 0; iGetFile(), m->GetLine(), me_UnknownMapToType, << "Unknown iwhMapToType for return type of method '" << m->GetName() << "'"); } } else if (IsObjectPointer(retType)) { const cable::Class* cRetType = cable::ClassType::SafeDownCast( cable::PointerType::SafeDownCast(retType)->GetTarget() )->GetClass(); this->EmitSpecialHandlingForObjectPointerReturns(os, GetFullyQualifiedNameForCPlusPlus(cRetType), m, mname, indent); } // Close exception try block: if (emitExceptionBlock) { EmitIndent(os); Emit(os, "}\n"); EmitIndent(os); Emit(os, "catch("); Emit(os, cws.exceptionBaseClass.c_str()); Emit(os, "& mel_exc)\n"); EmitIndent(os); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, cws.exceptionBaseClass.c_str()); Emit(os, "* mel_exc_clone = mel_exc."); Emit(os, cws.exceptionCloneMethod.c_str()); Emit(os, "();\n"); EmitIndent(os, 2); Emit(os, "Kitware::mummy::TypeEntry* entry = Kitware::mummy::Runtime::GetTypeEntry(\n"); EmitIndent(os, 3); Emit(os, "(void*) mel_exc_clone, typeid(*mel_exc_clone).name());\n"); EmitIndent(os, 2); Emit(os, "*clonedException = mel_exc_clone;\n"); EmitIndent(os, 2); Emit(os, "*mteExceptionIndex = entry->GetIndex();\n"); EmitIndent(os); Emit(os, "}\n"); } // Return statement: if (!voidReturn) { Emit(os, "\n"); EmitIndent(os); Emit(os, "return rv;\n"); } // Close body: Emit(os, "}\n"); } //---------------------------------------------------------------------------- void MummyCsharpExportLayerGenerator::EmitClassForExportLayer(gxsys_ios::ostream &os, const cable::Class *c) { gxsys_stl::string header(c->GetFile()); ClassWrappingSettings cws; if (!this->GetSettings()->FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { LogError(me_NoClassWrappingSettings, << "error: no ClassWrappingSettings for class " << GetFullyQualifiedNameForCPlusPlus(c).c_str()); } // Emit code: // EmitMummyVersionComments(os, "//"); // If the class maps directly to a builtin type, then DO NOT emit any code. // gxsys_stl::string mapToType = ExtractMapToType(c); if (mapToType != "") { Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "// Unmanaged class '"); Emit(os, GetFullyQualifiedNameForCPlusPlus(c).c_str()); Emit(os, "' maps directly to type '"); Emit(os, mapToType.c_str()); Emit(os, "'.\n"); Emit(os, "// No code generated for '"); Emit(os, GetFullyQualifiedNameForCPlusPlus(c).c_str()); Emit(os, "'...\n"); LogVerboseInfo(<< "Skipping code generation because class maps directly to native type."); return; } Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "// You can use this symbol in your header files if there are bits of your\n"); Emit(os, "// code that should be conditionally compiled in this export layer.\n"); Emit(os, "//\n"); Emit(os, "#define MUMMY_EXPORT_LAYER_CXX\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "// Do not emit the silly C4996 warning for strncpy use:\n"); Emit(os, "//\n"); Emit(os, "#ifndef _CRT_SECURE_NO_DEPRECATE\n"); Emit(os, "#define _CRT_SECURE_NO_DEPRECATE\n"); Emit(os, "#endif\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "// Forward declare functions that generated code might call...\n"); Emit(os, "//\n"); Emit(os, "#ifdef _WIN64\n"); Emit(os, "extern \"C\" __declspec(dllimport) void* __stdcall CoTaskMemAlloc(unsigned __int64 cb);\n"); Emit(os, "#define MUMMY_STRING_ALLOC ::CoTaskMemAlloc\n"); Emit(os, "#else\n"); Emit(os, "#ifdef _WIN32\n"); Emit(os, "extern \"C\" __declspec(dllimport) void* __stdcall CoTaskMemAlloc(unsigned long cb);\n"); Emit(os, "#define MUMMY_STRING_ALLOC ::CoTaskMemAlloc\n"); Emit(os, "#endif\n"); Emit(os, "#endif\n"); Emit(os, "\n"); Emit(os, "#ifndef MUMMY_STRING_ALLOC\n"); Emit(os, "#define MUMMY_STRING_ALLOC malloc\n"); Emit(os, "#endif\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "// Macro for exporting functions implemented in this file...\n"); Emit(os, "//\n"); Emit(os, "#ifdef _WIN32\n"); Emit(os, "#define MUMMY_DLL_EXPORT __declspec(dllexport)\n"); Emit(os, "#else\n"); Emit(os, "#define MUMMY_DLL_EXPORT\n"); Emit(os, "#endif\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "#include \""); Emit(os, header.c_str()); Emit(os, "\"\n"); Emit(os, "\n"); if (IsUtilityClass(c)) { // No export layer necessary... } else { // Gather wrapped elements: // gxsys_stl::vector wrapped_methods; cable::Method *factoryM = 0; cable::Method *disposalM = 0; cable::Method *registerM = 0; cable::Method *unRegisterM = 0; this->GetCsharpGenerator()->GatherWrappedMethods(c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM, false); const cable::Constructor* ctor = FindNonAbstractPublicDefaultConstructor(c); bool hasMethodsThatReturnRefs = false; for(gxsys_stl::vector::iterator mit = wrapped_methods.begin(); !hasMethodsThatReturnRefs && mit != wrapped_methods.end(); ++mit) { cable::FunctionType *ft = (*mit)->GetFunctionType(); cable::Type *retType = ft->GetReturns(); if (cable::Type::ReferenceTypeId == retType->GetTypeId()) { hasMethodsThatReturnRefs = true; } } if (hasMethodsThatReturnRefs) { Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "// Thanks to Brad King for the magic of the ref converter helper class:\n"); Emit(os, "template \n"); Emit(os, "class ref\n"); Emit(os, "{\n"); Emit(os, "public:\n"); EmitIndent(os); Emit(os, "ref() throw(): p_(0) {}\n"); EmitIndent(os); Emit(os, "ref& operator=(T& r) throw() { this->p_ = &r; return *this; }\n"); EmitIndent(os); Emit(os, "operator T&() throw() { return *this->p_; }\n"); Emit(os, "\n"); Emit(os, "private:\n"); EmitIndent(os); Emit(os, "T* p_;\n"); Emit(os, "};\n"); } // Emit include statements for any ref counted base classes involved in method return // values. Collect them into a set and then emit the set; has the nice effect of // eliminating duplicates and emitting the include statements in sorted order... // gxsys_stl::set includeStatements; gxsys_stl::string registerInclude; if (ctor) { registerInclude = this->GetSettings()->GetRegisterInclude(c); if (!registerInclude.empty()) { includeStatements.insert(registerInclude); } } for(gxsys_stl::vector::iterator mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { cable::FunctionType *ft = (*mit)->GetFunctionType(); cable::Type *retType = ft->GetReturns(); if (!HasMapToType(retType) && IsObjectPointer(retType)) { const cable::Class* cRetType = cable::ClassType::SafeDownCast( cable::PointerType::SafeDownCast(retType)->GetTarget() )->GetClass(); registerInclude = this->GetSettings()->GetRegisterInclude(cRetType); if (!registerInclude.empty()) { includeStatements.insert(registerInclude); } } } includeStatements.insert("#include \"MummyRuntime.h\""); includeStatements.insert("#include \"string.h\" // for possible memset use"); if (!cws.exceptionInclude.empty()) { includeStatements.insert(cws.exceptionInclude); } if (!includeStatements.empty()) { Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); for(gxsys_stl::set::iterator sit = includeStatements.begin(); sit != includeStatements.end(); ++sit) { Emit(os, sit->c_str()); Emit(os, "\n"); } } // Special methods first, then iterate the remainder in wrapped_methods: // if (factoryM) { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); EmitClassMethodForExportLayer(os, c, factoryM, factoryM->GetName()); } if (disposalM) { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); EmitClassMethodForExportLayer(os, c, disposalM, disposalM->GetName()); } if (registerM) { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); EmitClassMethodForExportLayer(os, c, registerM, registerM->GetName()); } if (unRegisterM) { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); EmitClassMethodForExportLayer(os, c, unRegisterM, unRegisterM->GetName()); } // If there's a public default constructor for concrete class 'c', emit "_new" // and "_delete" export layer functions: // if (ctor) { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); EmitClassMethodForExportLayer(os, c, ctor, "new"); Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); EmitClassMethodForExportLayer(os, c, ctor, "delete"); } for(gxsys_stl::vector::iterator mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); EmitClassMethodForExportLayer(os, c, *mit, (*mit)->GetName()); } } // If there is extraExportLayerCode, emit it at the bottom of the file. // If it's there, it's the name of a file that we are to include in // its entirety... // gxsys_stl::string extraCode = this->GetSettings()->GetExtraExportLayerCode(c); if (extraCode != "") { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "// Begin extraExportLayerCode\n"); Emit(os, "\n"); EmitFile(os, extraCode.c_str()); Emit(os, "\n"); Emit(os, "// End extraExportLayerCode\n"); } } mummy-1.0.3/MummyCsharpExportLayerGenerator.h0000644000175000017500000000444212120621217021213 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyCsharpExportLayerGenerator.h // // Author(s) : David Cole // // Copyright (C) 2006-2007 Kitware, Inc. //---------------------------------------------------------------------------- #include "MummyGenerator.h" // parent class #include "gxsys/stl/string" class MummyCsharpGenerator; class MummyCsharpExportLayerGenerator : public MummyGenerator { public: MummyCsharpExportLayerGenerator(); virtual ~MummyCsharpExportLayerGenerator(); virtual bool GenerateWrappers(); virtual MummyCsharpGenerator* GetCsharpGenerator(); virtual void SetCsharpGenerator(MummyCsharpGenerator* generator); //virtual bool FundamentalTypeIsWrappable(const cable::Type* t); //virtual bool TypeIsWrappable(const cable::Type* t); //virtual bool FunctionTypeIsWrappable(const cable::FunctionType* ft); //virtual bool MethodIsWrappable(const cable::Method* m, const cable::Context::Access& access); //virtual bool ClassIsWrappable(const cable::Class* c); virtual const char *GetArgName(cable::FunctionType *ftype, unsigned int i); virtual gxsys_stl::string GetArgTypeAndNameString(cable::Type *argType, const char *name, bool stripConst); //virtual gxsys_stl::string GetArgTypeAndNameString(cable::FunctionType *ft, const unsigned int i); virtual gxsys_stl::string GetExportLayerFunctionName(const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname); virtual void EmitSpecialHandlingForObjectPointerReturns(gxsys_ios::ostream &os, const gxsys_stl::string& cname, const cable::Method *m, const gxsys_stl::string& mname, const unsigned int indent); virtual void EmitClassMethodDeclarationForExportLayer(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, bool emitExceptionParams); virtual void EmitClassMethodForExportLayer(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname); virtual void EmitClassForExportLayer(gxsys_ios::ostream &os, const cable::Class *c); private: MummyCsharpGenerator* CsharpGenerator; MummyCsharpExportLayerGenerator(const MummyCsharpExportLayerGenerator&); //Not implemented MummyCsharpExportLayerGenerator& operator=(const MummyCsharpExportLayerGenerator&); //Not implemented }; mummy-1.0.3/MummyCsharpGenerator.cxx0000644000175000017500000041411412120621217017370 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyCsharpGenerator.cxx 517 2010-11-11 15:00:41Z david.cole $ // // $Author: david.cole $ // $Date: 2010-11-11 10:00:41 -0500 (Thu, 11 Nov 2010) $ // $Revision: 517 $ // // Copyright (C) 2006-2009 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyCsharpGenerator.h" #include "MummyLineOrientedTextFileReader.h" #include "MummyLog.h" #include "MummySettings.h" #include "cableArrayType.h" #include "cableClass.h" #include "cableClassType.h" #include "cableConstructor.h" #include "cableEnumeration.h" #include "cableEnumerationType.h" #include "cableField.h" #include "cableFunctionType.h" #include "cableFundamentalType.h" #include "cableMethod.h" #include "cablePointerType.h" #include "cableReferenceType.h" #include "cableType.h" #include "cableTypedef.h" #include "cxxFundamentalType.h" #include "gxsys/RegularExpression.hxx" #include "gxsys/SystemTools.hxx" #include "gxsys/ios/sstream" #include "gxsys/stl/algorithm" #include "gxsys/stl/map" #include "gxsys/stl/set" #include "gxsys/stl/string" #include "gxsys/stl/vector" #include "string.h" // strstr //---------------------------------------------------------------------------- MummyCsharpGenerator::MummyCsharpGenerator() { this->CurrentMethodId = 0; this->ClassLineNumber = 0; //this->MethodIdMap; // empty, as constructed //this->TargetInterface; // empty, as constructed //this->HintsMap; // empty, as constructed } //---------------------------------------------------------------------------- MummyCsharpGenerator::~MummyCsharpGenerator() { } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::GenerateWrappers() { gxsys_stl::string elDllVariableName(this->GetSettings()->GetGroup()); elDllVariableName += "EL_dll"; this->EmitCSharpWrapperClass(*GetStream(), elDllVariableName.c_str(), GetTargetClass()); if (this->GetSettings()->GetVerbose()) { gxsys_stl::map::iterator it; for (it = this->HintsMap.begin(); it != this->HintsMap.end(); ++it) { LogInfo(mi_VerboseInfo, << it->first << ": '" << it->second << "'"); } } return true; } //---------------------------------------------------------------------------- void MummyCsharpGenerator::SetTargetClass(const cable::Class *c) { this->MummyGenerator::SetTargetClass(c); // Ensure HeaderFileReader is always called first with the target class. // (Presently, there is only one cached HeaderFileReader and it only reads // the file when it is first called... Subsequent calls ignore the input // data and simply return the cached HeaderFileReader. Multiple readers // may eventually be necessary to support BTX/ETX exclusion fully...) // this->GetHeaderFileReader(c); // Only populate the lookup entries with stuff from the *parent* class // (and its parents...) That way, we can use the existence of a signature // in the table as evidence that a virtual is being overridden (for C# // keyword override purposes) or that a static is being redefined at a // more derived level (hence hiding the parent's definition and requiring // use of the C# keyword "new" to avoid the warning about hiding...) // ClearLookupEntries(); AddLookupEntries(GetWrappableParentClass(c)); // Cache a map of the externalHints file: // this->CacheExternalHints(this->GetSettings()->GetExternalHints(c)); } //---------------------------------------------------------------------------- void MummyCsharpGenerator::CacheExternalHints(const gxsys_stl::string& hintsfile) { gxsys_stl::vector hints; gxsys_stl::string line; gxsys::RegularExpression re; re.compile("([^\t ]+)[\t ]+([^\t ]+)[\t ]+([^\t ]+)[\t ]+([^\t ]+)"); MummyLineOrientedTextFileReader reader; reader.SetFileName(hintsfile.c_str()); this->HintsMap.clear(); unsigned int n = reader.GetNumberOfLines(); unsigned int i = 0; for (i= 1; i<=n; ++i) { line = reader.GetLine(i); if (!line.empty()) { if (re.find(line)) { gxsys_stl::string className = re.match(1); gxsys_stl::string methodName = re.match(2); gxsys_stl::string type = re.match(3); gxsys_stl::string count = re.match(4); gxsys_stl::string key(className + "::" + methodName); if (this->HintsMap.find(key) == this->HintsMap.end()) { this->HintsMap[key] = line; } else { LogFileLineWarningMsg(hintsfile, i, mw_MultipleHints, "More than one line in the hints file for " << className << "::" << methodName); } } } } } //---------------------------------------------------------------------------- void MummyCsharpGenerator::AddTargetInterface(const gxsys_stl::string& iface) { if (this->TargetInterface != "") { LogWarning(mw_MultipleTargetInterfaces, "AddTargetInterface being called more than once. " << "Implementation currently only supports 1 interface. " << "Clobbering existing target interface: " << this->TargetInterface); } this->TargetInterface = iface; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::HasTargetInterface(const char *iface) const { if (iface) { return this->TargetInterface == iface; } return false; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::IsKeyword(const char *p) { static gxsys_stl::set keywords; if (0 == keywords.size()) { keywords.insert("abstract"); keywords.insert("as"); keywords.insert("base"); keywords.insert("bool"); keywords.insert("break"); keywords.insert("byte"); keywords.insert("case"); keywords.insert("catch"); keywords.insert("char"); keywords.insert("checked"); keywords.insert("class"); keywords.insert("const"); keywords.insert("continue"); keywords.insert("decimal"); keywords.insert("default"); keywords.insert("delegate"); keywords.insert("do"); keywords.insert("double"); keywords.insert("else"); keywords.insert("enum"); keywords.insert("event"); keywords.insert("explicit"); keywords.insert("extern"); keywords.insert("false"); keywords.insert("finally"); keywords.insert("fixed"); keywords.insert("float"); keywords.insert("for"); keywords.insert("foreach"); keywords.insert("goto"); keywords.insert("if"); keywords.insert("implicit"); keywords.insert("in"); keywords.insert("int"); keywords.insert("interface"); keywords.insert("internal"); keywords.insert("is"); keywords.insert("lock"); keywords.insert("long"); keywords.insert("namespace"); keywords.insert("new"); keywords.insert("null"); keywords.insert("object"); keywords.insert("operator"); keywords.insert("out"); keywords.insert("override"); keywords.insert("params"); keywords.insert("private"); keywords.insert("protected"); keywords.insert("public"); keywords.insert("readonly"); keywords.insert("ref"); keywords.insert("return"); keywords.insert("sbyte"); keywords.insert("sealed"); keywords.insert("short"); keywords.insert("sizeof"); keywords.insert("stackalloc"); keywords.insert("static"); keywords.insert("string"); keywords.insert("struct"); keywords.insert("switch"); keywords.insert("this"); keywords.insert("throw"); keywords.insert("true"); keywords.insert("try"); keywords.insert("typeof"); keywords.insert("uint"); keywords.insert("ulong"); keywords.insert("unchecked"); keywords.insert("unsafe"); keywords.insert("ushort"); keywords.insert("using"); keywords.insert("virtual"); keywords.insert("void"); keywords.insert("volatile"); keywords.insert("while"); } gxsys_stl::set::iterator it = keywords.find(gxsys_stl::string(p)); if (it != keywords.end()) { return true; } return false; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::IsReservedMethodName(const gxsys_stl::string &name) { return ( name == "Equals" || name == "Finalize" || name == "GetHashCode" || name == "GetType" || name == "MemberwiseClone" || name == "Object" || name == "ToString"); } //---------------------------------------------------------------------------- gxsys_stl::string MummyCsharpGenerator::GetFundamentalTypeString(const cable::Type *t) { gxsys_stl::string s; if (cable::Type::FundamentalTypeId == t->GetTypeId()) { switch (cxx::FundamentalType::SafeDownCast(t->GetCxxType().GetType())->GetId()) { case cxx::FundamentalType::UnsignedChar: s = "byte"; break; case cxx::FundamentalType::UnsignedShortInt: s = "ushort"; break; case cxx::FundamentalType::UnsignedInt: case cxx::FundamentalType::UnsignedLongInt: s = "uint"; break; case cxx::FundamentalType::SignedChar: case cxx::FundamentalType::Char: s = "sbyte"; break; case cxx::FundamentalType::ShortInt: s = "short"; break; case cxx::FundamentalType::Int: case cxx::FundamentalType::LongInt: s = "int"; break; case cxx::FundamentalType::Bool: s = "bool"; break; case cxx::FundamentalType::Float: s = "float"; break; case cxx::FundamentalType::Double: s = "double"; break; case cxx::FundamentalType::Void: s = "void"; break; case cxx::FundamentalType::UnsignedLongLongInt: s = "ulong"; break; case cxx::FundamentalType::LongLongInt: s = "long"; break; //case cxx::FundamentalType::WChar_t: //case cxx::FundamentalType::LongDouble: //case cxx::FundamentalType::ComplexFloat: //case cxx::FundamentalType::ComplexDouble: //case cxx::FundamentalType::ComplexLongDouble: //case cxx::FundamentalType::NumberOfTypes: default: break; } } if (s == "") { LogError(me_UnknownFundamentalType, << "Unhandled variable type. GetFundamentalTypeString returning the empty string..."); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummyCsharpGenerator::GetWrappedMethodName(const cable::Method *m) { gxsys_stl::string name(m->GetName()); if (IsReservedMethodName(name)) { name = name + "Wrapper"; LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_ReservedMethodName, << "Reserved method name '" << m->GetName() << "' used. Rename it to eliminate this warning..."); } return name; } //---------------------------------------------------------------------------- gxsys_stl::string GetWrappedEnumName(const cable::Enumeration *e) { gxsys_stl::string ename(e->GetName()); // Don't name unnamed enums with invalid C#/C++ identifiers like "$"... // if (ename == "" || strstr(ename.c_str(), "$")) { if (e->Begin() != e->End()) { ename = *(e->Begin()); ename += "_WrapperEnum"; } else { ename = "WARNING_unnamed_enum"; } LogFileLineWarningMsg(e->GetFile(), e->GetLine(), mw_UnnamedEnum, "Unnamed enum found. Name it to eliminate this warning..."); } return ename; } //---------------------------------------------------------------------------- bool ExtractTypeAndCountFromHintLine( const gxsys_stl::string& hint, gxsys_stl::string& type, gxsys_stl::string& count ) { gxsys::RegularExpression re; re.compile("([^\t ]+)[\t ]+([^\t ]+)[\t ]+([^\t ]+)[\t ]+([^\t ]+)"); if (re.find(hint)) { //className = re.match(1); //methodName = re.match(2); type = re.match(3); count = re.match(4); return true; } return false; } //---------------------------------------------------------------------------- bool ReturnTypeMatchesHintType( cable::Type *t, const gxsys_stl::string& type ) { gxsys_stl::string utype = gxsys::SystemTools::UpperCase(type); // Init with the "not a real enum value" value: // cxx::FundamentalType::Id ftid = cxx::FundamentalType::NumberOfTypes; // Values of 'type' currently present in the VTK hints file are: // if (utype == "301") { ftid = cxx::FundamentalType::Float; } else if (utype == "304") { ftid = cxx::FundamentalType::Int; } else if (utype == "307") { ftid = cxx::FundamentalType::Double; } else if (utype == "30A") { ftid = cxx::FundamentalType::Int; } // vtkIdType (could be 32 or 64 bit...) else if (utype == "2307") { ftid = cxx::FundamentalType::Double; } // 0x2307 == double* + something? if (cxx::FundamentalType::NumberOfTypes == ftid) { LogWarning(mw_UnknownHintDataType, "Unknown externalHints data type string '" << type << "'"); } else if (IsFundamentalPointer(t, ftid)) { return true; } return false; } //---------------------------------------------------------------------------- bool ExtractCountFromMethodDeclarationLine( const gxsys_stl::string& line, gxsys_stl::string& count ) { // Grudgingly allow this VTK-ism to creep into the mummy codebase to avoid // introducing a list of regular expressions in the MummySettings.xml file // just for VTK-wrapping-hint-based array size specification... // // In VTK, in addition to the explicit external hints file VTK/Wrapping/hints, // the following macros from VTK/Common/vtkSetGet.h are also recognized as // implicitly having hint sizes associated with them: // gxsys::RegularExpression re; re.compile("^[\t ]*vtkGetVector([0-9]+)Macro\\(.*,.*\\)"); if (re.find(line)) { count = re.match(1); return true; } re.compile("^[\t ]*vtkGetVectorMacro\\(.*,.*,.*([0-9]+).*\\)"); if (re.find(line)) { count = re.match(1); return true; } re.compile("^[\t ]*vtkViewportCoordinateMacro\\(.*\\)"); if (re.find(line)) { count = "2"; return true; } re.compile("^[\t ]*vtkWorldCoordinateMacro\\(.*\\)"); if (re.find(line)) { count = "3"; return true; } return false; } //---------------------------------------------------------------------------- // Callers of GetMethodArgumentArraySize pass this value as "i" to query // about the return value of the method. Otherwise, "i" is presumed to be an // index (0 to cArgs-1) of one of the method's arguments. #define RETURN_VALUE (0x84848484) //---------------------------------------------------------------------------- gxsys_stl::string MummyCsharpGenerator::GetMethodArgumentArraySize(const cable::Class *c, const cable::Method *m, const cable::FunctionType *ft, unsigned int i) { gxsys_stl::string argArraySize; cable::Type *retType = 0; // First check for an attribute directly in the source code: // gxsys_stl::string atts; if (RETURN_VALUE == i) { atts = m->GetAttributes(); } else { atts = ft->GetArgumentAttributes(i); } if (atts != "") { argArraySize = ExtractArraySize(atts); } // If no direct hint, check the externalHints file, if any: // if ((argArraySize == "") && (this->HintsMap.size() > 0)) { // The VTK/Wrapping/hints file only tells us about the size of the pointer // returned by the method. Only return a non-empty array size from a // VTK/Wrapping/hints-style file if this is for a return value of a method: // if (RETURN_VALUE == i) { retType = ft->GetReturns(); if (!IsVoid(retType)) { gxsys_stl::string methodName(m->GetName()); gxsys_stl::map::iterator it; const cable::Class *cIt = c; while (cIt != NULL && (argArraySize == "")) { gxsys_stl::string fullClassName(GetFullyQualifiedNameForCPlusPlus(cIt)); gxsys_stl::string key(fullClassName + "::" + methodName); gxsys_stl::string hintline; it = this->HintsMap.find(key); if (it != this->HintsMap.end()) { hintline = it->second; gxsys_stl::string type; gxsys_stl::string count; if (ExtractTypeAndCountFromHintLine(hintline, type, count) && ReturnTypeMatchesHintType(retType, type)) { argArraySize = count; LogVerboseInfo("using external array size hint: " << argArraySize << " " << key); } } // If not found yet, keep looking up at parent class hints to see // if it is inherited. Method name and return type should still match // even if the hint is at the parent class level. // if (argArraySize == "") { cIt = GetParentClass(cIt); } } } } } // If still no hint, see if the line declaring the method in the header // file uses a macro that gives us a hint about the size of the array... // if (argArraySize == "") { if (RETURN_VALUE == i) { retType = ft->GetReturns(); if (!IsVoid(retType) && !IsObjectPointer(retType)) { gxsys_stl::string line(this->GetHeaderFileReader(c)->GetLine(m->GetLine())); gxsys_stl::string count; if (ExtractCountFromMethodDeclarationLine(line, count)) { argArraySize = count; if (this->GetSettings()->GetVerbose()) { LogFileLineInfoMsg(c->GetFile(), m->GetLine(), mi_VerboseInfo, "inferred array size hint '" << count << "' from method declaration '" << line << "'"); } } } } } return argArraySize; } //---------------------------------------------------------------------------- // // GetMethodSignature is very similar to EmitCSharpMethodDeclaration. // Changes in either may need to be made in both places... // gxsys_stl::string MummyCsharpGenerator::GetMethodSignature(const cable::Class *c, const cable::Method *m) { gxsys_ios::ostringstream os; cable::FunctionType *ft = m->GetFunctionType(); unsigned int cArgs = ft->GetNumberOfArguments(); unsigned int i = 0; cable::Type *argType = 0; // Method name: Emit(os, GetWrappedMethodName(m).c_str()); // Open args: Emit(os, "("); // The C# arg types: for (i= 0; iGetArgument(i); // Is arg an array? // gxsys_stl::string argArraySize(GetMethodArgumentArraySize(c, m, ft, i)); // arg type: Emit(os, GetCSharpTypeString(argType, false, argArraySize != "").c_str()); // array notation: if (argArraySize != "") { Emit(os, "[]"); } if (iGetArgumentName(i); if (p && *p && !IsKeyword(p)) { return p; } // Hacky, but for now: static char buf[32]; sprintf(buf, "arg%u", i); return buf; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::FundamentalTypeIsWrappable(const cable::Type* t) { if (cable::Type::FundamentalTypeId == t->GetTypeId()) { switch (cxx::FundamentalType::SafeDownCast(t->GetCxxType().GetType())->GetId()) { case cxx::FundamentalType::UnsignedChar: case cxx::FundamentalType::UnsignedShortInt: case cxx::FundamentalType::UnsignedInt: case cxx::FundamentalType::UnsignedLongInt: case cxx::FundamentalType::SignedChar: case cxx::FundamentalType::Char: case cxx::FundamentalType::ShortInt: case cxx::FundamentalType::Int: case cxx::FundamentalType::LongInt: case cxx::FundamentalType::Bool: case cxx::FundamentalType::Float: case cxx::FundamentalType::Double: case cxx::FundamentalType::Void: case cxx::FundamentalType::UnsignedLongLongInt: case cxx::FundamentalType::LongLongInt: return true; break; case cxx::FundamentalType::WChar_t: case cxx::FundamentalType::LongDouble: case cxx::FundamentalType::ComplexFloat: case cxx::FundamentalType::ComplexDouble: case cxx::FundamentalType::ComplexLongDouble: case cxx::FundamentalType::NumberOfTypes: default: break; } } return false; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::TypeIsWrappable(const cable::Type* t) { bool wrappable = false; switch (t->GetTypeId()) { case cable::Type::EnumerationTypeId: wrappable = true; break; case cable::Type::FundamentalTypeId: wrappable = FundamentalTypeIsWrappable(t); break; case cable::Type::ArrayTypeId: wrappable = false;//TypeIsWrappable(cable::ArrayType::SafeDownCast(t)->GetTarget()); break; case cable::Type::ClassTypeId: wrappable = ClassIsWrappable(cable::ClassType::SafeDownCast(t)->GetClass()); break; case cable::Type::PointerTypeId: { cable::Type *nested_type = cable::PointerType::SafeDownCast(t)->GetTarget(); cable::Type::TypeIdType nested_type_id = nested_type->GetTypeId(); // Only pointers to enums, fundamentals and objects are wrappable // and then only if the nested type is also wrappable... // // A function pointer is "nearly" wrappable (as a delegate definition) // if its return type and all of its argument types are wrappable. // And it has a typedef that names it within this class (because // that typedef is the thing that generates the delegate def in // the C# class...) // // (This is what prevents pointers to pointers from being wrapped // in the general case...) // if (cable::Type::EnumerationTypeId == nested_type_id || cable::Type::FundamentalTypeId == nested_type_id || cable::Type::ClassTypeId == nested_type_id) { wrappable = TypeIsWrappable(nested_type); } else if (cable::Type::FunctionTypeId == nested_type_id) { gxsys_stl::string s; // Only really wrappable if nested_type is wrappable and an // equivalent typedef name exists: // wrappable = TypeIsWrappable(nested_type) && EquivalentTypedefNameExists(this->GetTargetClass(), cable::FunctionType::SafeDownCast(nested_type), s); } else { wrappable = false; // as initialized... } } break; case cable::Type::ReferenceTypeId: { cable::Type *nested_type = cable::ReferenceType::SafeDownCast(t)->GetTarget(); cable::Type::TypeIdType nested_type_id = nested_type->GetTypeId(); wrappable = false; // as initialized... if (cable::Type::EnumerationTypeId == nested_type_id || cable::Type::FundamentalTypeId == nested_type_id || cable::Type::ClassTypeId == nested_type_id) { wrappable = TypeIsWrappable(nested_type); } else if (cable::Type::PointerTypeId == nested_type_id) { // References to pointers are allowed, but only if the pointer points // to a wrappable class... // cable::Type *doubly_nested_type = cable::PointerType::SafeDownCast(nested_type)->GetTarget(); cable::Type::TypeIdType doubly_nested_type_id = doubly_nested_type->GetTypeId(); if (cable::Type::ClassTypeId == doubly_nested_type_id) { wrappable = TypeIsWrappable(doubly_nested_type); } } } break; case cable::Type::OffsetTypeId: case cable::Type::MethodTypeId: wrappable = false; break; case cable::Type::FunctionTypeId: wrappable = FunctionTypeIsWrappable(cable::FunctionType::SafeDownCast(t)); break; default: wrappable = false; break; } return wrappable; } //---------------------------------------------------------------------------- bool IsCxxMainStyleParamPair(const cable::FunctionType* ft, unsigned int i) { // Special case C++ "main" style functions, as indicated by *this* *exact* // *signature* including arg names: // (..., int argc, char* argv[], ...) // if (i < ft->GetNumberOfArguments()-1 && gxsys_stl::string("argc") == ft->GetArgumentName(i) && cable::Type::FundamentalTypeId == ft->GetArgument(i)->GetTypeId() && cxx::FundamentalType::Int == cxx::FundamentalType::SafeDownCast(ft->GetArgument(i)->GetCxxType().GetType())->GetId() && gxsys_stl::string("argv") == ft->GetArgumentName(i+1) && IsCharPointerPointer(ft->GetArgument(i+1)) ) { return true; } return false; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::FunctionTypeIsWrappable(const cable::FunctionType* ft) { bool wrappable = true; cable::Type *argType = 0; cable::Type *retType = 0; unsigned int i = 0; unsigned int cArgs = ft->GetNumberOfArguments(); retType = ft->GetReturns(); wrappable = TypeIsWrappable(retType); for (i= 0; wrappable && iGetArgument(i); wrappable = TypeIsWrappable(argType); // If not wrappable because argType is "char**" but it is a cxx main style // param pair, then go ahead and say it is wrappable... // if (!wrappable && IsCxxMainStyleParamPair(ft, i-1)) { wrappable = true; } } return wrappable; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::MethodWrappableAsEvent(const cable::Method* m, const cable::Context::Access& access) { bool wrappableAsEvent = false; gxsys_stl::string atts; if (m) { if (cable::Context::Public == access) { if (cable::Function::FunctionId == m->GetFunctionId() || cable::Function::MethodId == m->GetFunctionId()) { wrappableAsEvent = HasAttribute(m, "gccxml(iwhEvent)"); } } } return wrappableAsEvent; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::MethodIsWrappable(const cable::Method* m, const cable::Context::Access& access) { bool wrappable = false; bool hasDeprecatedAttribute = false; bool hasExcludeAttribute = false; bool isExcludedViaBtxEtx = false; if (m) { if (cable::Context::Public == access) { if (cable::Function::FunctionId == m->GetFunctionId() || cable::Function::MethodId == m->GetFunctionId()) { if (FunctionTypeIsWrappable(m->GetFunctionType())) { wrappable = true; } } } } if (m && wrappable) { hasDeprecatedAttribute = HasAttribute(m, "deprecated"); hasExcludeAttribute = HasAttribute(m, "gccxml(iwhExclude)"); if (hasDeprecatedAttribute || hasExcludeAttribute) { wrappable = false; } } if (m && wrappable) { cable::Class* c = cable::Class::SafeDownCast(m->GetContext()); // BTX ETX style exclusion can only be applied to methods of the current target // class... We need to add multiple HeaderFileReader support to enable BTX ETX style // exclusion fully (including parent class method exclusion for purposes of constructing // the initial "what virtual methods do I inherit?" table...) // if (c && c == this->GetTargetClass() && this->GetHeaderFileReader(c)->IsLineExcluded(m->GetLine())) { isExcludedViaBtxEtx = true; wrappable = false; } } if (this->GetSettings()->GetVerbose()) { if (m) { if (cable::Context::Public == access) { if (cable::Function::FunctionId == m->GetFunctionId() || cable::Function::MethodId == m->GetFunctionId()) { if (wrappable) { LogInfo(mi_VerboseInfo, << m->GetNameOfClass() << " '" << m->GetName() << "' is wrappable..." << gxsys_ios::endl); } else { if (hasDeprecatedAttribute) { LogWarning(mw_CouldNotWrap, << m->GetNameOfClass() << " '" << m->GetName() << "' could not be wrapped because it is marked with the 'deprecated' attribute..." << gxsys_ios::endl); } else if (hasExcludeAttribute) { LogWarning(mw_CouldNotWrap, << m->GetNameOfClass() << " '" << m->GetName() << "' could not be wrapped because it is marked with the 'gccxml(iwhExclude)' attribute..." << gxsys_ios::endl); } else if (isExcludedViaBtxEtx) { LogWarning(mw_CouldNotWrap, << m->GetNameOfClass() << " '" << m->GetName() << "' could not be wrapped because it is in between begin/end exclude markers (BTX/ETX)..." << gxsys_ios::endl); } else { LogWarning(mw_CouldNotWrap, << m->GetNameOfClass() << " '" << m->GetName() << "' could not be wrapped because of its return type or one of its arguments' types..." << gxsys_ios::endl); } } } else { LogWarning(mw_CouldNotWrap, << m->GetNameOfClass() << " '" << m->GetName() << "' could not be wrapped because it's not a function or method..." << gxsys_ios::endl); } } else { LogWarning(mw_CouldNotWrap, << m->GetNameOfClass() << " '" << m->GetName() << "' is not considered for wrapping because of its non-public access level..." << gxsys_ios::endl); } } else { LogWarning(mw_CouldNotWrap, << "NULL m!!" << gxsys_ios::endl); } } return wrappable; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::ClassIsWrappable(const cable::Class* c) { return MummyGenerator::ClassIsWrappable(c); } //---------------------------------------------------------------------------- const cable::Class* MummyCsharpGenerator::GetWrappableParentClass(const cable::Class *c) { const cable::Class* wrappableParent = GetParentClass(c); while (wrappableParent && !this->ClassIsWrappable(wrappableParent)) { wrappableParent = GetParentClass(wrappableParent); } return wrappableParent; } //---------------------------------------------------------------------------- // // WARNING: GetIsRefArg, GetPInvokeTypeString and GetCSharpTypeString need to // stay in sync. Changes in one likely imply that changes in the other are // also required... // // This function needs to stay in sync with the case in GetCSharpTypeString // where "ref " is prepended to the C# type string... If "ref " is prepended // then this function should return true. // bool MummyCsharpGenerator::GetIsRefArg(const cable::Type *t) { cable::Type *nested_type = 0; if (cable::Type::ReferenceTypeId == t->GetTypeId()) { nested_type = cable::ReferenceType::SafeDownCast(t)->GetTarget(); cable::Type::TypeIdType nested_type_id = nested_type->GetTypeId(); if (cable::Type::EnumerationTypeId == nested_type_id || cable::Type::FundamentalTypeId == nested_type_id) { return true; } } return false; } //---------------------------------------------------------------------------- gxsys_stl::string /* MummyCsharpGenerator:: */ GetEnumerationTypeString(const cable::Type *t) { gxsys_stl::string s; cable::Enumeration* e = cable::EnumerationType::SafeDownCast(t)->GetEnumeration(); s = GetFullyQualifiedNameForCSharp(e); // Don't name unnamed enums with invalid C#/C++ identifiers like "$"... // if (strstr(s.c_str(), "$")) { s = "uint /* WARNING_unnamed_enum */"; } return s; } //---------------------------------------------------------------------------- // // WARNING: GetIsRefArg, GetPInvokeTypeString and GetCSharpTypeString need to // stay in sync. Changes in one likely imply that changes in the other are // also required... // gxsys_stl::string MummyCsharpGenerator::GetPInvokeTypeString(const cable::Type *t, bool forReturn, bool isArray, bool forDelegate) { gxsys_stl::string s; cable::Type *nested_type = 0; switch (t->GetTypeId()) { case cable::Type::EnumerationTypeId: s = GetEnumerationTypeString(t); break; case cable::Type::FundamentalTypeId: s = GetFundamentalTypeString(t); // C# byte maps automatically to C++ bool via PInvoke // if (s == "bool") { s = "byte"; } break; case cable::Type::ArrayTypeId: s = "ERROR_ArrayTypeId_not_yet_implemented"; LogError(me_InternalError, << s.c_str()); break; case cable::Type::ClassTypeId: //s = cable::ClassType::SafeDownCast(t)->GetClass()->GetName(); s = GetWrappedClassNameFullyQualified(cable::ClassType::SafeDownCast(t)->GetClass()); break; case cable::Type::PointerTypeId: nested_type = cable::PointerType::SafeDownCast(t)->GetTarget(); if (IsObject(nested_type)) { if (forReturn || forDelegate) { s = "IntPtr"; } else { cable::Class *c = cable::ClassType::SafeDownCast(nested_type)->GetClass(); if (IsUtilityClass(c)) { //s = c->GetName(); s = GetWrappedClassNameFullyQualified(c); } else { s = "HandleRef"; } } } else if (IsChar(nested_type)) { if (forReturn) { s = "IntPtr"; } else { s = "string"; } } else if (IsVoid(nested_type)) { s = "IntPtr"; } else if (cable::Type::FundamentalTypeId == nested_type->GetTypeId()) { if (isArray && !forReturn) { s = GetPInvokeTypeString(nested_type, forReturn, isArray, forDelegate); } else { s = "IntPtr"; } } else if (cable::Type::PointerTypeId == nested_type->GetTypeId()) { if (IsCharPointer(nested_type)) { s = "[In, Out] string[]"; } else { s = "IntPtr /* pointer-to-pointer */"; } } else if (cable::Type::FunctionTypeId == nested_type->GetTypeId()) { if (!EquivalentTypedefNameExists(this->GetTargetClass(), cable::FunctionType::SafeDownCast(nested_type), s)) { s = "ERROR_No_equivalent_typedef_name_for_function_pointer"; LogError(me_InternalError, << s.c_str()); } } else { s = "ERROR_PointerTypeId_not_yet_implemented_for_nested_type"; LogError(me_InternalError, << s.c_str()); } break; case cable::Type::ReferenceTypeId: { cable::Type *nested_type = cable::ReferenceType::SafeDownCast(t)->GetTarget(); cable::Type::TypeIdType nested_type_id = nested_type->GetTypeId(); s = "ERROR_ReferenceTypeId_not_yet_implemented_for_nested_type"; if (cable::Type::EnumerationTypeId == nested_type_id || cable::Type::FundamentalTypeId == nested_type_id || cable::Type::ClassTypeId == nested_type_id) { s = GetPInvokeTypeString(nested_type, forReturn, isArray, forDelegate); if (!isArray && (cable::Type::EnumerationTypeId == nested_type_id || cable::Type::FundamentalTypeId == nested_type_id)) { if (forReturn) { s = "IntPtr"; } else { s = gxsys_stl::string("ref ") + s; } } } else if (cable::Type::PointerTypeId == nested_type_id) { // References to pointers are allowed, but only if the pointer points // to a wrappable class... // cable::Type *doubly_nested_type = cable::PointerType::SafeDownCast(nested_type)->GetTarget(); cable::Type::TypeIdType doubly_nested_type_id = doubly_nested_type->GetTypeId(); if (cable::Type::ClassTypeId == doubly_nested_type_id) { s = GetPInvokeTypeString(nested_type, forReturn, isArray, forDelegate); } } if (s == "ERROR_ReferenceTypeId_not_yet_implemented_for_nested_type") { LogError(me_InternalError, << s.c_str()); } } break; case cable::Type::OffsetTypeId: case cable::Type::MethodTypeId: case cable::Type::FunctionTypeId: default: s = "ERROR_No_CSharp_type_for_cable_Type_TypeId"; LogError(me_InternalError, << s.c_str()); break; } return s; } //---------------------------------------------------------------------------- // // WARNING: GetIsRefArg, GetPInvokeTypeString and GetCSharpTypeString need to // stay in sync. Changes in one likely imply that changes in the other are // also required... // gxsys_stl::string MummyCsharpGenerator::GetCSharpTypeString(const cable::Type *t, bool forReturn, bool isArray) { gxsys_stl::string s; cable::Type *nested_type = 0; switch (t->GetTypeId()) { case cable::Type::EnumerationTypeId: s = GetEnumerationTypeString(t); break; case cable::Type::FundamentalTypeId: s = GetFundamentalTypeString(t); break; case cable::Type::ArrayTypeId: s = "ERROR_ArrayTypeId_not_yet_implemented"; LogError(me_InternalError, << s.c_str()); break; case cable::Type::ClassTypeId: //s = cable::ClassType::SafeDownCast(t)->GetClass()->GetName(); s = GetWrappedClassNameFullyQualified(cable::ClassType::SafeDownCast(t)->GetClass()); break; case cable::Type::PointerTypeId: nested_type = cable::PointerType::SafeDownCast(t)->GetTarget(); if (IsObject(nested_type)) { s = GetCSharpTypeString(nested_type, forReturn, isArray); } else if (IsChar(nested_type)) { s = "string"; } else if (IsVoid(nested_type)) { s = "IntPtr"; } else if (cable::Type::FundamentalTypeId == nested_type->GetTypeId()) { if (isArray) { s = GetCSharpTypeString(nested_type, forReturn, isArray); } else { s = "IntPtr"; } } else if (cable::Type::PointerTypeId == nested_type->GetTypeId()) { s = GetCSharpTypeString(nested_type, forReturn, isArray); if (IsCharPointer(nested_type)) { s += "[]"; } else { s += " /* pointer-to-pointer */ "; } } else if (cable::Type::FunctionTypeId == nested_type->GetTypeId()) { s = GetCSharpTypeString(nested_type, forReturn, isArray); } else { s = "ERROR_PointerTypeId_not_yet_implemented_for_nested_type"; LogError(me_InternalError, << s.c_str()); } break; case cable::Type::ReferenceTypeId: { cable::Type *nested_type = cable::ReferenceType::SafeDownCast(t)->GetTarget(); cable::Type::TypeIdType nested_type_id = nested_type->GetTypeId(); s = "ERROR_ReferenceTypeId_not_yet_implemented_for_nested_type"; if (cable::Type::EnumerationTypeId == nested_type_id || cable::Type::FundamentalTypeId == nested_type_id || cable::Type::ClassTypeId == nested_type_id) { s = GetCSharpTypeString(nested_type, forReturn, isArray); if (!isArray && (cable::Type::EnumerationTypeId == nested_type_id || cable::Type::FundamentalTypeId == nested_type_id)) { if (forReturn) { s = "IntPtr"; } else if (s == "bool") { // Special case: transform "ref bool" args to "ref byte" args so // that we can call the PInvoke method, which changes all "bool" // to "byte" -- we don't do it in the non-ref case because it works // automatically and "bool" is a nicer C# signature. But in the ref // case, we need: // s = gxsys_stl::string("ref byte"); } else { s = gxsys_stl::string("ref ") + s; } } } else if (cable::Type::PointerTypeId == nested_type_id) { // References to pointers are allowed, but only if the pointer points // to a wrappable class... // cable::Type *doubly_nested_type = cable::PointerType::SafeDownCast(nested_type)->GetTarget(); cable::Type::TypeIdType doubly_nested_type_id = doubly_nested_type->GetTypeId(); if (cable::Type::ClassTypeId == doubly_nested_type_id) { s = GetCSharpTypeString(doubly_nested_type, forReturn, isArray); } } if (s == "ERROR_ReferenceTypeId_not_yet_implemented_for_nested_type") { LogError(me_InternalError, << s.c_str()); } } break; case cable::Type::FunctionTypeId: if (!EquivalentTypedefNameExists(this->GetTargetClass(), cable::FunctionType::SafeDownCast(t), s)) { s = "ERROR_No_equivalent_typedef_name_for_function_pointer"; LogError(me_InternalError, << s.c_str()); } break; case cable::Type::OffsetTypeId: case cable::Type::MethodTypeId: default: s = "ERROR_No_CSharp_type_for_cable_Type_TypeId"; LogError(me_InternalError, << s.c_str()); break; } return s; } //---------------------------------------------------------------------------- class MethodInstance { public: const cable::Class* Class; const cable::Method* Method; MethodInstance(const cable::Class* c, const cable::Method* m) : Class(c), Method(m) { } }; //---------------------------------------------------------------------------- gxsys_stl::map OtherMethods; gxsys_stl::map StaticMethods; gxsys_stl::map VirtualMethods; gxsys_stl::map WrappedMethods; gxsys_stl::map WrappedEnums; // in this case all MethodInstance.Method members are null //---------------------------------------------------------------------------- void MummyCsharpGenerator::ClearLookupEntries() { OtherMethods.clear(); StaticMethods.clear(); VirtualMethods.clear(); WrappedMethods.clear(); WrappedEnums.clear(); // Pretend that "System.Object" is in our inheritance chain and that its // virtual method signatures exist in our lookup map: // // VirtualMethods.insert(gxsys_stl::make_pair("Equals(object)", MethodInstance(0, 0))); // VirtualMethods.insert(gxsys_stl::make_pair("Finalize()", MethodInstance(0, 0))); // VirtualMethods.insert(gxsys_stl::make_pair("GetHashCode()", MethodInstance(0, 0))); // VirtualMethods.insert(gxsys_stl::make_pair("GetType()", MethodInstance(0, 0))); // VirtualMethods.insert(gxsys_stl::make_pair("MemberwiseClone()", MethodInstance(0, 0))); // VirtualMethods.insert(gxsys_stl::make_pair("Object()", MethodInstance(0, 0))); // VirtualMethods.insert(gxsys_stl::make_pair("ToString()", MethodInstance(0, 0))); } //---------------------------------------------------------------------------- void MummyCsharpGenerator::AddLookupEntries(const cable::Class* c) { if (c) { const cable::Class *parent = GetWrappableParentClass(c); if (parent) { AddLookupEntries(parent); } for(cable::Context::Iterator it = c->Begin(); it != c->End(); ++it) { cable::Method *m = cable::Method::SafeDownCast(*it); if (m && MethodIsWrappable(m, it.GetAccess())) { if (m->GetVirtual()) { VirtualMethods.insert(gxsys_stl::make_pair(GetMethodSignature(c, m), MethodInstance(c, m))); } else if (m->GetStatic()) { StaticMethods.insert(gxsys_stl::make_pair(GetMethodSignature(c, m), MethodInstance(c, m))); } else { OtherMethods.insert(gxsys_stl::make_pair(GetMethodSignature(c, m), MethodInstance(c, m))); } } if (!m) { cable::Enumeration *e = cable::Enumeration::SafeDownCast(*it); if (e && (cable::Context::Public == it.GetAccess())) { WrappedEnums.insert(gxsys_stl::make_pair(GetWrappedEnumName(e), MethodInstance(c, 0))); } } } } } //---------------------------------------------------------------------------- void MummyCsharpGenerator::DumpLookupEntries() { gxsys_stl::map::iterator it; LogInfo(mi_Info, << ""); LogInfo(mi_Info, << "inherited static methods:"); for (it= StaticMethods.begin(); it!=StaticMethods.end(); ++it) { LogInfo(mi_Info, << " " << it->first); } LogInfo(mi_Info, << "inherited virtual methods:"); for (it= VirtualMethods.begin(); it!=VirtualMethods.end(); ++it) { LogInfo(mi_Info, << " " << it->first); } LogInfo(mi_Info, << "inherited other methods:"); for (it= OtherMethods.begin(); it!=OtherMethods.end(); ++it) { LogInfo(mi_Info, << " " << it->first); } LogInfo(mi_Info, << "wrapped methods:"); for (it= WrappedMethods.begin(); it!=WrappedMethods.end(); ++it) { LogInfo(mi_Info, << " " << it->first); } LogInfo(mi_Info, << "wrapped enums:"); for (it= WrappedEnums.begin(); it!=WrappedEnums.end(); ++it) { LogInfo(mi_Info, << " " << it->first); } LogInfo(mi_Info, << ""); } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::OtherMethodRedefined(const gxsys_stl::string &signature) { gxsys_stl::map::iterator it = OtherMethods.find(signature); return it != OtherMethods.end(); } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::StaticMethodRedefined(const gxsys_stl::string &signature) { gxsys_stl::map::iterator it = StaticMethods.find(signature); return it != StaticMethods.end(); } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::VirtualMethodOverridden(const gxsys_stl::string &signature) { gxsys_stl::map::iterator it = VirtualMethods.find(signature); return it != VirtualMethods.end(); } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::WrappedMethodExists(const gxsys_stl::string &signature) { gxsys_stl::map::iterator it = WrappedMethods.find(signature); return it != WrappedMethods.end(); } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::WrappedEnumExists(const gxsys_stl::string &name) { gxsys_stl::map::iterator it = WrappedEnums.find(name); return it != WrappedEnums.end(); } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::IsFactoryMethod(const cable::Class *c, const cable::Method *m) { if (m->GetStatic() && 0 == m->GetFunctionType()->GetNumberOfArguments() && gxsys_stl::string(m->GetName()) == this->GetSettings()->GetFactoryMethod(c)) { return true; } return false; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::IsDisposalMethod(const cable::Class *c, const cable::Method *m) { if (m->GetVirtual() && 0 == m->GetFunctionType()->GetNumberOfArguments() && gxsys_stl::string(m->GetName()) == this->GetSettings()->GetDisposalMethod(c)) { return true; } return false; } //---------------------------------------------------------------------------- bool MummyCsharpGenerator::MethodReturnValueIsCounted(const cable::Class *c, const cable::Method *m) { if (this->IsFactoryMethod(c, m)) { return true; } if (HasAttribute(m, "gccxml(iwhCounted)")) { return true; } gxsys_stl::string countedMethodsRegex(this->GetSettings()->GetCountedMethodsRegex(c)); if (!countedMethodsRegex.empty()) { gxsys::RegularExpression re; re.compile(countedMethodsRegex.c_str()); if (re.find(m->GetName())) { LogVerboseInfo( << "MethodReturnValueIsCounted match:" << gxsys_ios::endl << " countedMethodsRegex: " << countedMethodsRegex << gxsys_ios::endl << " method: " << c->GetName() << "::" << m->GetName() ); return true; } } return false; } //---------------------------------------------------------------------------- gxsys_stl::string MummyCsharpGenerator::GetExportLayerFunctionName(const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname) { gxsys_stl::string s(GetFullyQualifiedName(c, "_")); s += "_"; s += mname; if (this->IsFactoryMethod(c, m) || this->IsDisposalMethod(c, m) || mname == "new" || mname == "delete") { // No suffix... } else { // Append a unique-fying suffix... char idStr[32]; unsigned int methodId = 0; gxsys_stl::map::iterator it = this->MethodIdMap.find(m); if (it != this->MethodIdMap.end()) { methodId = it->second; } else { // Any methods passed in to here should have been inserted into the // MethodIdMap during a previous call to GatherWrappedMethods... // What happened...!?!? // LogError(me_InternalError, << "Could not find method in MethodIdMap."); } sprintf(idStr, "%02u", methodId); s += "_"; s += idStr; } return s; } //---------------------------------------------------------------------------- // // GetMethodSignature is very similar to EmitCSharpMethodDeclaration. // Changes in either may need to be made in both places... // void MummyCsharpGenerator::EmitCSharpMethodDeclaration(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method *m, bool asProperty, bool useArg0AsReturn, const gxsys_stl::string& accessLevel) { gxsys_stl::string signature(GetMethodSignature(c, m)); gxsys_stl::string arraySize; gxsys_stl::string s; cable::FunctionType *ft = m->GetFunctionType(); unsigned int cArgs = ft->GetNumberOfArguments(); unsigned int i = 0; cable::Type *argType = 0; cable::Type *retType = ft->GetReturns(); i = RETURN_VALUE; // If emitting a declaration based on a "property set" method, // the type of the first argument to the set method is the type // of the C# property... typically retType will be "void" when // this is the case... // if (asProperty && useArg0AsReturn) { if (!IsVoid(retType)) { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_PropSetReturnsNonVoid, "Method transformed to a property 'set' returns non-void. The return value will be ignored in generated code."); } if (cArgs!=1) { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_PropSetUnexpectedArgCount, "Unexpected number of arguments for method transformed to a property 'set' - cArgs: " << cArgs); } // :-) // // Pretend return type and attributes come from arg0 for the // rest of this method call: // if (cArgs!=0) { i = 0; retType = ft->GetArgument(0); } } // Do attributes indicate an array? // arraySize = GetMethodArgumentArraySize(c, m, ft, i); // Public, protected, private, internal, hmmmm...? // Emit(os, accessLevel.c_str()); Emit(os, " "); if (m->GetStatic()) { // C# static == C++ static: // if (StaticMethodRedefined(signature)) { Emit(os, "new "); } Emit(os, "static "); } if (!asProperty) { if (m->GetVirtual()) { // C# : "virtual" or "override" ? // if (VirtualMethodOverridden(signature)) { Emit(os, "override "); } else { // If I am virtual, but my parent is not then: // if (OtherMethodRedefined(signature)) { Emit(os, "new "); } Emit(os, "virtual "); } } else { if (OtherMethodRedefined(signature)) { Emit(os, "new "); } } } // Return type. (Has special transformations for supporting collections // and enumerators. Method name + class supports target interface == // special generated code...) // gxsys_stl::string mname = m->GetName(); if ((mname == "GetEnumerator") && this->HasTargetInterface("IEnumerable")) { Emit(os, "System.Collections.IEnumerator"); } else if ((mname == "GetCurrent") && this->HasTargetInterface("IEnumerator")) { Emit(os, "object"); } else { Emit(os, GetCSharpTypeString(retType, true, arraySize != "").c_str()); if (arraySize != "") { Emit(os, "[]"); } } Emit(os, " "); // Use the wrapped method name or the property name: // s = GetWrappedMethodName(m); if (asProperty) { s = ExtractDerivedName(s.c_str(), m, this->GetSettings()->GetVerbose()); } Emit(os, s.c_str()); if (!asProperty) { // Open args: Emit(os, "("); // The C# args: for (i= 0; iGetArgument(i); // Is arg an array? // arraySize = GetMethodArgumentArraySize(c, m, ft, i); // arg type: Emit(os, GetCSharpTypeString(argType, false, arraySize != "").c_str()); // array notation: if (arraySize != "") { Emit(os, "[]"); } // arg name: Emit(os, " "); Emit(os, GetArgName(ft, i)); if (iGetFunctionType(); unsigned int cArgs = ft->GetNumberOfArguments(); unsigned int cArgsEmitted = 0; unsigned int i = 0; cable::Type *argType = 0; cable::Type *retType = ft->GetReturns(); Emit(os, "[DllImport("); Emit(os, dllname); Emit(os, ", EntryPoint = \""); Emit(os, f); Emit(os, "\")]"); Emit(os, "\n"); // Does method return an array? // arraySize = GetMethodArgumentArraySize(c, m, ft, RETURN_VALUE); EmitIndent(os); Emit(os, "internal static extern "); if (mname == "new") { Emit(os, "IntPtr "); Emit(os, f); Emit(os, "(ref uint mteStatus, ref uint mteIndex, ref uint rawRefCount"); cArgsEmitted += 3; if (emitExceptionParams) { Emit(os, ", ref uint mteExceptionIndex, ref IntPtr clonedException"); cArgsEmitted += 2; } Emit(os, ");"); } else if (mname == "delete") { Emit(os, "void "); Emit(os, f); Emit(os, "(HandleRef pThis"); cArgsEmitted += 1; if (emitExceptionParams) { Emit(os, ", ref uint mteExceptionIndex, ref IntPtr clonedException"); cArgsEmitted += 2; } Emit(os, ");"); } else { Emit(os, GetPInvokeTypeString(retType, true, arraySize != "", false).c_str()); Emit(os, " "); Emit(os, f); Emit(os, "("); if (!m->GetStatic()) { Emit(os, "HandleRef pThis"); cArgsEmitted += 1; if (cArgs!=0) { Emit(os, ", "); } } for (i= 0; iGetArgument(i); // Is arg an array? // arraySize = GetMethodArgumentArraySize(c, m, ft, i); // array MarshalAs directive: if (arraySize != "") { Emit(os, "[MarshalAs(UnmanagedType.LPArray, SizeConst = "); Emit(os, arraySize.c_str()); Emit(os, ")] "); } // arg type: Emit(os, GetPInvokeTypeString(argType, false, arraySize != "", false).c_str()); // array notation: if (arraySize != "") { Emit(os, "[]"); } // arg name: Emit(os, " "); Emit(os, GetArgName(ft, i)); cArgsEmitted += 1; if (iGetFunctionType()->GetReturns() )->GetTarget())->GetClass(); gxsys_stl::string eventName; if (c && c->GetContext()) { eventName = c->GetContext()->GetName(); eventName += GetWrappedClassName(c); } else { eventName = "ERROR_invalid_input_to_GetQualifiedEventName"; LogError(me_InvalidArg, << eventName.c_str()); } return eventName; } //---------------------------------------------------------------------------- gxsys_stl::string GetEventName(const cable::Method *m) { gxsys_stl::string eventName = GetWrappedClassName( cable::ClassType::SafeDownCast(cable::PointerType::SafeDownCast( m->GetFunctionType()->GetReturns() )->GetTarget())->GetClass() ); return eventName; } //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpEvent(gxsys_ios::ostream& os, const char *, const cable::Class* c, const cable::Method* m, const gxsys_stl::string& eventName) { // Caller provides eventName because caller is the one with the knowledge // about whether there are multiple events with the same unqualified name // due to classes with the same name existing in multiple namespaces. // So, if there are not, eventName will be from "GetEventName", but if // there are, eventName will be from "GetQualifiedEventName"... // gxsys_stl::string e(eventName); gxsys_stl::string eFull; gxsys_stl::string mname(m->GetName()); // An "event method" is expected to return a pointer to the event class // that it is supposed to wrap... If that's not true, the code generated // by this following block is likely not to compile! So make sure it's // true in your sources to be wrapped. // cable::FunctionType *ft = m->GetFunctionType(); cable::Type *retType = ft->GetReturns(); if (retType->GetTypeId() != cable::Type::PointerTypeId) { LogFileLineErrorMsg(m->GetFile(), m->GetLine(), me_EventMethodIncorrectReturnType, "iwhEvent method '" << mname << "' does not return a pointer to an event object"); return; } if (cable::PointerType::SafeDownCast(retType)->GetTarget()->GetTypeId() != cable::Type::ClassTypeId) { LogFileLineErrorMsg(m->GetFile(), m->GetLine(), me_EventMethodIncorrectReturnType, "iwhEvent method '" << mname << "' does not return a pointer to an event object"); return; } eFull = GetWrappedClassNameFullyQualified(cable::ClassType::SafeDownCast( cable::PointerType::SafeDownCast(retType)->GetTarget())->GetClass()); // Assumptions: // // (These could all be codified and made into non-assumptions, but for now // they all *are* assumptions...) // // There's a type called "Handler" in the Event class (typedef to a function pointer in unmanaged C++) // The typedef signature is "void blah(object sender, object args)" // There's a corresponding EventArgs class named the same but with "EventArgs" at the end // There's an AddHandler method in the Event class // There's a RemoveHandler method in the Event class // The handler is id'able by a C# "uint" // Make this next section collapsible inside a "region": // EmitIndent(os); Emit(os, "#region "); Emit(os, e.c_str()); Emit(os, " event implementation details\n"); Emit(os, "\n"); // A data member (*Impl) to hold the managed listeners: // EmitIndent(os); Emit(os, "private "); Emit(os, e.c_str()); Emit(os, "EventHandler "); Emit(os, e.c_str()); Emit(os, "Impl;\n"); // A data member (*Instance) to cache the managed wrapper of the unmanaged // event object: // EmitIndent(os); Emit(os, "private "); Emit(os, eFull.c_str()); Emit(os, " "); Emit(os, e.c_str()); Emit(os, "Instance;\n"); // A data member (*RelayHandler) and an id (*RelayHandlerId) for the handler // when we are actively connected... // EmitIndent(os); Emit(os, "private "); Emit(os, eFull.c_str()); Emit(os, ".Handler "); Emit(os, e.c_str()); Emit(os, "RelayHandler;\n"); EmitIndent(os); Emit(os, "private uint "); Emit(os, e.c_str()); Emit(os, "RelayHandlerId;\n"); Emit(os, "\n"); // A listener to receive events from the unmanaged code and relay them on to // managed listeners. Conforms to event's "unmanaged" delegate signature. // (The delegate named "Handler" in the event class itself.) One improvement // we could make here would be to generate RelayHandler's signature based // on the actual signature of "Handler." // EmitIndent(os); Emit(os, "private void "); Emit(os, e.c_str()); Emit(os, "RelayHandlerMethod(IntPtr rawSender, IntPtr rawArgs)\n"); EmitIndent(os); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, "if (this."); Emit(os, e.c_str()); Emit(os, "Impl != null)\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 3); Emit(os, eFull.c_str()); Emit(os, "EventArgs rv = null;\n"); EmitIndent(os, 3); Emit(os, "if (IntPtr.Zero != rawArgs)\n"); EmitIndent(os, 3); Emit(os, "{\n"); const cable::Class* cRetType = cable::ClassType::SafeDownCast( cable::PointerType::SafeDownCast(retType)->GetTarget() )->GetClass(); gxsys_stl::string registerMethod = this->GetSettings()->GetRegisterMethod(cRetType); gxsys_stl::string unRegisterMethod = this->GetSettings()->GetUnRegisterMethod(cRetType); // Technique #1 : using "new" (and ignoring potential issues with // the mummy Runtime table... // EmitIndent(os, 4); Emit(os, "rv = new "); Emit(os, eFull.c_str()); Emit(os, "EventArgs(rawArgs, "); if (!registerMethod.empty()) { Emit(os, "true"); } else { Emit(os, "false"); } Emit(os, ", false);\n"); if (!registerMethod.empty()) { EmitIndent(os, 4); Emit(os, "rv."); Emit(os, registerMethod.c_str()); Emit(os, ";\n"); } // Technique #2 : using "CreateWrappedObject" (and forcing a call // back across the boundary to "Register" the EventArgs if the wrapper // was just created...) // // This imposes an additional assumption/constraint on Event and EventArgs // classes. They must share Register/UnRegister methods for this to work // properly... // // Either that, or we need to get a "cable::Class*" to the EventArgs class // somehow (which we may or may not be able to do depending on how the // gccxml step and the input header files were crafted...) // //unsigned int indent = 3; //EmitIndent(os, indent+1); //Emit(os, "bool mteCreated;\n"); //EmitIndent(os, indent+1); //Emit(os, "rv = ("); //Emit(os, eFull.c_str()); //Emit(os, "EventArgs)\n"); //EmitIndent(os, indent+2); //Emit(os, "Kitware.mummy.Runtime.Methods.CreateWrappedObject(\n"); //EmitIndent(os, indent+3); //Emit(os, "\"class "); //Emit(os, eFull.c_str()); //Emit(os, "EventArgs\", rawArgs, "); //if (!unRegisterMethod.empty()) // { // Emit(os, "true"); // } //else // { // Emit(os, "false"); // } //Emit(os, ", out mteCreated"); //Emit(os, ");\n"); //if (!registerMethod.empty()) // { // //if (this->MethodReturnValueIsCounted(c, m)) // // { // // EmitIndent(os, indent+1); // // Emit(os, "Returned object is counted already, (factory method or iwhCounted hint),\n"); // // EmitIndent(os, indent+1); // // Emit(os, "// no 'rv."); // // Emit(os, registerMethod.c_str()); // // Emit(os, "' call is necessary...\n"); // // } // //else // // { // EmitIndent(os, indent+1); // Emit(os, "if (mteCreated)\n"); // EmitIndent(os, indent+1); // Emit(os, "{\n"); // EmitIndent(os, indent+2); // Emit(os, "rv."); // Emit(os, registerMethod.c_str()); // Emit(os, ";\n"); // EmitIndent(os, indent+1); // Emit(os, "}\n"); // // } // } EmitIndent(os, 3); Emit(os, "}\n"); EmitIndent(os, 3); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "Impl(this, rv);\n"); EmitIndent(os, 2); Emit(os, "}\n"); EmitIndent(os); Emit(os, "}\n"); Emit(os, "\n"); // Methods to add and remove the RelayHandler: // EmitIndent(os); Emit(os, "private void Add"); Emit(os, e.c_str()); Emit(os, "RelayHandler()\n"); EmitIndent(os); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, "if (0 == this."); Emit(os, e.c_str()); Emit(os, "RelayHandlerId)\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 3); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "RelayHandler =\n"); EmitIndent(os, 4); Emit(os, "new "); Emit(os, eFull.c_str()); Emit(os, ".Handler(\n"); EmitIndent(os, 5); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "RelayHandlerMethod);\n"); Emit(os, "\n"); EmitIndent(os, 3); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "Instance =\n"); EmitIndent(os, 4); Emit(os, "this."); Emit(os, mname.c_str()); Emit(os, "();\n"); Emit(os, "\n"); EmitIndent(os, 3); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "RelayHandlerId =\n"); EmitIndent(os, 4); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "Instance.AddHandler(\n"); EmitIndent(os, 5); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "RelayHandler);\n"); EmitIndent(os, 2); Emit(os, "}\n"); EmitIndent(os); Emit(os, "}\n"); Emit(os, "\n"); EmitIndent(os); Emit(os, "private void Remove"); Emit(os, e.c_str()); Emit(os, "RelayHandler()\n"); EmitIndent(os); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, "if (0 != this."); Emit(os, e.c_str()); Emit(os, "RelayHandlerId)\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 3); Emit(os, "if (System.IntPtr.Zero != this."); Emit(os, e.c_str()); Emit(os, "Instance.GetCppThis().Handle)\n"); EmitIndent(os, 3); Emit(os, "{\n"); EmitIndent(os, 4); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "Instance.RemoveHandler(\n"); EmitIndent(os, 5); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "RelayHandlerId);\n"); EmitIndent(os, 3); Emit(os, "}\n"); Emit(os, "\n"); EmitIndent(os, 3); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "Instance = null;\n"); EmitIndent(os, 3); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "RelayHandler = null;\n"); EmitIndent(os, 3); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "RelayHandlerId = 0;\n"); EmitIndent(os, 2); Emit(os, "}\n"); EmitIndent(os); Emit(os, "}\n"); Emit(os, "\n"); // End the private details "region": // EmitIndent(os); Emit(os, "#endregion\n"); Emit(os, "\n"); Emit(os, "\n"); // A delegate definition that managed C# handlers must conform to in order // to listen to this event: // EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "/// Delegate signature for the "); Emit(os, e.c_str()); Emit(os, " event.\n"); EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "public delegate void "); Emit(os, e.c_str()); Emit(os, "EventHandler("); Emit(os, c->GetName()); Emit(os, " sender, "); Emit(os, eFull.c_str()); Emit(os, "EventArgs args);\n"); Emit(os, "\n"); Emit(os, "\n"); // Documentation: gxsys_stl::vector docblock; this->GetHeaderFileReader(c)->GetCommentBlockBefore(m->GetLine(), docblock, this->ClassLineNumber); EmitDocumentationBlock(os, docblock, 1); // The actual event with add and remove handlers. // EmitIndent(os); Emit(os, "public event "); Emit(os, e.c_str()); Emit(os, "EventHandler "); Emit(os, e.c_str()); Emit(os, "\n"); EmitIndent(os); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, "add\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 3); Emit(os, "if (this."); Emit(os, e.c_str()); Emit(os, "Impl == null)\n"); EmitIndent(os, 3); Emit(os, "{\n"); EmitIndent(os, 4); Emit(os, "Add"); Emit(os, e.c_str()); Emit(os, "RelayHandler();\n"); EmitIndent(os, 3); Emit(os, "}\n"); Emit(os, "\n"); EmitIndent(os, 3); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "Impl += value;\n"); EmitIndent(os, 2); Emit(os, "}\n"); Emit(os, "\n"); EmitIndent(os, 2); Emit(os, "remove\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 3); Emit(os, "this."); Emit(os, e.c_str()); Emit(os, "Impl -= value;\n"); Emit(os, "\n"); EmitIndent(os, 3); Emit(os, "if (this."); Emit(os, e.c_str()); Emit(os, "Impl == null)\n"); EmitIndent(os, 3); Emit(os, "{\n"); EmitIndent(os, 4); Emit(os, "Remove"); Emit(os, e.c_str()); Emit(os, "RelayHandler();\n"); EmitIndent(os, 3); Emit(os, "}\n"); EmitIndent(os, 2); Emit(os, "}\n"); EmitIndent(os); Emit(os, "}\n"); } //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpProperty(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *propGetMethod, const cable::Method *propSetMethod, bool emitExceptionParams) { gxsys_stl::string fGet; gxsys_stl::string fSet; unsigned int indent = 3; const cable::Method *declMethod = propGetMethod; // Declare the DllImport functions. // if (propGetMethod) { fGet = GetExportLayerFunctionName(c, propGetMethod, propGetMethod->GetName()); EmitIndent(os); EmitCSharpDllImportDeclaration(os, dllname, c, propGetMethod, propGetMethod->GetName(), fGet.c_str(), emitExceptionParams); Emit(os, "\n"); Emit(os, "\n"); } if (propSetMethod) { fSet = GetExportLayerFunctionName(c, propSetMethod, propSetMethod->GetName()); EmitIndent(os); EmitCSharpDllImportDeclaration(os, dllname, c, propSetMethod, propSetMethod->GetName(), fSet.c_str(), emitExceptionParams); Emit(os, "\n"); Emit(os, "\n"); if (!declMethod) { declMethod = propSetMethod; } } if (!declMethod) { // What? no propGetMethod or propSetMethod? Caller has made a mistake somewhere... // LogError(me_InternalError, << "No declMethod in MummyCsharpGenerator::EmitCSharpProperty."); return; } // Documentation: gxsys_stl::vector docblock; this->GetHeaderFileReader(c)->GetCommentBlockBefore(declMethod->GetLine(), docblock, this->ClassLineNumber); EmitDocumentationBlock(os, docblock, 1); // Declaration: EmitIndent(os); EmitCSharpMethodDeclaration(os, c, declMethod, true, declMethod == propSetMethod, "public"); Emit(os, "\n"); // Open body: EmitIndent(os); Emit(os, "{"); Emit(os, "\n"); // The "get" body: if (propGetMethod) { EmitIndent(os, 2); Emit(os, "get\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 3); Emit(os, "// iwhPropGet\n"); EmitCSharpMethodBody(os, 3, c, propGetMethod, fGet, 0, emitExceptionParams); indent = 3; EmitIndent(os, 2); Emit(os, "}\n"); } // The "set" body: if (propSetMethod) { if (propGetMethod) { Emit(os, "\n"); } EmitIndent(os, 2); Emit(os, "set\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 3); Emit(os, "// iwhPropSet\n"); EmitCSharpMethodBody(os, 3, c, propSetMethod, fSet, "value", emitExceptionParams); indent = 3; EmitIndent(os, 2); Emit(os, "}\n"); } // Close body: EmitIndent(os); Emit(os, "}"); Emit(os, "\n"); } //---------------------------------------------------------------------------- void EmitThrowClonedException(gxsys_ios::ostream &os, unsigned int indent) { EmitIndent(os, indent); Emit(os, "if (IntPtr.Zero != clonedException)\n"); EmitIndent(os, indent); Emit(os, "{\n"); EmitIndent(os, indent+1); Emit(os, "bool mteCreatedException;\n"); EmitIndent(os, indent+1); Emit(os, "System.Exception wrappedException = (System.Exception)\n"); EmitIndent(os, indent+2); Emit(os, "Kitware.mummy.Runtime.Methods.CreateWrappedObject(\n"); EmitIndent(os, indent+3); Emit(os, "0, mteExceptionIndex, 0, clonedException, true, out mteCreatedException);\n"); EmitIndent(os, indent+1); Emit(os, "throw wrappedException;\n"); //EmitIndent(os, indent+1); //Emit(os, "System.Exception exc = new System.Exception(\"received clonedException from unmanaged layer...\");\n"); //EmitIndent(os, indent+1); //Emit(os, "throw exc;\n"); EmitIndent(os, indent); Emit(os, "}\n"); } //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpMethodBody(gxsys_ios::ostream &os, unsigned int indent, const cable::Class *c, const cable::Method *m, gxsys_stl::string& f, const char *impliedArg0, bool emitExceptionParams) { // need qualified name? gxsys_stl::string cname(c->GetName()); gxsys_stl::string retArraySize; gxsys_stl::string argArraySize; cable::FunctionType *ft = m->GetFunctionType(); unsigned int cArgs = ft->GetNumberOfArguments(); unsigned int cArgsEmitted = 0; unsigned int i = 0; cable::Type *argType = 0; cable::Type *retType = ft->GetReturns(); bool voidReturn = false; gxsys_stl::string rvType; gxsys_stl::string rvpType; bool argIsRef = false; gxsys_stl::string argTypeString; gxsys_stl::string emittedArg; bool callGetCppThis = false; // Does method return anything? // if (IsVoid(retType)) { voidReturn = true; } // Does method return an array? // retArraySize = GetMethodArgumentArraySize(c, m, ft, RETURN_VALUE); rvpType = GetPInvokeTypeString(retType, true, retArraySize != "", false); rvType = GetCSharpTypeString(retType, true, retArraySize != ""); // Body: // // Set up to handle wrapped exceptions if this class may throw them: // if (emitExceptionParams) { EmitIndent(os, indent); Emit(os, "uint mteExceptionIndex = 0;\n"); EmitIndent(os, indent); Emit(os, "IntPtr clonedException = IntPtr.Zero;\n"); Emit(os, "\n"); } // Delegate the call through the PInvoke/DllImport layer: // EmitIndent(os, indent); if (!voidReturn) { if (retArraySize != "") { Emit(os, rvpType.c_str()); Emit(os, " rvp = "); // rvp == return value pointer } else if (IsObjectPointer(retType)) { Emit(os, rvType.c_str()); Emit(os, " rv = null;\n"); Emit(os, "\n"); EmitIndent(os, indent); Emit(os, "uint mteStatus = 0;\n"); EmitIndent(os, indent); Emit(os, "uint mteIndex = UInt32.MaxValue;\n"); EmitIndent(os, indent); Emit(os, "uint rawRefCount = 0;\n"); EmitIndent(os, indent); Emit(os, rvpType.c_str()); Emit(os, " rvp = "); // rvp == return value pointer } else { Emit(os, rvType.c_str()); Emit(os, " rv = "); // rv == return value } } // Open any special marshalling blocks required: // if (IsCharPointer(retType)) { Emit(os, "Marshal.PtrToStringAnsi("); } // Call the DllImport function: // Emit(os, f.c_str()); Emit(os, "("); // Arguments, 'this' first, then loop over C++ method formal params: // if (!m->GetStatic()) { Emit(os, "this.GetCppThis()"); cArgsEmitted += 1; if (cArgs!=0) { Emit(os, ", "); } } for (i= 0; iGetArgument(i); // Is arg an array? // argArraySize = GetMethodArgumentArraySize(c, m, ft, i); argIsRef = false; if (argArraySize == "" && GetIsRefArg(argType)) { argIsRef = true; Emit(os, "ref "); } argTypeString = GetCSharpTypeString(argType, true, argArraySize != ""); if (!argIsRef && (argTypeString == "bool")) { Emit(os, "(byte)("); } if (impliedArg0 && 0==i) { emittedArg = impliedArg0; } else { emittedArg = GetArgName(ft, i); } Emit(os, emittedArg.c_str()); if (argIsRef) { LogInfo(mi_InfoRefArgEncountered, << "reference arg: " << cname << "." << m->GetName() << " " << argType->GetCxxType().GetName() << " " << emittedArg << " (arg " << i << ")" ); } callGetCppThis = false; if (IsObjectPointer(argType)) { const cable::Class* argClass = cable::ClassType::SafeDownCast( cable::PointerType::SafeDownCast(argType)->GetTarget())->GetClass(); if (!IsUtilityClass(argClass)) { callGetCppThis = true; } } else if (IsObjectPointerReference(argType)) { const cable::PointerType* ptrClass = cable::PointerType::SafeDownCast( cable::ReferenceType::SafeDownCast(argType)->GetTarget()); const cable::Class* argClass = cable::ClassType::SafeDownCast( ptrClass->GetTarget())->GetClass(); if (!IsUtilityClass(argClass)) { callGetCppThis = true; } } if (callGetCppThis) { Emit(os, " == null ? new HandleRef() : "); Emit(os, emittedArg.c_str()); Emit(os, ".GetCppThis()"); } if (!argIsRef && (argTypeString == "bool")) { Emit(os, " ? 1 : 0)"); } } cArgsEmitted += 1; if (iGetTarget() )->GetClass(); gxsys_stl::string registerMethod = this->GetSettings()->GetRegisterMethod(cRetType); gxsys_stl::string unRegisterMethod = this->GetSettings()->GetUnRegisterMethod(cRetType); Emit(os, ";\n"); EmitIndent(os, indent); Emit(os, "if (IntPtr.Zero != rvp)\n"); EmitIndent(os, indent); Emit(os, "{\n"); EmitIndent(os, indent+1); Emit(os, "bool mteCreated;\n"); EmitIndent(os, indent+1); Emit(os, "rv = ("); Emit(os, rvType.c_str()); Emit(os, ")\n"); EmitIndent(os, indent+2); Emit(os, "Kitware.mummy.Runtime.Methods.CreateWrappedObject(\n"); EmitIndent(os, indent+3); Emit(os, "mteStatus, mteIndex, rawRefCount, rvp, "); if (!unRegisterMethod.empty()) { Emit(os, "true"); } else { Emit(os, "false"); } Emit(os, ", out mteCreated"); Emit(os, ");\n"); if (!registerMethod.empty()) { if (this->MethodReturnValueIsCounted(c, m)) { EmitIndent(os, indent+1); Emit(os, "// Returned object is counted already, (factory method or iwhCounted hint),\n"); EmitIndent(os, indent+1); Emit(os, "// no 'rv."); Emit(os, registerMethod.c_str()); Emit(os, "' call is necessary...\n"); } else { EmitIndent(os, indent+1); Emit(os, "if (mteCreated)\n"); EmitIndent(os, indent+1); Emit(os, "{\n"); EmitIndent(os, indent+2); Emit(os, "rv."); Emit(os, registerMethod.c_str()); Emit(os, ";\n"); EmitIndent(os, indent+1); Emit(os, "}\n"); } } EmitIndent(os, indent); Emit(os, "}\n"); Emit(os, "\n"); } else if (IsCharPointer(retType)) { Emit(os, ");\n"); } else if (rvType == "bool") { Emit(os, " == 0 ? false : true;\n"); } else { Emit(os, ";\n"); } if (emitExceptionParams) { Emit(os, "\n"); EmitThrowClonedException(os, indent); Emit(os, "\n"); } // Specially marshal array return values: if (retArraySize != "") { EmitIndent(os, indent); Emit(os, rvType.c_str()); Emit(os, "[] rv = null;"); Emit(os, "\n"); EmitIndent(os, indent); Emit(os, "if (IntPtr.Zero != rvp)"); Emit(os, "\n"); EmitIndent(os, indent); Emit(os, "{"); Emit(os, "\n"); EmitIndent(os, indent+1); Emit(os, "rv = new "); Emit(os, rvType.c_str()); Emit(os, "["); Emit(os, retArraySize.c_str()); Emit(os, "];"); Emit(os, "\n"); // Special case "uint" since Marshal.Copy does not have // a "uint" overload... // if (rvType == "uint") { EmitIndent(os, indent+1); Emit(os, "int[] rv2 = new int["); Emit(os, retArraySize.c_str()); Emit(os, "];"); Emit(os, "\n"); EmitIndent(os, indent+1); Emit(os, "Marshal.Copy(rvp, rv2, 0, rv.Length);"); Emit(os, "\n"); EmitIndent(os, indent+1); Emit(os, "for (int rv2i = 0; rv2i < "); Emit(os, retArraySize.c_str()); Emit(os, "; ++rv2i)"); Emit(os, "\n"); EmitIndent(os, indent+1); Emit(os, "{"); Emit(os, "\n"); EmitIndent(os, indent+2); Emit(os, "rv[rv2i] = (uint)rv2[rv2i];"); Emit(os, "\n"); EmitIndent(os, indent+1); Emit(os, "}"); Emit(os, "\n"); } else { EmitIndent(os, indent+1); Emit(os, "Marshal.Copy(rvp, rv, 0, rv.Length);"); Emit(os, "\n"); } EmitIndent(os, indent); Emit(os, "}"); Emit(os, "\n"); } // Return statement: if (!voidReturn) { EmitIndent(os, indent); Emit(os, "return rv;"); Emit(os, "\n"); } } //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpMethod(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, const gxsys_stl::string& accessLevel, bool emitExceptionParams) { gxsys_stl::string f(GetExportLayerFunctionName(c, m, mname)); // First declare the DllImport function. This gets called within the method body. // EmitIndent(os); EmitCSharpDllImportDeclaration(os, dllname, c, m, mname, f.c_str(), emitExceptionParams); Emit(os, "\n"); Emit(os, "\n"); // Documentation: gxsys_stl::vector docblock; this->GetHeaderFileReader(c)->GetCommentBlockBefore(m->GetLine(), docblock, this->ClassLineNumber); EmitDocumentationBlock(os, docblock, 1); // Declaration: EmitIndent(os); EmitCSharpMethodDeclaration(os, c, m, false, false, accessLevel); Emit(os, "\n"); // Open body: EmitIndent(os); Emit(os, "{"); Emit(os, "\n"); // Body: EmitCSharpMethodBody(os, 2, c, m, f, 0, emitExceptionParams); // Close body: EmitIndent(os); Emit(os, "}"); Emit(os, "\n"); } //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpEnums(gxsys_ios::ostream &os, const cable::Class *c) { gxsys_stl::vector docblock; for (cable::Context::Iterator it = c->Begin(); it != c->End(); ++it) { cable::Enumeration *e = cable::Enumeration::SafeDownCast(*it); if (e && (cable::Context::Public == it.GetAccess())) { gxsys_stl::string ename(GetWrappedEnumName(e)); LogVerboseInfo(<< "public enum - wrapped name: " << ename); Emit(os, "\n"); Emit(os, "\n"); docblock.clear(); this->GetHeaderFileReader(c)->GetCommentBlockBefore(e->GetLine(), docblock, this->ClassLineNumber); EmitDocumentationBlock(os, docblock, 1); EmitIndent(os); Emit(os, "public "); if (WrappedEnumExists(ename)) { Emit(os, "new "); } Emit(os, "enum "); Emit(os, ename.c_str()); Emit(os, "\n"); EmitIndent(os); Emit(os, "{\n"); for (cable::Enumeration::Iterator eit = e->Begin(); eit != e->End(); ++eit) { EmitIndent(os, 2); Emit(os, "/// enum member\n"); EmitIndent(os, 2); Emit(os, *eit); Emit(os, " = "); EmitInt(os, eit.GetValue()); Emit(os, ","); Emit(os, "\n"); Emit(os, "\n"); } EmitIndent(os); Emit(os, "}\n"); } } } //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpConstructor(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, bool emitExceptionParams) { // need qualified name? gxsys_stl::string cname(c->GetName()); gxsys_stl::string f; if (this->GetSettings()->GetUseShadow(c)) { // Special case shadow class factory method since m might be NULL // (like it *is* with vtkCommand...) // f = cname + "Shadow_CreateShadow"; EmitIndent(os); Emit(os, "[DllImport("); Emit(os, dllname); Emit(os, ", EntryPoint = \""); Emit(os, f.c_str()); Emit(os, "\")]"); Emit(os, "\n"); EmitIndent(os); Emit(os, "static extern IntPtr "); Emit(os, f.c_str()); Emit(os, "(IntPtr primary);\n"); Emit(os, "\n"); // Documentation: gxsys_stl::vector docblock; this->GetHeaderFileReader(c)->GetCommentBlockBefore( (m ? m->GetLine() : c->GetLine()), docblock, this->ClassLineNumber); EmitDocumentationBlock(os, docblock, 1); EmitIndent(os); Emit(os, "public "); Emit(os, cname.c_str()); Emit(os, "() : this(IntPtr.Zero, false, false)\n"); EmitIndent(os); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, "IntPtr primary = Marshal.GetIDispatchForObject(this);\n"); EmitIndent(os, 2); Emit(os, "this.SetCppThis("); Emit(os, f.c_str()); Emit(os, "(primary), true, false);\n"); EmitIndent(os, 2); Emit(os, "Marshal.Release(primary);\n"); EmitIndent(os); Emit(os, "}\n"); } else { f = GetExportLayerFunctionName(c, m, mname); // Explanation of the "emitDefaultFactoryMethod" MummySettings.xml attribute. // ========================================================================== // // Either: emit the factory method itself, including the DllImport declaration, // and then emit the default C# constructor, too, which gives two ways to get an // instance of an object of class c... // (emitDefaultFactoryMethod="true" in MummySettings.xml) // // Or: emit just the DllImport declaration and the default C# constructor and // *skip* emitting the factory method itself, which only gives one way to get an // instance of class c. // (emitDefaultFactoryMethod="false" in or absent from MummySettings.xml) // // We code for both ways because we have some clients who want abstract C# classes // to be really abstract and *uncreatable* (even via a separate factory method) at // this class level. Only concrete subclasses can even be instantiated. // // On the other hand, we also have clients (think VTK and its ubiquitous New method) // that want the factory method behavior specifically so that abstract class instances // *can* be created, even though behind the scenes a concrete subclass of the factory // method's choice is the thing actually being instantiated. // if (this->GetSettings()->GetEmitDefaultFactoryMethod(c)) { EmitCSharpMethod(os, dllname, c, m, mname, "public", emitExceptionParams); } else { EmitIndent(os); EmitCSharpDllImportDeclaration(os, dllname, c, m, mname, f.c_str(), emitExceptionParams); } Emit(os, "\n"); Emit(os, "\n"); // Documentation: gxsys_stl::vector docblock; this->GetHeaderFileReader(c)->GetCommentBlockBefore(m->GetLine(), docblock, this->ClassLineNumber); EmitDocumentationBlock(os, docblock, 1); EmitIndent(os); Emit(os, "public "); Emit(os, cname.c_str()); Emit(os, "()\n"); EmitIndent(os, 2); Emit(os, ": base(IntPtr.Zero, false, false)\n"); EmitIndent(os); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, "// mummy generated default C# constructor\n"); EmitIndent(os, 2); Emit(os, "uint mteStatus = 0;\n"); EmitIndent(os, 2); Emit(os, "uint mteIndex = UInt32.MaxValue;\n"); EmitIndent(os, 2); Emit(os, "uint rawRefCount = 0;\n"); Emit(os, "\n"); if (emitExceptionParams) { EmitIndent(os, 2); Emit(os, "uint mteExceptionIndex = UInt32.MaxValue;\n"); EmitIndent(os, 2); Emit(os, "IntPtr clonedException = IntPtr.Zero;\n"); Emit(os, "\n"); } EmitIndent(os, 2); Emit(os, "IntPtr rawCppThis = "); Emit(os, f.c_str()); Emit(os, "(ref mteStatus, ref mteIndex, ref rawRefCount"); if (emitExceptionParams) { Emit(os, ", ref mteExceptionIndex, ref clonedException"); } Emit(os, ");\n"); if (emitExceptionParams) { Emit(os, "\n"); EmitThrowClonedException(os, 2); Emit(os, "\n"); } EmitIndent(os, 2); Emit(os, "this.SetCppThis(rawCppThis, true, (0==mteStatus || rawRefCount<2 ? false : true));\n"); EmitIndent(os); Emit(os, "}\n"); } } //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpRegister(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, bool emitExceptionParams) { EmitCSharpMethod(os, dllname, c, m, mname, "public", emitExceptionParams); } //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpDispose(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, const unsigned int eventCount, bool emitExceptionParams) { cable::FunctionType *ft = 0; cable::Type *argType = 0; unsigned int cArgs = 0; unsigned int i = 0; gxsys_stl::string f; if (m) { ft = m->GetFunctionType(); cArgs = ft->GetNumberOfArguments(); // need qualified name? f = GetExportLayerFunctionName(c, m, mname); EmitIndent(os); EmitCSharpDllImportDeclaration(os, dllname, c, m, mname, f.c_str(), emitExceptionParams); Emit(os, "\n"); Emit(os, "\n"); // Documentation: gxsys_stl::vector docblock; this->GetHeaderFileReader(c)->GetCommentBlockBefore(m->GetLine(), docblock, this->ClassLineNumber); EmitDocumentationBlock(os, docblock, 1); } else { EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "/// Automatically generated protected Dispose method - called from\n"); EmitIndent(os); Emit(os, "/// public Dispose or the C# destructor. DO NOT call directly.\n"); EmitIndent(os); Emit(os, "/// \n"); } EmitIndent(os); Emit(os, "protected override void Dispose(bool disposing)\n"); EmitIndent(os); Emit(os, "{\n"); // If we are going to emit any code other than "base.Dispose(disposing);" // then make sure it is wrapped in a try/finally block so that we still call // base.Dispose if one of these other bits of code we're calling throws // an exception... // bool openedTryFinally = false; unsigned int indent = 2; if ((0 != eventCount) || m) { openedTryFinally = true; indent = 3; EmitIndent(os, indent-1); Emit(os, "try\n"); EmitIndent(os, indent-1); Emit(os, "{\n"); } if (0 != eventCount) { EmitIndent(os, indent); Emit(os, "this.RemoveAllRelayHandlers();\n"); } if (m) { EmitIndent(os, indent); Emit(os, "if (this.GetCallDisposalMethod())\n"); EmitIndent(os, indent); Emit(os, "{\n"); if (emitExceptionParams) { EmitIndent(os, indent+1); Emit(os, "uint mteExceptionIndex = 0;\n"); EmitIndent(os, indent+1); Emit(os, "IntPtr clonedException = IntPtr.Zero;\n"); Emit(os, "\n"); } EmitIndent(os, indent+1); Emit(os, f.c_str()); Emit(os, "(this.GetCppThis()"); for (i = 0; iGetArgument(i); if (IsObjectPointer(argType)) { Emit(os, ", new HandleRef()"); } else if (IsVoidPointer(argType)) { Emit(os, ", System.IntPtr.Zero"); } else { Emit(os, ", 0"); } } if (emitExceptionParams) { Emit(os, ", ref mteExceptionIndex, ref clonedException"); } Emit(os, ");\n"); EmitIndent(os, indent+1); Emit(os, "this.ClearCppThis();\n"); if (emitExceptionParams) { Emit(os, "\n"); EmitThrowClonedException(os, indent+1); } EmitIndent(os, indent); Emit(os, "}\n"); Emit(os, "\n"); } if (openedTryFinally) { EmitIndent(os, indent-1); Emit(os, "}\n"); EmitIndent(os, indent-1); Emit(os, "finally\n"); EmitIndent(os, indent-1); Emit(os, "{\n"); } EmitIndent(os, indent); Emit(os, "base.Dispose(disposing);\n"); if (openedTryFinally) { EmitIndent(os, indent-1); Emit(os, "}\n"); } EmitIndent(os); Emit(os, "}\n"); } //---------------------------------------------------------------------------- struct SortByFieldOffset { bool operator()(const cable::Field* f1, const cable::Field* f2) { return f1->GetOffset() < f2->GetOffset(); } }; //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpWrapperClassAsStruct(gxsys_ios::ostream &os, const cable::Class *c) { gxsys_stl::vector fields; gxsys_stl::vector::iterator fit; gxsys_stl::string derivedName; gxsys_stl::string fieldType; gxsys_stl::vector docblock; bool isPartial = this->GetSettings()->GetPartialClass(c); bool fieldAccess = !HasAttribute(c, "gccxml(iwhNoFieldAccess)"); // First iterate and collect all the fields in a local vector: // for (cable::Context::Iterator it = c->Begin(); it != c->End(); ++it) { cable::Field* f = cable::Field::SafeDownCast(*it); if (f) { fields.push_back(f); } } // Sort the vector so that we can emit the fields in the same order // in which they appear in the original C++ struct/class: // gxsys_stl::sort(fields.begin(), fields.end(), SortByFieldOffset()); // Emit class opening: // Emit(os, "public "); if (isPartial) { Emit(os, "partial "); } Emit(os, "struct "); Emit(os, GetWrappedClassName(c).c_str()); Emit(os, "\n"); Emit(os, "{\n"); // Enums: // EmitCSharpEnums(os, c); // Now iterate and emit a private data member for each field: // for (fit = fields.begin(); fit != fields.end(); ++fit) { cable::Field* f = *fit; if (f) { derivedName = ExtractDerivedName(f->GetName(), f, this->GetSettings()->GetVerbose()); fieldType = GetCSharpTypeString(f->GetType(), false, false); // "bool" is special - help it marshal properly to a C++ bool struct // data member... // // Using C# bool here causes an InteropServices.MarshalDirectiveException // with a message that says the type cannot be marshalled via PInvoke. // So we use C# byte instead and make it look like a bool through the // public accessors emitted in the next step. // if (fieldType == "bool") { fieldType = "byte"; } EmitIndent(os); Emit(os, "private "); Emit(os, fieldType.c_str()); Emit(os, " m_"); Emit(os, derivedName.c_str()); Emit(os, ";"); Emit(os, "\n"); } } // Iterate and emit public accessors for each private data member: // for (fit = fields.begin(); fieldAccess && fit != fields.end(); ++fit) { cable::Field* f = *fit; if (f) { derivedName = ExtractDerivedName(f->GetName(), f, false); fieldType = GetCSharpTypeString(f->GetType(), false, false); Emit(os, "\n"); this->GetHeaderFileReader(c)->GetCommentBlockBefore(f->GetLine(), docblock, this->ClassLineNumber); EmitDocumentationBlock(os, docblock, 1); docblock.clear(); EmitIndent(os); Emit(os, "public "); Emit(os, fieldType.c_str()); Emit(os, " "); Emit(os, derivedName.c_str()); Emit(os, "\n"); EmitIndent(os); Emit(os, "{"); Emit(os, "\n"); EmitIndent(os, 2); Emit(os, "get\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 3); Emit(os, "return this.m_"); Emit(os, derivedName.c_str()); if (fieldType == "bool") { // "bool" is special -- see above comments... // Emit(os, " == 0 ? false : true"); } Emit(os, ";\n"); EmitIndent(os, 2); Emit(os, "}\n"); Emit(os, "\n"); EmitIndent(os, 2); Emit(os, "set\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 3); Emit(os, "this.m_"); Emit(os, derivedName.c_str()); Emit(os, " = "); if (fieldType == "bool") { // "bool" is special -- see above comments... // Emit(os, "(byte)(value ? 1 : 0)"); } else { Emit(os, "value"); } Emit(os, ";\n"); EmitIndent(os, 2); Emit(os, "}\n"); EmitIndent(os); Emit(os, "}"); Emit(os, "\n"); } } // Caller emits closing brace for struct so that he can emit // extraCSharpCode if necessary before the closing brace... } //---------------------------------------------------------------------------- void MummyCsharpGenerator::GatherWrappedMethods( const cable::Class *c, gxsys_stl::vector& wrapped_methods, cable::Method*& factoryM, cable::Method*& disposalM, cable::Method*& registerM, cable::Method*& unRegisterM, bool includeParentMethods ) { // When recursion hits the top of the class hierarchy, we're done: // if (!c) { return; } gxsys_stl::string factoryMethod(this->GetSettings()->GetFactoryMethod(c)); gxsys_stl::string disposalMethod(this->GetSettings()->GetDisposalMethod(c)); gxsys_stl::string registerMethod(this->GetSettings()->GetRegisterMethod(c)); gxsys_stl::string unRegisterMethod(this->GetSettings()->GetUnRegisterMethod(c)); // Reset state only if we are iterating the methods of the *target* class. // (And only track factory method if iterating the target class...) // if (c == this->GetTargetClass()) { this->CurrentMethodId = 0; this->MethodIdMap.clear(); WrappedMethods.clear(); wrapped_methods.clear(); factoryM = 0; disposalM = 0; registerM = 0; unRegisterM = 0; } // If including parents, do so first so that the list of methods is in // "superclass first" order... And so that tracked pointers get set // to the most derived override possible. // if (includeParentMethods) { this->GatherWrappedMethods(GetWrappableParentClass(c), wrapped_methods, factoryM, disposalM, registerM, unRegisterM, true); } // Iterate class c's methods, adding wrappable ones to wrapped_methods and // tracking "special" methods as we encounter them: // for (cable::Context::Iterator it = c->Begin(); it != c->End(); ++it) { cable::Method *m = cable::Method::SafeDownCast(*it); if (m && MethodIsWrappable(m, it.GetAccess())) { gxsys_stl::string signature(GetMethodSignature(c, m)); if ((c == this->GetTargetClass()) && signature == factoryMethod + "()") { LogVerboseInfo(<< "Found factory method, signature: " << signature); factoryM = m; this->MethodIdMap.insert(gxsys_stl::make_pair(m, ++this->CurrentMethodId)); } else if (signature == disposalMethod + "()") { LogVerboseInfo(<< "Found disposal method, signature: " << signature); disposalM = m; this->MethodIdMap.insert(gxsys_stl::make_pair(m, ++this->CurrentMethodId)); } else if (gxsys::SystemTools::StringStartsWith(registerMethod.c_str(), (gxsys_stl::string(m->GetName())+"(").c_str())) { LogVerboseInfo(<< "Found register method, signature: " << signature); registerM = m; this->MethodIdMap.insert(gxsys_stl::make_pair(m, ++this->CurrentMethodId)); } else if (gxsys::SystemTools::StringStartsWith(unRegisterMethod.c_str(), (gxsys_stl::string(m->GetName())+"(").c_str())) { LogVerboseInfo(<< "Found unregister method, signature: " << signature); unRegisterM = m; this->MethodIdMap.insert(gxsys_stl::make_pair(m, ++this->CurrentMethodId)); } else if (!WrappedMethodExists(signature)) { WrappedMethods.insert(gxsys_stl::make_pair(signature, MethodInstance(c, m))); wrapped_methods.push_back(m); this->MethodIdMap.insert(gxsys_stl::make_pair(m, ++this->CurrentMethodId)); } else { if (this->GetSettings()->GetVerbose()) { //Emit(os, "//WARNING: "); //Emit(os, GetAccessString(it.GetAccess())); //Emit(os, " "); //Emit(os, (*it)->GetNameOfClass()); //Emit(os, " '"); //Emit(os, (*it)->GetName()); //Emit(os, "' wrappable method *NOT WRAPPED* because its signature matches a method that was already wrapped...\n"); } } } if (this->GetSettings()->GetVerbose()) { if (!m) { LogInfo(mi_VerboseInfo, << GetAccessString(it.GetAccess()) << " " << (*it)->GetNameOfClass() << " '" << (*it)->GetName() << "' not wrapped because it's not a method...\n" ); } } } } //---------------------------------------------------------------------------- struct SortByMethodDeclarationLineNumber { bool operator()(const cable::Method* m1, const cable::Method* m2) { return m1->GetLine() < m2->GetLine(); } }; //---------------------------------------------------------------------------- bool MummyCsharpGenerator::ValidateWrappedMethods( const cable::Class *, gxsys_stl::vector& wrapped_methods, cable::Method*&, cable::Method*&, cable::Method*&, cable::Method*& ) { bool valid = true; gxsys_stl::vector wrapped_methods_local; gxsys_stl::vector::iterator mit; cable::Method* m = 0; gxsys::RegularExpression reGet; gxsys::RegularExpression reSet; reGet.compile("^[Gg]et"); reSet.compile("^[Ss]et"); // Make a local copy of the wrapped_methods vector so we can sort it by // "method declaration line number"... // gxsys_stl::copy(wrapped_methods.begin(), wrapped_methods.end(), gxsys_stl::back_inserter(wrapped_methods_local)); // Sort the vector so that we can emit the fields in the same order // in which they appear in the original C++ struct/class: // gxsys_stl::sort(wrapped_methods_local.begin(), wrapped_methods_local.end(), SortByMethodDeclarationLineNumber()); for (mit = wrapped_methods_local.begin(); mit != wrapped_methods_local.end(); ++mit) { m = *mit; cable::FunctionType *ft = m->GetFunctionType(); unsigned int cArgs = ft->GetNumberOfArguments(); unsigned int cReqArgs = ft->GetNumberOfRequiredArguments(); cable::Type *retType = ft->GetReturns(); bool voidReturn = false; bool iwhPropGetExempt = false; if (IsVoid(retType)) { voidReturn = true; } if (cArgs != cReqArgs) { // Method has at least one default arg... Warn that mummy is ignoring // any default argument values... // LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_DefaultArgumentValuesIgnored, "ignoring default argument values for method '" << m->GetName() << "'."); } if (reGet.find(m->GetName())) { // // It's a "getter" : warn if it returns "void" or if it's not a const // method or if it's missing the iwhPropGet hint... // if (gxsys_stl::string("GetEnumerator") == m->GetName()) { iwhPropGetExempt = true; } // The mw_PropGetReturnsVoid and mw_PropGetHasArgs warnings are based on // the desire that a simple getter method should return one and only one // thing by return value, not through one or more "byref" arguments... // if (voidReturn) { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_PropGetReturnsVoid, "'Getter' method '" << m->GetName() << "' returns void."); } if (cArgs) { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_PropGetHasArgs, "'Getter' method '" << m->GetName() << "' has arguments. Should it?"); } if (!iwhPropGetExempt && !HasAttribute(m, "gccxml(iwhPropGet)")) { if (!voidReturn && 0==cArgs) { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_SeriousMissingPropGetHint, "'Getter' method '" << m->GetName() << "' is a perfect candidate for the 'iwhPropGet' hint. Add the 'iwhPropGet' hint to eliminate this warning."); } else { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_MissingPropGetHint, "'Getter' method '" << m->GetName() << "' does not have the 'iwhPropGet' hint. Should it?"); } } if (!m->GetConst() && !m->GetStatic()) { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_PropGetNotConst, "'Getter' method '" << m->GetName() << "' is not const. Should it be const?"); } } if (reSet.find(m->GetName())) { // It's a "setter" : warn if it's missing the iwhPropSet hint: // if (!HasAttribute(m, "gccxml(iwhPropSet)")) { if (voidReturn && 1==cArgs) { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_SeriousMissingPropSetHint, "'Setter' method '" << m->GetName() << "' is a perfect candidate for the 'iwhPropSet' hint. Add the 'iwhPropSet' hint to eliminate this warning."); } else { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_MissingPropSetHint, "'Setter' method '" << m->GetName() << "' does not have the 'iwhPropSet' hint. Should it?"); } } if (cArgs!=1) { LogFileLineWarningMsg(m->GetFile(), m->GetLine(), mw_PropSetUnexpectedArgCount, "'Setter' method '" << m->GetName() << "' has " << cArgs << " arguments. Should it have exactly one argument instead?"); } } } return valid; } //---------------------------------------------------------------------------- void MummyCsharpGenerator::BuildPropGetsAndSetsMap( gxsys_stl::vector& wrapped_methods, gxsys_stl::map >& wrapped_properties ) { gxsys_stl::vector::iterator mit; gxsys_stl::map >::iterator gsit; bool addingPropGet = false; bool addingPropSet = false; cable::Method* propGetMethod = 0; cable::Method* propSetMethod = 0; gxsys_stl::string propName; for (mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { addingPropGet = HasAttribute(*mit, "gccxml(iwhPropGet)"); addingPropSet = addingPropGet ? false : HasAttribute(*mit, "gccxml(iwhPropSet)"); if (addingPropGet || addingPropSet) { if (addingPropGet) { propGetMethod = *mit; } else { propGetMethod = 0; } if (addingPropSet) { propSetMethod = *mit; } else { propSetMethod = 0; } propName = ExtractDerivedName(GetWrappedMethodName(*mit).c_str(), *mit, this->GetSettings()->GetVerbose()); gsit = wrapped_properties.find(propName); if (gsit == wrapped_properties.end()) { // propName not in our map yet, add it: // wrapped_properties.insert(gxsys_stl::make_pair(propName, gxsys_stl::make_pair(propGetMethod, propSetMethod))); } else { // We already have an entry for propName... // This should be the "other" half of the pair. // So, if we are adding the *get*, then save the // existing "set" that's already in the map and // vice versa. // if (addingPropGet) { propSetMethod = gsit->second.second; } if (addingPropSet) { propGetMethod = gsit->second.first; } // The iterator points to the real map entry. Just // overwrite it: // gsit->second = gxsys_stl::make_pair(propGetMethod, propSetMethod); } } } // Analyze wrapped_properties and report anything suspicious. // Or just report info if verbose... // bool verbose = this->GetSettings()->GetVerbose(); if (!wrapped_properties.empty()) { gxsys_stl::string comment; if (verbose) { LogInfo(mi_VerboseInfo, << "Properties:"); } for (gsit = wrapped_properties.begin(); gsit != wrapped_properties.end(); ++gsit) { if (gsit->second.first!=0 && gsit->second.second!=0) { comment = "ReadWrite property."; } else if (gsit->second.first!=0) { comment = "ReadOnly property."; } else if (gsit->second.second!=0) { LogFileLineWarningMsg(gsit->second.second->GetFile(), gsit->second.second->GetLine(), mw_WriteOnlyProperty, "A WriteOnly property '" << gsit->first << "' is very unusual - did you forget to mark the 'Get' method with 'iwhPropGet'?"); } else { LogError(me_InternalError, "Property with no 'get' and no 'set'... Impossible!"); } if (verbose) { LogInfo(mi_VerboseInfo, << comment << " propName: " << gsit->first << " propGetMethod: " << gsit->second.first << " propSetMethod: " << gsit->second.second ); } } } } //---------------------------------------------------------------------------- void MummyCsharpGenerator::EmitCSharpWrapperClass(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c) { // Gather wrapped elements: // gxsys_stl::vector wrapped_methods; gxsys_stl::vector::iterator mit; cable::Method *factoryM = 0; cable::Method *disposalM = 0; cable::Method *registerM = 0; cable::Method *unRegisterM = 0; bool verbose = this->GetSettings()->GetVerbose(); gxsys_stl::string atts(c->GetAttributes()); gxsys_stl::string mname; // The "package" directive from the gccxml input is used as a base // namespace. If it's not empty, prepend it to the class's namespace. // gxsys_stl::string target_namespace; gxsys_stl::string base_namespace(this->GetSettings()->GetPackage()); gxsys_stl::string class_namespace(GetFullyQualifiedNameForCSharp(c->GetContext())); // C++ global scope means "no namespace please" // if (class_namespace == "::") { class_namespace = ""; } if (base_namespace == "") { target_namespace = class_namespace; } else if (class_namespace == "") { target_namespace = base_namespace; } else { target_namespace = base_namespace + "." + class_namespace; } // Emit code: // EmitMummyVersionComments(os, "//"); // If the class maps directly to a builtin type, then DO NOT emit any code. // gxsys_stl::string mapToType = ExtractMapToType(c); if (mapToType != "") { Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "// Unmanaged class '"); Emit(os, GetFullyQualifiedNameForCPlusPlus(c).c_str()); Emit(os, "' maps directly to type '"); Emit(os, mapToType.c_str()); Emit(os, "'.\n"); Emit(os, "// No code generated for '"); Emit(os, GetFullyQualifiedNameForCPlusPlus(c).c_str()); Emit(os, "'...\n"); if (verbose) { LogInfo(mi_VerboseInfo, << "Skipping code generation because class maps directly to native type."); } return; } Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "using System;\n"); Emit(os, "using System.Runtime.InteropServices; // DllImport and HandleRef both live here\n"); Emit(os, "\n"); // If this project depends on "using" any other C# namespaces, they will be listed // as "Reference" elements in MummySettings.xml... // gxsys_stl::vector refs; this->GetSettings()->GetReferences(refs); if (refs.size()) { Emit(os, "// References\n"); gxsys_stl::vector::iterator rit; for (rit = refs.begin(); rit != refs.end(); ++rit) { Emit(os, "using "); Emit(os, rit->c_str()); Emit(os, ";\n"); } Emit(os, "\n"); } // Open the (optional) namespace: // if (target_namespace != "") { Emit(os, "namespace "); Emit(os, target_namespace.c_str()); Emit(os, "\n"); Emit(os, "{\n"); Emit(os, "\n"); } // Documentation: // gxsys_stl::vector docblock; this->ClassLineNumber = c->GetLine(); if (gxsys::SystemTools::StringStartsWith(GetFullyQualifiedNameForCPlusPlus(c).c_str(), "vtk")) { this->GetHeaderFileReader(c)->GetFirstCommentBlock(docblock); } else { this->GetHeaderFileReader(c)->GetCommentBlockBefore(c->GetLine(), docblock, 1); } EmitDocumentationBlock(os, docblock, 0, true); if (IsUtilityClass(c)) { // Verify no virtual methods... If any, emit error: // cable::Method* um = 0; bool bVirtual = false; for (cable::Context::Iterator umit = c->Begin(); !bVirtual && umit != c->End(); ++umit) { um = cable::Method::SafeDownCast(*umit); if (um && um->GetVirtual()) { bVirtual = true; } } if (bVirtual) { LogFileLineErrorMsg(um->GetFile(), um->GetLine(), me_NoVirtualMethodsAllowed, "A utility class cannot have any virtual methods. The '" << um->GetName() << "' method should not be virtual."); return; } // Utility classes get wrapped as structs: // EmitCSharpWrapperClassAsStruct(os, c); } else { if (verbose) { LogInfo(mi_VerboseInfo, << "Calling GatherWrappedMethods..."); } this->GatherWrappedMethods(c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM, false); if (verbose) { DumpLookupEntries(); } this->ValidateWrappedMethods(c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM); // Filter out prop gets and sets, putting them in their very own data structure. // Key in the map is the name of the property. 1st method in pair is propget, // 2nd method is propset. // gxsys_stl::map > wrapped_properties; this->BuildPropGetsAndSetsMap(wrapped_methods, wrapped_properties); // Now remove any entries found in the props *map* from the methods *vector*. // Otherwise, we'd end up with all of the properties "repeated" as methods, too. // gxsys_stl::map >::iterator gsit; for (gsit = wrapped_properties.begin(); gsit != wrapped_properties.end(); ++gsit) { if (gsit->second.first) { mit = gxsys_stl::find(wrapped_methods.begin(), wrapped_methods.end(), gsit->second.first); if (mit != wrapped_methods.end()) { wrapped_methods.erase(mit); } else { LogWarning(mw_InternalWarning, << "Unexpected unfound propget method..."); } } if (gsit->second.second) { mit = gxsys_stl::find(wrapped_methods.begin(), wrapped_methods.end(), gsit->second.second); if (mit != wrapped_methods.end()) { wrapped_methods.erase(mit); } else { LogWarning(mw_InternalWarning, << "Unexpected unfound propset method..."); } } } ClassWrappingSettings cws; if (!this->GetSettings()->FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { LogError(me_NoClassWrappingSettings, << "error: no ClassWrappingSettings for class " << GetFullyQualifiedNameForCPlusPlus(c).c_str()); } const cable::Class *parent = GetWrappableParentClass(c); bool isPartial = cws.partialClass; bool emitExceptionParams = !cws.exceptionBaseClass.empty(); // Class declaration: // Emit(os, "public "); if (c->GetAbstract()) { Emit(os, "abstract "); } if (isPartial) { Emit(os, "partial "); } Emit(os, "class "); Emit(os, GetWrappedClassName(c).c_str()); Emit(os, " : "); if (parent) { Emit(os, GetWrappedClassNameFullyQualified(parent).c_str()); } else { gxsys_stl::string wrappedObjectBase(cws.wrappedObjectBase); if (wrappedObjectBase.empty()) { wrappedObjectBase = "Kitware.mummy.Runtime.WrappedObject"; } Emit(os, wrappedObjectBase.c_str()); } // Any interface(s)? david.cole::fix - allow potentially many interfaces, // extract a list here if necessary rather than just one string... // gxsys_stl::string iface(ExtractImplementsInterface(atts)); if (!iface.empty()) { if (iface == "IEnumerable") { this->AddTargetInterface(iface); Emit(os, ", System.Collections.IEnumerable"); } else if (iface == "IEnumerator") { this->AddTargetInterface(iface); Emit(os, ", System.Collections.IEnumerator"); } else { this->AddTargetInterface(iface); Emit(os, ", "); Emit(os, iface.c_str()); } } Emit(os, "\n"); // Open class: // Emit(os, "{\n"); // david.cole::fix - GetFullyQualifiedNameForCSharp should handle // target_namespace being set in the gccxml input file, but it currently // does not. It relies on exact mapping of the C++ namespaces, which does // not allow for "pushing" stuff in the global C++ namespace into a C# // namespace as we do in the Vehicles example and Kitware.VTK wrappers... // gxsys_stl::string fullCSharpName; if (target_namespace != "") { fullCSharpName = target_namespace + "." + GetWrappedClassName(c); } else { fullCSharpName = GetWrappedClassName(c); } // Register type info with the mummy.Runtime for *all* classes, // even abstract classes. Type registration needs to occur even // if the first call to the dll is a static method on an abstract // class (which forces the static constructor to run prior to // entering the static method...) // EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "/// Automatically generated type registration mechanics.\n"); EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "public new static readonly string MRClassNameKey = \""); Emit(os, GetFullyQualifiedCPlusPlusTypeIdName(c).c_str()); Emit(os, "\";\n"); Emit(os, "\n"); EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "/// Automatically generated type registration mechanics.\n"); EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "public new const string MRFullTypeName = \""); Emit(os, fullCSharpName.c_str()); Emit(os, "\";\n"); Emit(os, "\n"); EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "/// Automatically generated type registration mechanics.\n"); EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "static "); Emit(os, GetWrappedClassName(c).c_str()); Emit(os, "()\n"); EmitIndent(os); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, "Kitware.mummy.Runtime.Methods.RegisterType(\n"); EmitIndent(os, 3); Emit(os, "System.Reflection.Assembly.GetExecutingAssembly(),\n"); EmitIndent(os, 3); Emit(os, "MRClassNameKey,\n"); EmitIndent(os, 3); Emit(os, "System.Type.GetType(MRFullTypeName)\n"); EmitIndent(os, 3); Emit(os, ");\n"); EmitIndent(os); Emit(os, "}\n"); Emit(os, "\n"); Emit(os, "\n"); // Count events *now* before EmitCSharpDisposalMethod. // But emit code for the events further below. // // Also, examine the full set of events to be generated for this class. // For any duplicate names, use GetQualifiedEventName instead of // GetEventName in the methodEventNames map. // unsigned int eventCount = 0; gxsys_stl::map event_name_counter; gxsys_stl::map methodEventNames; gxsys_stl::string eventName; // Count events and fill in event_name_counter as we go: // for (mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { if (MethodWrappableAsEvent(*mit, cable::Context::Public)) { ++eventCount; eventName = GetEventName(*mit); event_name_counter[eventName]++; } } // Use event_name_counter to build a map of cable::Method* to event names. // If a method's GetEventName is a duplicate according to event_name_counter // then use GetQualifiedEventName for that method's event name... With this // data, we can simply look up the proper event name when given the // cable::Method* later when we are calling EmitCSharpEvent. // for (mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { if (MethodWrappableAsEvent(*mit, cable::Context::Public)) { eventName = GetEventName(*mit); if (1 == event_name_counter[eventName]) { methodEventNames[*mit] = eventName; } else { methodEventNames[*mit] = GetQualifiedEventName(*mit); } } } // Now verify that we have non-duplicate event names. Reset event_name_counter // and this time analyze whether there are duplicate strings within the // methodEventNames map. // gxsys_stl::map::iterator menIt; event_name_counter.clear(); for (mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { if (MethodWrappableAsEvent(*mit, cable::Context::Public)) { menIt = methodEventNames.find(*mit); if (menIt != methodEventNames.end()) { eventName = menIt->second; event_name_counter[eventName]++; if (event_name_counter[eventName] > 1) { LogFileLineWarningMsg((*mit)->GetFile(), (*mit)->GetLine(), mw_DuplicateGeneratedName, << "duplicate event name found: " << eventName.c_str() << " (a C# compile error will likely follow...)" ); } } else { LogFileLineErrorMsg((*mit)->GetFile(), (*mit)->GetLine(), me_InternalError, << "event method not found in methodEventNames map..."); } } } // Constructor(s): // gxsys_stl::string ctorModifier(this->GetSettings()->GetCsharpConstructorModifier(c)); if (ctorModifier.empty()) { ctorModifier = "public"; } EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "/// Automatically generated constructor - called from generated code.\n"); EmitIndent(os); Emit(os, "/// DO NOT call directly.\n"); EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, ctorModifier.c_str()); Emit(os, " "); Emit(os, GetWrappedClassName(c).c_str()); Emit(os, "(IntPtr rawCppThis, bool callDisposalMethod, bool strong) :\n"); EmitIndent(os, 2); Emit(os, "base(rawCppThis, callDisposalMethod, strong)\n"); EmitIndent(os); Emit(os, "{\n"); EmitIndent(os); Emit(os, "}\n"); // Factory method: // const cable::Method* fmp = 0; gxsys_stl::string factoryMethod = this->GetSettings()->GetFactoryMethod(c); const cable::Constructor* ctor = FindNonAbstractPublicDefaultConstructor(c); if (!factoryMethod.empty() && factoryMethod!="new") { if (factoryM) { fmp = factoryM; mname = fmp->GetName(); } } else { fmp = ctor; mname = "new"; } if (fmp || this->GetSettings()->GetUseShadow(c)) { Emit(os, "\n"); Emit(os, "\n"); EmitCSharpConstructor(os, dllname, c, fmp, mname, emitExceptionParams); } // Register method: // if (registerM) { mname = registerM->GetName(); Emit(os, "\n"); Emit(os, "\n"); EmitCSharpRegister(os, dllname, c, registerM, mname, emitExceptionParams); } // Disposal method: // // (disposalM/unRegisterM may be NULL, but we always emit a Dispose... // the guts of it vary based on disposalM/unRegisterM, but it's always // there and can be used as a cleaning spot for disconnecting any // outstanding event RelayHandler delegates...) // // If this is a ref-counted class, then use unRegisterM instead of disposalM: // const cable::Method* dmp = 0; gxsys_stl::string disposalMethod = this->GetSettings()->GetDisposalMethod(c); gxsys_stl::string unRegisterMethod = this->GetSettings()->GetUnRegisterMethod(c); if (!unRegisterMethod.empty()) { if (unRegisterM) { dmp = unRegisterM; mname = dmp->GetName(); } } else if (!disposalMethod.empty()) { if (disposalM) { dmp = disposalM; mname = dmp->GetName(); } } else { dmp = ctor; mname = "delete"; } // Call EmitCSharpDispose even if dmp is NULL... // Emit(os, "\n"); Emit(os, "\n"); EmitCSharpDispose(os, dllname, c, dmp, mname, eventCount, emitExceptionParams); // Enums: // EmitCSharpEnums(os, c); // Delegates: // for (cable::Context::Iterator it = c->Begin(); it != c->End(); ++it) { cable::Typedef *t = cable::Typedef::SafeDownCast(*it); if (t && (cable::Context::Public == it.GetAccess())) { bool isDelegate = false; gxsys_stl::string tname(t->GetName()); //isDelegate = HasAttribute(t, "gccxml(iwhDelegate)"); cable::PointerType *pt = cable::PointerType::SafeDownCast(t->GetType()); cable::FunctionType *ft = 0; if (pt) { ft = cable::FunctionType::SafeDownCast(pt->GetTarget()); } if (ft) { isDelegate = true; } if (isDelegate) { Emit(os, "\n"); Emit(os, "\n"); docblock.clear(); this->GetHeaderFileReader(c)->GetCommentBlockBefore(t->GetLine(), docblock, this->ClassLineNumber); EmitDocumentationBlock(os, docblock, 1); EmitIndent(os); Emit(os, "public delegate "); unsigned int cArgs = ft->GetNumberOfArguments(); cable::Type *argType = 0; cable::Type *retType = ft->GetReturns(); // The following chunk is a near-copy of the bottom of // EmitCSharpMethodDeclaration... // // Does method return an array? // gxsys_stl::string arraySize = ""; atts = t->GetAttributes(); if (atts != "") { // Use ExtractArraySize instead of GetMethodArgumentArraySize here. // This is a delegate definition and cannot be in the VTK hints file. // (since the hints file only covers "normal" C++ methods...) // GetMethodArgumentArraySize uses ExtractArraySize internally, and // if there is no inline hint, it then examines the externalHints // file to see if there's a match. In this case, there could be no // match anyhow (as evidenced by the fact that we do not have access // to a cable::Method here...) so simply use ExtractArraySize directly. // Same reasoning applies below with the next use of ExtractArraySize. // arraySize = ExtractArraySize(atts); } // Return type: Emit(os, GetPInvokeTypeString(retType, true, arraySize != "", true).c_str()); if (arraySize != "") { Emit(os, "[]"); } Emit(os, " "); // Use the typedef name: Emit(os, t->GetName()); // Open args: Emit(os, "("); // The C# args: unsigned int i; for (i= 0; iGetArgument(i); // Is arg an array? // arraySize = ""; atts = ft->GetArgumentAttributes(i); if (atts != "") { // See comments above regarding direct use of ExtractArraySize // instead of GetMethodArgumentArraySize. // arraySize = ExtractArraySize(atts); } // arg type: Emit(os, GetPInvokeTypeString(argType, false, arraySize != "", true).c_str()); // array notation: if (arraySize != "") { Emit(os, "[]"); } // arg name: Emit(os, " "); Emit(os, GetArgName(ft, i)); if (i Emit(os, ";\n"); } } } // Events: // if (0 != eventCount) { for (mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { if (MethodWrappableAsEvent(*mit, cable::Context::Public)) { Emit(os, "\n"); Emit(os, "\n"); menIt = methodEventNames.find(*mit); if (menIt != methodEventNames.end()) { eventName = menIt->second; } else { eventName = GetEventName(*mit); LogFileLineErrorMsg((*mit)->GetFile(), (*mit)->GetLine(), me_InternalError, << "event method not found in methodEventNames map..."); } EmitCSharpEvent(os, dllname, c, *mit, eventName); } } // Add a special "disconnect all" method that can be called at Dispose // time so that the unmanaged side does not end up with a stale pointer // to a garbage collected event RelayHandler... // Emit(os, "\n"); Emit(os, "\n"); EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "/// Method to disconnect all RelayHandler event members.\n"); EmitIndent(os); Emit(os, "/// Called automatically from Dispose. DO NOT call directly.\n"); EmitIndent(os); Emit(os, "/// \n"); EmitIndent(os); Emit(os, "private void RemoveAllRelayHandlers()\n"); EmitIndent(os); Emit(os, "{\n"); for (mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { if (MethodWrappableAsEvent(*mit, cable::Context::Public)) { menIt = methodEventNames.find(*mit); if (menIt != methodEventNames.end()) { eventName = menIt->second; } else { eventName = GetEventName(*mit); LogFileLineErrorMsg((*mit)->GetFile(), (*mit)->GetLine(), me_InternalError, << "event method not found in methodEventNames map..."); } EmitIndent(os, 2); Emit(os, "this.Remove"); Emit(os, eventName.c_str()); Emit(os, "RelayHandler();\n"); } } EmitIndent(os); Emit(os, "}\n"); } // Properties: // for (gsit = wrapped_properties.begin(); gsit != wrapped_properties.end(); ++gsit) { Emit(os, "\n"); Emit(os, "\n"); EmitCSharpProperty(os, dllname, c, gsit->second.first, gsit->second.second, emitExceptionParams); } // Plain old methods: // for (mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { Emit(os, "\n"); Emit(os, "\n"); EmitCSharpMethod(os, dllname, c, *mit, (*mit)->GetName(), "public", emitExceptionParams); } } // Hand written shtuff: // // If there is extraCSharpCode, emit it *within* the class definition. // If it's there, it's the name of a file that we are to include in // its entirety... // gxsys_stl::string extraCode = this->GetSettings()->GetExtraCsharpCode(c); if (extraCode != "") { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "// Begin extraCsharpCode\n"); Emit(os, "\n"); EmitFile(os, extraCode.c_str()); Emit(os, "\n"); Emit(os, "// End extraCsharpCode\n"); Emit(os, "\n"); } // Close the struct/class: // Emit(os, "}\n"); // Close the namespace: // if (target_namespace != "") { Emit(os, "\n"); Emit(os, "}\n"); } } mummy-1.0.3/MummyCsharpGenerator.h0000644000175000017500000001437512120621217017022 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyCsharpGenerator.h // // Author(s) : David Cole // // Copyright (C) 2006-2008 Kitware, Inc. //---------------------------------------------------------------------------- #ifndef _MummyCsharpGenerator_h_ #define _MummyCsharpGenerator_h_ #include "MummyGenerator.h" // parent class #include "gxsys/stl/map" #include "gxsys/stl/string" #include "gxsys/stl/vector" class MummyCsharpGenerator : public MummyGenerator { public: MummyCsharpGenerator(); virtual ~MummyCsharpGenerator(); virtual void SetTargetClass(const cable::Class *c); virtual void CacheExternalHints(const gxsys_stl::string& hintsfile); virtual void AddTargetInterface(const gxsys_stl::string& iface); virtual bool HasTargetInterface(const char *iface) const; virtual bool IsKeyword(const char *p); virtual bool IsReservedMethodName(const gxsys_stl::string &name); virtual gxsys_stl::string GetFundamentalTypeString(const cable::Type *t); virtual gxsys_stl::string GetWrappedMethodName(const cable::Method *m); virtual gxsys_stl::string GetMethodArgumentArraySize(const cable::Class *c, const cable::Method *m, const cable::FunctionType *ft, unsigned int i); virtual gxsys_stl::string GetMethodSignature(const cable::Class *c, const cable::Method *m); virtual const char *GetArgName(cable::FunctionType *ftype, unsigned int i); virtual bool GetIsRefArg(const cable::Type *t); virtual gxsys_stl::string GetPInvokeTypeString(const cable::Type *t, bool forReturn, bool isArray, bool forDelegate); virtual gxsys_stl::string GetCSharpTypeString(const cable::Type *t, bool forReturn, bool isArray); virtual void ClearLookupEntries(); virtual void AddLookupEntries(const cable::Class* c); virtual void DumpLookupEntries(); virtual bool OtherMethodRedefined(const gxsys_stl::string &signature); virtual bool StaticMethodRedefined(const gxsys_stl::string &signature); virtual bool VirtualMethodOverridden(const gxsys_stl::string &signature); virtual bool WrappedMethodExists(const gxsys_stl::string &signature); virtual bool WrappedEnumExists(const gxsys_stl::string &name); virtual bool FundamentalTypeIsWrappable(const cable::Type* t); virtual bool TypeIsWrappable(const cable::Type* t); virtual bool FunctionTypeIsWrappable(const cable::FunctionType* ft); virtual bool MethodWrappableAsEvent(const cable::Method* m, const cable::Context::Access& access); virtual bool MethodIsWrappable(const cable::Method* m, const cable::Context::Access& access); virtual bool ClassIsWrappable(const cable::Class* c); virtual const cable::Class* GetWrappableParentClass(const cable::Class *c); virtual bool IsFactoryMethod(const cable::Class *c, const cable::Method *m); virtual bool IsDisposalMethod(const cable::Class *c, const cable::Method *m); virtual bool MethodReturnValueIsCounted(const cable::Class *c, const cable::Method *m); virtual gxsys_stl::string GetExportLayerFunctionName(const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname); virtual void EmitCSharpMethodDeclaration(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method *m, bool asProperty, bool useArg0AsReturn, const gxsys_stl::string& accessLevel); virtual void EmitCSharpDllImportDeclaration(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, const char *f, bool emitExceptionParams); virtual void EmitCSharpProperty(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *propGetMethod, const cable::Method *propSetMethod, bool emitExceptionParams); virtual void EmitCSharpMethodBody(gxsys_ios::ostream &os, unsigned int indent, const cable::Class *c, const cable::Method *m, gxsys_stl::string& f, const char *impliedArg0, bool emitExceptionParams); virtual void EmitCSharpMethod(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, const gxsys_stl::string& accessLevel, bool emitExceptionParams); virtual void EmitCSharpEvent(gxsys_ios::ostream& os, const char *dllname, const cable::Class* c, const cable::Method* m, const gxsys_stl::string& eventName); virtual void EmitCSharpEnums(gxsys_ios::ostream &os, const cable::Class *c); virtual void EmitCSharpConstructor(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, bool emitExceptionParams); virtual void EmitCSharpRegister(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, bool emitExceptionParams); virtual void EmitCSharpDispose(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c, const cable::Method *m, const gxsys_stl::string& mname, const unsigned int eventCount, bool emitExceptionParams); virtual void EmitCSharpWrapperClassAsStruct(gxsys_ios::ostream &os, const cable::Class *c); virtual void GatherWrappedMethods( const cable::Class *c, gxsys_stl::vector& wrapped_methods, cable::Method*& factoryM, cable::Method*& disposalM, cable::Method*& registerM, cable::Method*& unRegisterM, bool includeParentMethods ); virtual bool ValidateWrappedMethods( const cable::Class *c, gxsys_stl::vector& wrapped_methods, cable::Method*& factoryM, cable::Method*& disposalM, cable::Method*& registerM, cable::Method*& unRegisterM ); virtual void BuildPropGetsAndSetsMap( gxsys_stl::vector& wrapped_methods, gxsys_stl::map >& wrapped_properties ); virtual void EmitCSharpWrapperClass(gxsys_ios::ostream &os, const char *dllname, const cable::Class *c); protected: // Provide implementation for inherited pure virtuals: virtual bool GenerateWrappers(); private: unsigned int CurrentMethodId; unsigned int ClassLineNumber; gxsys_stl::map MethodIdMap; gxsys_stl::string TargetInterface; gxsys_stl::map HintsMap; MummyCsharpGenerator(const MummyCsharpGenerator&); //Not implemented MummyCsharpGenerator& operator=(const MummyCsharpGenerator&); //Not implemented }; #endif mummy-1.0.3/MummyCsharpShadowLayerGenerator.cxx0000644000175000017500000007443412120621217021542 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyCsharpShadowLayerGenerator.cxx 442 2009-04-03 19:47:41Z david.cole $ // // $Author: david.cole $ // $Date: 2009-04-03 15:47:41 -0400 (Fri, 03 Apr 2009) $ // $Revision: 442 $ // // Copyright (C) 2006-2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyCsharpShadowLayerGenerator.h" #include "MummyCsharpGenerator.h" #include "MummyLog.h" #include "MummySettings.h" #include "cableClass.h" #include "cableClassType.h" #include "cableFundamentalType.h" #include "cableFunctionType.h" #include "cableMethod.h" #include "cablePointerType.h" #include "cableType.h" #include "gxsys/ios/sstream" //---------------------------------------------------------------------------- MummyCsharpShadowLayerGenerator::MummyCsharpShadowLayerGenerator() { this->CsharpGenerator = 0; } //---------------------------------------------------------------------------- MummyCsharpShadowLayerGenerator::~MummyCsharpShadowLayerGenerator() { } //---------------------------------------------------------------------------- bool MummyCsharpShadowLayerGenerator::GenerateWrappers() { this->EmitClassForShadowLayer(*GetStream(), GetTargetClass()); return false; } //---------------------------------------------------------------------------- MummyCsharpGenerator* MummyCsharpShadowLayerGenerator::GetCsharpGenerator() { return this->CsharpGenerator; } //---------------------------------------------------------------------------- void MummyCsharpShadowLayerGenerator::SetCsharpGenerator(MummyCsharpGenerator* generator) { this->CsharpGenerator = generator; } //---------------------------------------------------------------------------- const char *MummyCsharpShadowLayerGenerator::GetArgName(cable::FunctionType *ftype, unsigned int i) { return this->GetCsharpGenerator()->GetArgName(ftype, i); } //---------------------------------------------------------------------------- gxsys_stl::string GetShadowClassName(const cable::Class *c) { gxsys_stl::string s(c->GetName()); s += "Shadow"; return s; } //---------------------------------------------------------------------------- gxsys_stl::string GetPrimaryDelegateCxxType(const cable::Class *c) { return GetShadowClassName(c) + "_PrimaryType"; } //---------------------------------------------------------------------------- gxsys_stl::string GetSecondaryDelegateCxxType(const cable::Class *c) { return gxsys_stl::string(c->GetName()) + "*"; } //---------------------------------------------------------------------------- void MummyCsharpShadowLayerGenerator::EmitClassMethodDeclarationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *, const cable::Method *m, const unsigned int, int indent, const char *implClassName) { cable::FunctionType *ft = m->GetFunctionType(); unsigned int cArgs = ft->GetNumberOfArguments(); unsigned int i = 0; cable::Type *argType = 0; cable::Type *retType = ft->GetReturns(); EmitIndent(os, indent); // Context: // Emit(os, "/* "); // Emit(os, m->GetContext()->GetName()); // Emit(os, " */ "); // Abstract? // if (m->GetPureVirtual()) // { // Emit(os, "/* pure virtual */ "); // } // Definitely virtual: if (m->GetVirtual() && !implClassName) { Emit(os, "virtual "); } // Return type: Emit(os, retType->GetCxxType().GetName().c_str()); Emit(os, " "); // Class name colon colon: if (implClassName) { Emit(os, implClassName); Emit(os, "::"); } // Method name: Emit(os, m->GetName()); // Open args: Emit(os, "("); // The real args: for (i= 0; iGetArgument(i); // arg "i": Emit(os, argType->GetCxxType().GetName().c_str()); Emit(os, " "); Emit(os, GetArgName(ft, i)); if (i& wrapped_methods, cable::Method*, cable::Method*, cable::Method*, cable::Method*) { unsigned int i = 0; gxsys_stl::string s(GetShadowClassName(c)); if (ClassIsA(c, "vtkObject")) { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "#include \"vtkDebugLeaks.h\"\n"); } Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "#undef "); Emit(os, s.c_str()); Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n"); Emit(os, "\n"); Emit(os, "#ifdef _MSC_VER\n"); Emit(os, "#define "); Emit(os, s.c_str()); Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n"); Emit(os, "#endif\n"); Emit(os, "\n"); Emit(os, "#ifdef "); Emit(os, s.c_str()); Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n"); Emit(os, "#include \"windows.h\" // HRESULT, FAILED, E_UNEXPECTED\n"); Emit(os, "#define "); Emit(os, s.c_str()); Emit(os, "_PrimaryType IDispatch*\n"); Emit(os, "#else\n"); Emit(os, "#define "); Emit(os, s.c_str()); Emit(os, "_PrimaryType void*\n"); Emit(os, "#define HRESULT long\n"); Emit(os, "#define FAILED(hr) ((HRESULT)(hr) < 0)\n"); Emit(os, "#define E_UNEXPECTED ((HRESULT)0x8000FFFFL)\n"); Emit(os, "#endif\n"); Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "class "); Emit(os, s.c_str()); Emit(os, " : public "); Emit(os, c->GetQualifiedName().c_str()); // Abstract? //if (c->GetAbstract()) // { // Emit(os, " /* abstract */"); // } Emit(os, "\n"); Emit(os, "{\n"); Emit(os, "public:\n"); // Shadow class always has factory method and DisconnectShadowDelegates: // // The factory method is "create-and-connect" so that it can be made in // one "over-the-boundary" call from the wrapped layer: // EmitIndent(os); Emit(os, "static "); Emit(os, s.c_str()); Emit(os, "* CreateShadow("); Emit(os, GetPrimaryDelegateCxxType(c).c_str()); Emit(os, " primary);"); Emit(os, "\n"); EmitIndent(os); Emit(os, "void DisconnectShadowDelegates();"); Emit(os, "\n"); Emit(os, "\n"); // And overrides of all the virtual wrapped methods (including the Register // and UnRegister methods, if any...) // i = 0; for (gxsys_stl::vector::const_iterator mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { if ((*mit)->GetVirtual()) { EmitClassMethodDeclarationForShadowLayer(os, c, *mit, i+1, 1, false); Emit(os, ";\n"); } ++i; } Emit(os, "\n"); Emit(os, "protected:\n"); EmitIndent(os); Emit(os, s.c_str()); Emit(os, "();\n"); EmitIndent(os); Emit(os, "virtual ~"); Emit(os, s.c_str()); Emit(os, "();\n"); Emit(os, "\n"); Emit(os, "private:\n"); EmitIndent(os); Emit(os, GetPrimaryDelegateCxxType(c).c_str()); Emit(os, " PrimaryDelegate;"); Emit(os, "\n"); EmitIndent(os); Emit(os, GetSecondaryDelegateCxxType(c).c_str()); Emit(os, " SecondaryDelegate;"); Emit(os, "\n"); // A bool flag for each virtual override indicating whether the shadow // class is currently calling that method on the primary delegate or not: // i = 0; for (gxsys_stl::vector::const_iterator mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { if ((*mit)->GetVirtual()) { EmitIndent(os); Emit(os, "bool CallingPrimary_"); Emit(os, (*mit)->GetName()); Emit(os, "_"); EmitUint(os, i+1); Emit(os, ";\n"); } ++i; } Emit(os, "};\n"); } //---------------------------------------------------------------------------- // The string returned from these Variant functions should be a valid V_ and // VT_ suffix for use with initializing/accessing a VARIANT variable of the // given type... // // For example, in the use case: // VariantInit(&vargs[0]); // V_VT(&vargs[0]) = VT_I4; // V_I4(&vargs[0]) = (long) callData; // This function will receive a cable type representing the C++ type "long" // and return "I4"... // gxsys_stl::string /* MummyCsharpShadowLayerGenerator:: */ GetVariantFundamentalTypeString(const cable::Type *t) { gxsys_stl::string s; if (cable::Type::FundamentalTypeId == t->GetTypeId()) { s = cable::FundamentalType::SafeDownCast(t)->GetTypeName(); switch (cxx::FundamentalType::SafeDownCast(t->GetCxxType().GetType())->GetId()) { case cxx::FundamentalType::UnsignedChar: s = "UI1"; break; case cxx::FundamentalType::UnsignedShortInt: s = "UI2"; break; case cxx::FundamentalType::UnsignedInt: case cxx::FundamentalType::UnsignedLongInt: s = "UI4"; break; case cxx::FundamentalType::UnsignedLongLongInt: s = "UI8"; break; case cxx::FundamentalType::SignedChar: case cxx::FundamentalType::Char: s = "I1"; break; case cxx::FundamentalType::ShortInt: s = "I2"; break; case cxx::FundamentalType::Int: case cxx::FundamentalType::LongInt: s = "I4"; break; case cxx::FundamentalType::LongLongInt: s = "I8"; break; case cxx::FundamentalType::Bool: s = "BOOL"; break; case cxx::FundamentalType::Float: s = "R4"; break; case cxx::FundamentalType::Double: s = "R8"; break; //case cxx::FundamentalType::Void: //case cxx::FundamentalType::WChar_t: //case cxx::FundamentalType::LongDouble: //case cxx::FundamentalType::ComplexFloat: //case cxx::FundamentalType::ComplexDouble: //case cxx::FundamentalType::ComplexLongDouble: //case cxx::FundamentalType::NumberOfTypes: default: break; } } if (s == "") { LogError(me_InternalError, << "Unhandled variable type. GetVariantFundamentalTypeString returning the empty string..."); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string /* MummyCsharpShadowLayerGenerator:: */ GetVariantTypeString(const cable::Type *t) { gxsys_stl::string s; cable::Type *nested_type = 0; switch (t->GetTypeId()) { case cable::Type::EnumerationTypeId: s = "UI4"; break; case cable::Type::FundamentalTypeId: s = GetVariantFundamentalTypeString(t); break; case cable::Type::ArrayTypeId: s = "ERROR_ArrayTypeId_not_yet_implemented"; LogError(me_InternalError, << s.c_str()); break; case cable::Type::ClassTypeId: s = "ERROR_passing_class__"; s += cable::ClassType::SafeDownCast(t)->GetClass()->GetName(); s += "__by_value_not_allowed"; LogError(me_InternalError, << s.c_str()); break; case cable::Type::PointerTypeId: nested_type = cable::PointerType::SafeDownCast(t)->GetTarget(); // IntPtr maps to I4 on 32-bit windows and I8 on 64-bit windows... // if (IsObject(nested_type)) { s = "I4"; } else if (IsChar(nested_type)) { s = "I4"; } else if (IsVoid(nested_type)) { s = "I4"; } else if (cable::Type::FundamentalTypeId == nested_type->GetTypeId()) { s = "I4"; } else if (cable::Type::PointerTypeId == nested_type->GetTypeId()) { s = "I4 /* pointer */"; } else { s = "ERROR_PointerTypeId_not_yet_implemented_for_nested_type"; LogError(me_InternalError, << s.c_str()); } break; case cable::Type::ReferenceTypeId: s = "ERROR_ReferenceTypeId_not_yet_implemented"; LogError(me_InternalError, << s.c_str()); break; case cable::Type::OffsetTypeId: case cable::Type::MethodTypeId: case cable::Type::FunctionTypeId: default: s = "ERROR_No_Variant_type_for_cable_Type_TypeId"; LogError(me_InternalError, << s.c_str()); break; } if (s == "") { LogError(me_InternalError, << "Unhandled variable type. GetVariantTypeString returning the empty string..."); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string /* MummyCsharpShadowLayerGenerator:: */ GetVariantTypeCastingString(const cable::Type *t) { gxsys_stl::string s; cable::Type *nested_type = 0; switch (t->GetTypeId()) { case cable::Type::EnumerationTypeId: s = "(unsigned int) "; break; case cable::Type::FundamentalTypeId: // No cast needed... s = ""; break; case cable::Type::ArrayTypeId: s = "ERROR_ArrayTypeId_not_yet_implemented"; LogError(me_InternalError, << s.c_str()); break; case cable::Type::ClassTypeId: s = "ERROR_passing_class__"; s += cable::ClassType::SafeDownCast(t)->GetClass()->GetName(); s += "__by_value_not_allowed"; LogError(me_InternalError, << s.c_str()); break; case cable::Type::PointerTypeId: nested_type = cable::PointerType::SafeDownCast(t)->GetTarget(); // IntPtr maps to I4 on 32-bit windows and I8 on 64-bit windows... // if (IsObject(nested_type)) { s = "(int) "; } else if (IsChar(nested_type)) { s = "(int) "; } else if (IsVoid(nested_type)) { s = "(int) "; } else if (cable::Type::FundamentalTypeId == nested_type->GetTypeId()) { s = "(int) "; } else if (cable::Type::PointerTypeId == nested_type->GetTypeId()) { s = "(int) /* pointer */"; } else { s = "ERROR_PointerTypeId_not_yet_implemented_for_nested_type"; LogError(me_InternalError, << s.c_str()); } break; case cable::Type::ReferenceTypeId: s = "ERROR_ReferenceTypeId_not_yet_implemented"; LogError(me_InternalError, << s.c_str()); break; case cable::Type::OffsetTypeId: case cable::Type::MethodTypeId: case cable::Type::FunctionTypeId: default: s = "ERROR_No_Variant_type_for_cable_Type_TypeId"; LogError(me_InternalError, << s.c_str()); break; } return s; } //---------------------------------------------------------------------------- void MummyCsharpShadowLayerGenerator::EmitClassImplementationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c, const gxsys_stl::vector& wrapped_methods, cable::Method* factoryM, cable::Method* disposalM, cable::Method* registerM, cable::Method* unRegisterM) { unsigned int i = 0; gxsys_stl::string s(GetShadowClassName(c)); gxsys_ios::ostringstream oss; gxsys_stl::string vargs; // Shadow class always has factory method and DisconnectShadowDelegates: // Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "/* static */\n"); Emit(os, s.c_str()); Emit(os, "* "); Emit(os, s.c_str()); Emit(os, "::"); Emit(os, "CreateShadow("); Emit(os, GetPrimaryDelegateCxxType(c).c_str()); Emit(os, " primary)"); Emit(os, "\n"); Emit(os, "{\n"); EmitIndent(os); Emit(os, s.c_str()); Emit(os, "* rv = new "); Emit(os, s.c_str()); Emit(os, ";\n"); EmitIndent(os); Emit(os, "rv->PrimaryDelegate = primary;\n"); EmitIndent(os); Emit(os, "rv->SecondaryDelegate = "); if (factoryM) { Emit(os, c->GetName()); Emit(os, "::"); Emit(os, factoryM->GetName()); Emit(os, "()"); } else { Emit(os, "0"); } Emit(os, ";\n"); Emit(os, "\n"); EmitIndent(os); Emit(os, "if (rv->PrimaryDelegate)\n"); EmitIndent(os, 2); Emit(os, "{\n"); Emit(os, "#ifdef "); Emit(os, s.c_str()); Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n"); EmitIndent(os, 2); Emit(os, "rv->PrimaryDelegate->AddRef();\n"); Emit(os, "#else\n"); Emit(os, "#endif\n"); EmitIndent(os, 2); Emit(os, "}\n"); Emit(os, "\n"); EmitIndent(os); Emit(os, "return rv;\n"); Emit(os, "}\n"); Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "void "); Emit(os, s.c_str()); Emit(os, "::"); Emit(os, "DisconnectShadowDelegates()"); Emit(os, "\n"); Emit(os, "{\n"); EmitIndent(os); Emit(os, "if (this->PrimaryDelegate)\n"); EmitIndent(os, 2); Emit(os, "{\n"); Emit(os, "#ifdef "); Emit(os, s.c_str()); Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n"); EmitIndent(os, 2); Emit(os, "this->PrimaryDelegate->Release();\n"); Emit(os, "#else\n"); Emit(os, "#endif\n"); EmitIndent(os, 2); Emit(os, "}\n"); EmitIndent(os); Emit(os, "this->PrimaryDelegate = 0;\n"); Emit(os, "\n"); if (disposalM) { EmitIndent(os); Emit(os, "if (this->SecondaryDelegate)\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, "this->SecondaryDelegate->"); Emit(os, disposalM->GetName()); Emit(os, "();\n"); EmitIndent(os, 2); Emit(os, "}\n"); } EmitIndent(os); Emit(os, "this->SecondaryDelegate = 0;\n"); Emit(os, "\n"); Emit(os, "}\n"); // And overrides of all the virtual wrapped methods: // i = 0; for (gxsys_stl::vector::const_iterator mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { if ((*mit)->GetVirtual()) { unsigned int argi = 0; unsigned int cArgs = (*mit)->GetFunctionType()->GetNumberOfArguments(); cable::Type *retType = (*mit)->GetFunctionType()->GetReturns(); bool voidReturn = false; if (IsVoid(retType)) { voidReturn = true; } Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); EmitClassMethodDeclarationForShadowLayer(os, c, *mit, i+1, 0, s.c_str()); Emit(os, "\n"); Emit(os, "{\n"); if (!voidReturn) { EmitIndent(os); Emit(os, retType->GetCxxType().GetName().c_str()); Emit(os, " rv = "); if (cable::Type::PointerTypeId == retType->GetTypeId()) { Emit(os, "0"); } else if (cable::Type::FundamentalTypeId == retType->GetTypeId()) { Emit(os, "("); Emit(os, retType->GetCxxType().GetName().c_str()); Emit(os, ") 0"); } else { Emit(os, retType->GetCxxType().GetName().c_str()); Emit(os, "()"); } Emit(os, ";\n"); } EmitIndent(os); Emit(os, "HRESULT msl_hr = E_UNEXPECTED;\n"); Emit(os, "\n"); EmitIndent(os); Emit(os, "if (this->PrimaryDelegate && !this->CallingPrimary_"); Emit(os, (*mit)->GetName()); Emit(os, "_"); EmitUint(os, i+1); Emit(os, ")\n"); EmitIndent(os, 2); Emit(os, "{\n"); EmitIndent(os, 2); Emit(os, "this->CallingPrimary_"); Emit(os, (*mit)->GetName()); Emit(os, "_"); EmitUint(os, i+1); Emit(os, " = true;\n"); Emit(os, "\n"); Emit(os, "#ifdef "); Emit(os, s.c_str()); Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n"); EmitIndent(os, 2); Emit(os, "IDispatch *msl_pDisp = (IDispatch *) this->PrimaryDelegate;\n"); EmitIndent(os, 2); Emit(os, "msl_pDisp->AddRef();\n"); Emit(os, "\n"); EmitIndent(os, 2); Emit(os, "DISPID msl_dispid = (DISPID) -1;\n"); EmitIndent(os, 2); Emit(os, "OLECHAR *msl_name = L\""); Emit(os, (*mit)->GetName()); Emit(os, "\";\n"); if (cArgs!=0) { EmitIndent(os, 2); Emit(os, "VARIANTARG msl_vargs["); oss.rdbuf()->str(""); oss << cArgs << gxsys_ios::ends; vargs = oss.str(); Emit(os, vargs.c_str()); Emit(os, "];\n"); } EmitIndent(os, 2); Emit(os, "DISPPARAMS msl_params;\n"); EmitIndent(os, 2); Emit(os, "VARIANT msl_result;\n"); EmitIndent(os, 2); Emit(os, "EXCEPINFO msl_excep;\n"); EmitIndent(os, 2); Emit(os, "UINT msl_arg = (UINT) -1;\n"); Emit(os, "\n"); EmitIndent(os, 2); Emit(os, "msl_hr = msl_pDisp->GetIDsOfNames(\n"); EmitIndent(os, 3); Emit(os, "IID_NULL,\n"); EmitIndent(os, 3); Emit(os, "&msl_name,\n"); EmitIndent(os, 3); Emit(os, "1,\n"); EmitIndent(os, 3); Emit(os, "LOCALE_USER_DEFAULT,\n"); EmitIndent(os, 3); Emit(os, "&msl_dispid);\n"); Emit(os, "\n"); EmitIndent(os, 2); Emit(os, "if (SUCCEEDED(msl_hr))\n"); EmitIndent(os, 3); Emit(os, "{\n"); for (argi= 0; argistr(""); oss << "&msl_vargs[" << (cArgs-1-argi) << "]" << gxsys_ios::ends; vargs = oss.str(); EmitIndent(os, 3); Emit(os, "VariantInit("); Emit(os, vargs.c_str()); Emit(os, ");\n"); EmitIndent(os, 3); Emit(os, "V_VT("); Emit(os, vargs.c_str()); Emit(os, ") = VT_"); Emit(os, GetVariantTypeString((*mit)->GetFunctionType()->GetArgument(argi)).c_str()); Emit(os, ";\n"); EmitIndent(os, 3); Emit(os, "V_"); Emit(os, GetVariantTypeString((*mit)->GetFunctionType()->GetArgument(argi)).c_str()); Emit(os, "("); Emit(os, vargs.c_str()); Emit(os, ") = "); Emit(os, GetVariantTypeCastingString((*mit)->GetFunctionType()->GetArgument(argi)).c_str()); Emit(os, GetArgName((*mit)->GetFunctionType(), argi)); Emit(os, ";\n"); Emit(os, "\n"); } EmitIndent(os, 3); Emit(os, "msl_params.rgvarg = "); if (0 == cArgs) { Emit(os, "0"); } else { Emit(os, "&msl_vargs[0]"); } Emit(os, ";\n"); EmitIndent(os, 3); Emit(os, "msl_params.rgdispidNamedArgs = 0;\n"); EmitIndent(os, 3); Emit(os, "msl_params.cArgs = "); if (0 == cArgs) { Emit(os, "0"); } else { Emit(os, "sizeof(msl_vargs)/sizeof(msl_vargs[0])"); } Emit(os, ";\n"); EmitIndent(os, 3); Emit(os, "msl_params.cNamedArgs = 0;\n"); Emit(os, "\n"); EmitIndent(os, 3); Emit(os, "VariantInit(&msl_result);\n"); Emit(os, "\n"); EmitIndent(os, 3); Emit(os, "memset(&msl_excep, 0, sizeof(msl_excep));\n"); Emit(os, "\n"); EmitIndent(os, 3); Emit(os, "msl_hr = msl_pDisp->Invoke(msl_dispid, IID_NULL, LOCALE_USER_DEFAULT,\n"); EmitIndent(os, 4); Emit(os, "DISPATCH_METHOD, &msl_params, &msl_result, &msl_excep, &msl_arg);\n"); Emit(os, "\n"); if (!voidReturn) { EmitIndent(os, 3); Emit(os, "if (SUCCEEDED(msl_hr))\n"); EmitIndent(os, 4); Emit(os, "{\n"); EmitIndent(os, 4); Emit(os, "rv = ("); Emit(os, retType->GetCxxType().GetName().c_str()); Emit(os, ") V_"); Emit(os, GetVariantTypeString(retType).c_str()); Emit(os, "(&msl_result);\n"); EmitIndent(os, 4); Emit(os, "}\n"); Emit(os, "\n"); } EmitIndent(os, 3); Emit(os, "VariantClear(&msl_result);\n"); for (argi= 0; argistr(""); oss << "&msl_vargs[" << argi << "]" << gxsys_ios::ends; vargs = oss.str(); EmitIndent(os, 3); Emit(os, "VariantClear("); Emit(os, vargs.c_str()); Emit(os, ");\n"); } EmitIndent(os, 3); Emit(os, "}\n"); Emit(os, "\n"); EmitIndent(os, 2); Emit(os, "msl_pDisp->Release();\n"); Emit(os, "#else\n"); Emit(os, "#endif\n"); Emit(os, "\n"); EmitIndent(os, 2); Emit(os, "this->CallingPrimary_"); Emit(os, (*mit)->GetName()); Emit(os, "_"); EmitUint(os, i+1); Emit(os, " = false;\n"); EmitIndent(os, 2); Emit(os, "}\n"); Emit(os, "\n"); EmitIndent(os); Emit(os, "if (FAILED(msl_hr) || this->CallingPrimary_"); Emit(os, (*mit)->GetName()); Emit(os, "_"); EmitUint(os, i+1); Emit(os, ")\n"); EmitIndent(os, 2); Emit(os, "{\n"); // Do NOT delegate Register or UnRegister calls to the // SecondaryDelegate... Only pass them up to the parent // class implementation on *this* object. The SecondaryDelegate // is only held by us for delegating non-ref-counting calls // to... // int secondaryIndent = 3; if (*mit != registerM && *mit != unRegisterM) { secondaryIndent = 3; EmitIndent(os, 2); Emit(os, "if (this->SecondaryDelegate)\n"); EmitIndent(os, 3); Emit(os, "{\n"); EmitIndent(os, 3); if (!voidReturn) { Emit(os, "rv = "); } Emit(os, "this->SecondaryDelegate->"); Emit(os, (*mit)->GetName()); Emit(os, "("); for (argi= 0; argiGetFunctionType(), argi)); if (argiGetPureVirtual()) { EmitIndent(os, secondaryIndent); Emit(os, "// pure virtual method in parent class...\n"); if (*mit == registerM || *mit == unRegisterM) { EmitIndent(os, secondaryIndent); Emit(os, "// Register and UnRegister methods should *not* be\n"); EmitIndent(os, secondaryIndent); Emit(os, "// pure virtual methods in a shadowed class...\n"); LogError(me_PureVirtualMethodNotAllowed, << "Register and UnRegister methods *cannot* be pure " << "virtual methods in a shadowed class..." ); } } else { EmitIndent(os, secondaryIndent); if (!voidReturn) { Emit(os, "rv = "); } Emit(os, "this->"); Emit(os, c->GetQualifiedName().c_str()); Emit(os, "::"); Emit(os, (*mit)->GetName()); Emit(os, "("); for (argi= 0; argiGetFunctionType(), argi)); if (argiPrimaryDelegate = 0;\n"); EmitIndent(os); Emit(os, "this->SecondaryDelegate = 0;\n"); i = 0; for (gxsys_stl::vector::const_iterator mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { if ((*mit)->GetVirtual()) { EmitIndent(os); Emit(os, "this->CallingPrimary_"); Emit(os, (*mit)->GetName()); Emit(os, "_"); EmitUint(os, i+1); Emit(os, " = false;\n"); } ++i; } if (ClassIsA(c, "vtkObject")) { Emit(os, "\n"); Emit(os, "#ifdef VTK_DEBUG_LEAKS\n"); EmitIndent(os); Emit(os, "vtkDebugLeaks::ConstructClass(\""); Emit(os, c->GetName()); Emit(os, "\");\n"); Emit(os, "#endif\n"); } Emit(os, "}\n"); // Destructor: // Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, s.c_str()); Emit(os, "::~"); Emit(os, s.c_str()); Emit(os, "()\n"); Emit(os, "{\n"); EmitIndent(os); Emit(os, "this->DisconnectShadowDelegates();\n"); Emit(os, "}\n"); // And one extra export layer style function to create an instance of the // shadow class: // Emit(os, "\n"); Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "extern \"C\" MUMMY_DLL_EXPORT\n"); Emit(os, s.c_str()); Emit(os, "* "); Emit(os, s.c_str()); Emit(os, "_CreateShadow("); Emit(os, GetPrimaryDelegateCxxType(c).c_str()); Emit(os, " primary)\n"); Emit(os, "{\n"); EmitIndent(os); Emit(os, s.c_str()); Emit(os, "* rv = "); Emit(os, s.c_str()); Emit(os, "::CreateShadow(primary);\n"); EmitIndent(os); Emit(os, "return rv;\n"); Emit(os, "}\n"); } //---------------------------------------------------------------------------- void MummyCsharpShadowLayerGenerator::EmitClassForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c) { // Gather wrapped elements: // gxsys_stl::vector wrapped_methods; cable::Method *factoryM = 0; cable::Method *disposalM = 0; cable::Method *registerM = 0; cable::Method *unRegisterM = 0; this->GetCsharpGenerator()->GatherWrappedMethods(c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM, true); // For the purposes of the shadow layer, make sure the Register and UnRegister // methods are emitted (same as any other wrapped method) in the shadow class: // wrapped_methods.insert(wrapped_methods.begin(), unRegisterM); wrapped_methods.insert(wrapped_methods.begin(), registerM); EmitClassDeclarationForShadowLayer(os, c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM); EmitClassImplementationForShadowLayer(os, c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM); } mummy-1.0.3/MummyCsharpShadowLayerGenerator.h0000644000175000017500000000347312120621217021162 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyCsharpShadowLayerGenerator.h // // Author(s) : David Cole // // Copyright (C) 2006-2007 Kitware, Inc. //---------------------------------------------------------------------------- #include "MummyGenerator.h" // parent class #include "gxsys/stl/string" #include "gxsys/stl/vector" class MummyCsharpGenerator; class MummyCsharpShadowLayerGenerator : public MummyGenerator { public: MummyCsharpShadowLayerGenerator(); virtual ~MummyCsharpShadowLayerGenerator(); virtual bool GenerateWrappers(); virtual MummyCsharpGenerator* GetCsharpGenerator(); virtual void SetCsharpGenerator(MummyCsharpGenerator* generator); virtual const char *GetArgName(cable::FunctionType *ftype, unsigned int i); virtual void EmitClassMethodDeclarationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method *m, const unsigned int index, int indent, const char* implClassName); virtual void EmitClassDeclarationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c, const gxsys_stl::vector& wrapped_methods, cable::Method* factoryM, cable::Method* disposalM, cable::Method* registerM, cable::Method* unRegisterM); virtual void EmitClassImplementationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c, const gxsys_stl::vector& wrapped_methods, cable::Method* factoryM, cable::Method* disposalM, cable::Method* registerM, cable::Method* unRegisterM); virtual void EmitClassForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c); private: MummyCsharpGenerator* CsharpGenerator; MummyCsharpShadowLayerGenerator(const MummyCsharpShadowLayerGenerator&); //Not implemented MummyCsharpShadowLayerGenerator& operator=(const MummyCsharpShadowLayerGenerator&); //Not implemented }; mummy-1.0.3/MummyCsharpUnitTestGenerator.cxx0000644000175000017500000002553012120621217021070 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyCsharpUnitTestGenerator.cxx 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2006-2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyCsharpUnitTestGenerator.h" #include "MummyCsharpGenerator.h" #include "MummyLog.h" #include "MummySettings.h" #include "cableClass.h" #include "cableClassType.h" #include "cableFunctionType.h" #include "cableMethod.h" #include "cablePointerType.h" #include "cableReferenceType.h" #include "cxxCvQualifiedType.h" #include "cxxFunctionType.h" #include "cxxPointerType.h" #include "gxsys/stl/algorithm" #include "gxsys/SystemTools.hxx" //---------------------------------------------------------------------------- MummyCsharpUnitTestGenerator::MummyCsharpUnitTestGenerator() { this->CsharpGenerator = 0; } //---------------------------------------------------------------------------- MummyCsharpUnitTestGenerator::~MummyCsharpUnitTestGenerator() { } //---------------------------------------------------------------------------- bool MummyCsharpUnitTestGenerator::GenerateWrappers() { this->EmitClass(*GetStream(), GetTargetClass()); return false; } //---------------------------------------------------------------------------- MummyCsharpGenerator* MummyCsharpUnitTestGenerator::GetCsharpGenerator() { return this->CsharpGenerator; } //---------------------------------------------------------------------------- void MummyCsharpUnitTestGenerator::SetCsharpGenerator(MummyCsharpGenerator* generator) { this->CsharpGenerator = generator; } //---------------------------------------------------------------------------- //bool MummyCsharpUnitTestGenerator::FundamentalTypeIsWrappable(const cable::Type* t) //{ // return this->GetCsharpGenerator()->FundamentalTypeIsWrappable(t); //} //---------------------------------------------------------------------------- //bool MummyCsharpUnitTestGenerator::TypeIsWrappable(const cable::Type* t) //{ // return this->GetCsharpGenerator()->TypeIsWrappable(t); //} //---------------------------------------------------------------------------- //bool MummyCsharpUnitTestGenerator::FunctionTypeIsWrappable(const cable::FunctionType* ft) //{ // return this->GetCsharpGenerator()->FunctionTypeIsWrappable(ft); //} //---------------------------------------------------------------------------- //bool MummyCsharpUnitTestGenerator::MethodIsWrappable(const cable::Method* m, const cable::Context::Access& access) //{ // return this->GetCsharpGenerator()->MethodIsWrappable(m, access); //} //---------------------------------------------------------------------------- //bool MummyCsharpUnitTestGenerator::ClassIsWrappable(const cable::Class* c) //{ // return this->GetCsharpGenerator()->ClassIsWrappable(c); //} //---------------------------------------------------------------------------- const char *MummyCsharpUnitTestGenerator::GetArgName(cable::FunctionType *ftype, unsigned int i) { return this->GetCsharpGenerator()->GetArgName(ftype, i); } //---------------------------------------------------------------------------- void MummyCsharpUnitTestGenerator::EmitCSharpFactoryMethodUnitTest(gxsys_ios::ostream &os, const cable::Class *) { Emit(os, "// EmitCSharpFactoryMethodUnitTest\n"); } //---------------------------------------------------------------------------- void MummyCsharpUnitTestGenerator::EmitCSharpMethodUnitTest(gxsys_ios::ostream &os, const cable::Class *, const cable::Method*) { Emit(os, "// EmitCSharpMethodUnitTest\n"); } //---------------------------------------------------------------------------- void MummyCsharpUnitTestGenerator::EmitCSharpPropertyUnitTest(gxsys_ios::ostream &os, const cable::Class *, const cable::Method*, const cable::Method*) { Emit(os, "// EmitCSharpPropertyUnitTest\n"); } //---------------------------------------------------------------------------- void MummyCsharpUnitTestGenerator::EmitCSharpStructMemberAccessUnitTest(gxsys_ios::ostream &os, const cable::Class *) { Emit(os, "// EmitCSharpStructMemberAccessUnitTest\n"); } //---------------------------------------------------------------------------- void MummyCsharpUnitTestGenerator::EmitClass(gxsys_ios::ostream &os, const cable::Class *c) { // Gather wrapped elements: // gxsys_stl::vector wrapped_methods; gxsys_stl::vector::iterator mit; cable::Method *factoryM = 0; cable::Method *disposalM = 0; cable::Method *registerM = 0; cable::Method *unRegisterM = 0; bool verbose = this->GetSettings()->GetVerbose(); gxsys_stl::string atts(c->GetAttributes()); // The "package" directive from the gccxml input is used as a base // namespace. If it's not empty, prepend it to the class's namespace. // gxsys_stl::string target_namespace; gxsys_stl::string base_namespace(this->GetSettings()->GetPackage()); gxsys_stl::string class_namespace(GetFullyQualifiedNameForCSharp(c->GetContext())); // C++ global scope means "no namespace please" // if (class_namespace == "::") { class_namespace = ""; } if (base_namespace == "") { target_namespace = class_namespace; } else if (class_namespace == "") { target_namespace = base_namespace; } else { target_namespace = base_namespace + "." + class_namespace; } if (target_namespace != "") { target_namespace = target_namespace + ".UnitTests"; } // Emit code: // EmitMummyVersionComments(os, "//"); // If the class maps directly to a builtin type, then DO NOT emit any code. // gxsys_stl::string mapToType = ExtractMapToType(c); if (mapToType != "") { Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "// Unmanaged class '"); Emit(os, GetFullyQualifiedNameForCPlusPlus(c).c_str()); Emit(os, "' maps directly to type '"); Emit(os, mapToType.c_str()); Emit(os, "'.\n"); Emit(os, "// No code generated for '"); Emit(os, GetFullyQualifiedNameForCPlusPlus(c).c_str()); Emit(os, "'...\n"); if (verbose) { LogInfo(mi_VerboseInfo, << "Skipping code generation because class maps directly to native type."); } return; } Emit(os, "\n"); Emit(os, "//----------------------------------------------------------------------------\n"); Emit(os, "using System;\n"); Emit(os, "using System.Runtime.InteropServices; // DllImport and HandleRef both live here\n"); Emit(os, "\n"); // If this project depends on "using" any other C# namespaces, they will be listed // as "Reference" elements in MummySettings.xml... // gxsys_stl::vector refs; this->GetSettings()->GetReferences(refs); if (refs.size()) { Emit(os, "// References\n"); gxsys_stl::vector::iterator rit; for (rit = refs.begin(); rit != refs.end(); ++rit) { Emit(os, "using "); Emit(os, rit->c_str()); Emit(os, ";\n"); } Emit(os, "\n"); } // Open the (optional) namespace: // if (target_namespace != "") { Emit(os, "namespace "); Emit(os, target_namespace.c_str()); Emit(os, "\n"); Emit(os, "{\n"); Emit(os, "\n"); } // Documentation: // Emit(os, "/// \n"); Emit(os, "/// Automatically generated unit test\n"); Emit(os, "/// \n"); if (IsUtilityClass(c)) { // Utility classes get wrapped as structs: // EmitCSharpStructMemberAccessUnitTest(os, c); } else { if (verbose) { LogInfo(mi_VerboseInfo, << "Calling GatherWrappedMethods..."); } this->GetCsharpGenerator()->GatherWrappedMethods(c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM, false); // Filter out prop gets and sets, putting them in their very own data structure. // Key in the map is the name of the property. 1st method in pair is propget, // 2nd method is propset. // gxsys_stl::map > wrapped_properties; this->GetCsharpGenerator()->BuildPropGetsAndSetsMap(wrapped_methods, wrapped_properties); // Now remove any entries found in the props *map* from the methods *vector*. // Otherwise, we'd end up with all of the properties "repeated" as methods, too. // gxsys_stl::map >::iterator gsit; for (gsit = wrapped_properties.begin(); gsit != wrapped_properties.end(); ++gsit) { if (gsit->second.first) { mit = gxsys_stl::find(wrapped_methods.begin(), wrapped_methods.end(), gsit->second.first); if (mit != wrapped_methods.end()) { wrapped_methods.erase(mit); } else { LogWarning(mw_InternalWarning, << "Unexpected unfound propget method..."); } } if (gsit->second.second) { mit = gxsys_stl::find(wrapped_methods.begin(), wrapped_methods.end(), gsit->second.second); if (mit != wrapped_methods.end()) { wrapped_methods.erase(mit); } else { LogWarning(mw_InternalWarning, << "Unexpected unfound propset method..."); } } } // Class declaration: // Emit(os, "public "); // if (c->GetAbstract()) // { // Emit(os, "abstract "); // } Emit(os, "class "); Emit(os, GetWrappedClassName(c).c_str()); Emit(os, "UnitTest"); Emit(os, "\n"); // Open class: // Emit(os, "{\n"); // Factory method test: // if (factoryM || this->GetSettings()->GetUseShadow(c)) { Emit(os, "\n"); Emit(os, "\n"); EmitCSharpFactoryMethodUnitTest(os, c); } // Properties: // for (gsit = wrapped_properties.begin(); gsit != wrapped_properties.end(); ++gsit) { Emit(os, "\n"); Emit(os, "\n"); EmitCSharpPropertyUnitTest(os, c, gsit->second.first, gsit->second.second); } // Plain old methods: // for (mit = wrapped_methods.begin(); mit != wrapped_methods.end(); ++mit) { Emit(os, "\n"); Emit(os, "\n"); EmitCSharpMethodUnitTest(os, c, *mit); } } // Hand written shtuff: // // If there is extraCSharpCode, emit it *within* the class definition. // If it's there, it's the name of a file that we are to include in // its entirety... // gxsys_stl::string extraCode = this->GetSettings()->GetExtraCsharpUnitTestCode(c); if (extraCode != "") { Emit(os, "\n"); Emit(os, "\n"); Emit(os, "// Begin extraCSharpCode\n"); Emit(os, "\n"); EmitFile(os, extraCode.c_str()); Emit(os, "\n"); Emit(os, "// End extraCSharpCode\n"); Emit(os, "\n"); } // Close the struct/class: // Emit(os, "}\n"); // Close the namespace: // if (target_namespace != "") { Emit(os, "\n"); Emit(os, "}\n"); } } mummy-1.0.3/MummyCsharpUnitTestGenerator.h0000644000175000017500000000351612120621217020515 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyCsharpUnitTestGenerator.h // // Author(s) : David Cole // // Copyright (C) 2006-2007 Kitware, Inc. //---------------------------------------------------------------------------- #include "MummyGenerator.h" // parent class #include "gxsys/stl/string" class MummyCsharpGenerator; class MummyCsharpUnitTestGenerator : public MummyGenerator { public: MummyCsharpUnitTestGenerator(); virtual ~MummyCsharpUnitTestGenerator(); virtual bool GenerateWrappers(); virtual MummyCsharpGenerator* GetCsharpGenerator(); virtual void SetCsharpGenerator(MummyCsharpGenerator* generator); //virtual bool FundamentalTypeIsWrappable(const cable::Type* t); //virtual bool TypeIsWrappable(const cable::Type* t); //virtual bool FunctionTypeIsWrappable(const cable::FunctionType* ft); //virtual bool MethodIsWrappable(const cable::Method* m, const cable::Context::Access& access); //virtual bool ClassIsWrappable(const cable::Class* c); virtual const char *GetArgName(cable::FunctionType *ftype, unsigned int i); virtual void EmitCSharpFactoryMethodUnitTest(gxsys_ios::ostream &os, const cable::Class *c); virtual void EmitCSharpMethodUnitTest(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method* m); virtual void EmitCSharpPropertyUnitTest(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method* mGet, const cable::Method* mSet); virtual void EmitCSharpStructMemberAccessUnitTest(gxsys_ios::ostream &os, const cable::Class *c); virtual void EmitClass(gxsys_ios::ostream &os, const cable::Class *c); private: MummyCsharpGenerator* CsharpGenerator; MummyCsharpUnitTestGenerator(const MummyCsharpUnitTestGenerator&); //Not implemented MummyCsharpUnitTestGenerator& operator=(const MummyCsharpUnitTestGenerator&); //Not implemented }; mummy-1.0.3/MummyDoxygen.cmake0000644000175000017500000000301412120621217016165 0ustar mathieumathieuIF(NOT DOXYGEN_EXECUTABLE) FIND_PACKAGE(Doxygen) ENDIF(NOT DOXYGEN_EXECUTABLE) SET(Mummy_BUILD_DOCUMENTATION_DEFAULT OFF) IF(DOXYGEN_EXECUTABLE) IF(Mummy_BUILD_COMPONENT_MUMMY) SET(Mummy_BUILD_DOCUMENTATION_DEFAULT ON) ENDIF(Mummy_BUILD_COMPONENT_MUMMY) ENDIF(DOXYGEN_EXECUTABLE) OPTION(Mummy_BUILD_DOCUMENTATION "Build mummy doxygen documentation" ${Mummy_BUILD_DOCUMENTATION_DEFAULT}) IF(Mummy_BUILD_DOCUMENTATION) OPTION(Mummy_DOXYGEN_SHORT_NAMES "Build mummy doxygen output with short file names" OFF) MARK_AS_ADVANCED(Mummy_DOXYGEN_SHORT_NAMES) # Force it to be exactly "YES" or "NO" IF(Mummy_DOXYGEN_SHORT_NAMES) SET(Mummy_DOXYGEN_SHORT_NAMES YES) ELSE(Mummy_DOXYGEN_SHORT_NAMES) SET(Mummy_DOXYGEN_SHORT_NAMES NO) ENDIF(Mummy_DOXYGEN_SHORT_NAMES) SET(HAVE_DOT_YESNO NO) IF(DOT) SET(HAVE_DOT_YESNO YES) IF(NOT DOT_PATH) GET_FILENAME_COMPONENT(DOT_PATH ${DOT} PATH) ENDIF(NOT DOT_PATH) ENDIF(DOT) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/MummyDoxygen.doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/doxygen/doxyfile ) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/index.html COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxygen/doxyfile DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/doxygen/doxyfile ${CMAKE_CURRENT_LIST_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/MummyApplication.cxx ) ADD_CUSTOM_TARGET(mummyDoxygen ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/doxygen/html/index.html ) ENDIF(Mummy_BUILD_DOCUMENTATION) mummy-1.0.3/MummyDoxygen.doxyfile.in0000644000175000017500000015532612120621217017353 0ustar mathieumathieu# Doxyfile 1.5.4 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file that # follow. The default is UTF-8 which is also the encoding used for all text before # the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into # libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of # possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = mummy # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @Mummy_VERSION_MAJOR@.@Mummy_VERSION_MINOR@.@Mummy_VERSION_PATCH@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = "@CMAKE_CURRENT_BINARY_DIR@/doxygen" # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, # Italian, Japanese, Japanese-en (Japanese with English messages), Korean, # Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, # Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = "@CMAKE_CURRENT_SOURCE_DIR@/" # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = @Mummy_DOXYGEN_SHORT_NAMES@ # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct (or union) is # documented as struct with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code where the coding convention is that all structs are # typedef'ed and only the typedef is referenced never the struct's name. TYPEDEF_HIDES_STRUCT = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be extracted # and appear in the documentation as a namespace called 'anonymous_namespace{file}', # where file will be replaced with the base name of the file that contains the anonymous # namespace. By default anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file($line): warning: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = "@CMAKE_CURRENT_SOURCE_DIR@" # This tag can be used to specify the character encoding of the source files that # doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default # input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. # See http://www.gnu.org/software/libiconv for the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the output. # The symbol name can be a fully qualified name, a word, or if the wildcard * is used, # a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = * # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH # then you must also enable this option. If you don't then doxygen will produce # a warning and turn it on anyway SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = NO # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to # produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to # specify the directory where the mscgen tool resides. If left empty the tool is assumed to # be found in the default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = @HAVE_DOT_YESNO@ # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = YES # If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will # generate a caller dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected # functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = "@DOT_PATH@" # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the number # of direct children of the root node in a graph is already larger than # MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 1000 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO mummy-1.0.3/MummyDummyGenerator.cxx0000644000175000017500000000146712120621217017246 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyDummyGenerator.cxx 62 2008-03-07 21:07:18Z david.cole $ // // $Author: david.cole $ // $Date: 2008-03-07 16:07:18 -0500 (Fri, 07 Mar 2008) $ // $Revision: 62 $ // // Copyright (C) 2006-2008 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyDummyGenerator.h" //---------------------------------------------------------------------------- MummyDummyGenerator::MummyDummyGenerator() { } //---------------------------------------------------------------------------- MummyDummyGenerator::~MummyDummyGenerator() { } //---------------------------------------------------------------------------- bool MummyDummyGenerator::GenerateWrappers() { return false; } mummy-1.0.3/MummyDummyGenerator.h0000644000175000017500000000133712120621217016667 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyDummyGenerator.h // // Author(s) : David Cole // // Copyright (C) 2006-2008 Kitware, Inc. //---------------------------------------------------------------------------- #ifndef _MummyDummyGenerator_h_ #define _MummyDummyGenerator_h_ #include "MummyGenerator.h" // parent class //---------------------------------------------------------------------------- /// /// "Dummy" concrete derived class - its only purpose is to increase the /// coverage results. /// class MummyDummyGenerator : public MummyGenerator { public: MummyDummyGenerator(); virtual ~MummyDummyGenerator(); virtual bool GenerateWrappers(); }; #endif mummy-1.0.3/MummyGenerator.cxx0000644000175000017500000001172312120621217016226 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyGenerator.cxx 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2006-2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyGenerator.h" #include "MummyLineOrientedTextFileReader.h" #include "MummyLog.h" #include "MummySettings.h" #include "cableClass.h" #include "gxsys/RegularExpression.hxx" //---------------------------------------------------------------------------- MummyGenerator::MummyGenerator() { this->Settings = 0; this->TargetClass = 0; this->HeaderFileReader = 0; } //---------------------------------------------------------------------------- MummyGenerator::~MummyGenerator() { if (this->HeaderFileReader) { delete this->HeaderFileReader; this->HeaderFileReader = 0; } } //---------------------------------------------------------------------------- MummySettings* MummyGenerator::GetSettings() { return this->Settings; } //---------------------------------------------------------------------------- void MummyGenerator::SetSettings(MummySettings* settings) { this->Settings = settings; } //---------------------------------------------------------------------------- const cable::Class* MummyGenerator::GetTargetClass() { return this->TargetClass; } //---------------------------------------------------------------------------- void MummyGenerator::SetTargetClass(const cable::Class *c) { this->TargetClass = c; } //---------------------------------------------------------------------------- bool MummyGenerator::FundamentalTypeIsWrappable(const cable::Type*) { return false; } //---------------------------------------------------------------------------- bool MummyGenerator::TypeIsWrappable(const cable::Type*) { return false; } //---------------------------------------------------------------------------- bool MummyGenerator::FunctionTypeIsWrappable(const cable::FunctionType*) { return false; } //---------------------------------------------------------------------------- bool MummyGenerator::MethodIsWrappable(const cable::Method*, const cable::Context::Access&) { return false; } //---------------------------------------------------------------------------- bool MummyGenerator::ClassIsWrappable(const cable::Class* c) { MummySettings* settings = this->GetSettings(); if (settings) { return settings->ClassIsWrappable(c); } return false; } //---------------------------------------------------------------------------- MummyLineOrientedTextFileReader* MummyGenerator::GetHeaderFileReader(const cable::Class* c) { if (0 == this->HeaderFileReader) { this->HeaderFileReader = new MummyLineOrientedTextFileReader; MummySettings* settings = this->GetSettings(); if (settings) { ClassWrappingSettings cws; if (settings->FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { this->HeaderFileReader->SetExcludeMarkedLines(cws.excludeMarkedLines); this->HeaderFileReader->SetBeginExcludeRegex(cws.beginExcludeRegex); this->HeaderFileReader->SetEndExcludeRegex(cws.endExcludeRegex); } else { LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } } this->HeaderFileReader->SetFileName(c->GetFile()); } else { if (this->HeaderFileReader->GetFileName() != c->GetFile()) { LogError(me_InternalError, << "Trying to open a different file for HeaderFileReader..." << gxsys_stl::endl << " class: " << GetFullyQualifiedNameForCPlusPlus(c).c_str() << gxsys_stl::endl << " c->GetFile(): " << c->GetFile() << gxsys_stl::endl << " this->HeaderFileReader->GetFileName(): " << this->HeaderFileReader->GetFileName() << gxsys_stl::endl ); } } return this->HeaderFileReader; } //---------------------------------------------------------------------------- void MummyGenerator::EmitMummyVersionComments(gxsys_ios::ostream &os, const char *lineCommentString) { gxsys_stl::string mummy_version(this->GetSettings()->GetMummyVersion()); if (!lineCommentString) { lineCommentString = "//"; } Emit(os, lineCommentString); Emit(os, "----------------------------------------------------------------------------\n"); Emit(os, lineCommentString); Emit(os, "\n"); Emit(os, lineCommentString); Emit(os, " This file was machine generated by:\n"); Emit(os, lineCommentString); Emit(os, " "); Emit(os, mummy_version.c_str()); Emit(os, "\n"); Emit(os, lineCommentString); Emit(os, "\n"); Emit(os, lineCommentString); Emit(os, " Manual changes to this file may be overwritten by the next build.\n"); Emit(os, lineCommentString); Emit(os, "\n"); } mummy-1.0.3/MummyGenerator.h0000644000175000017500000000577212120621217015662 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyGenerator.h // // Author(s) : David Cole // // Copyright (C) 2006-2007 Kitware, Inc. //---------------------------------------------------------------------------- #ifndef _MummyGenerator_h_ #define _MummyGenerator_h_ #include "MummyUtilities.h" // first mummy include for root classes #include "cableGenerator.h" // parent class #include "cableContext.h" // enum Context::Access #include "gxsys/ios/iosfwd" namespace cable { class Class; class Context; class FunctionType; class Method; class Type; } class MummyLineOrientedTextFileReader; class MummySettings; //---------------------------------------------------------------------------- /// /// Base class for all Mummy generators. /// class MummyGenerator : public cable::Generator { public: MummyGenerator(); virtual ~MummyGenerator(); //-------------------------------------------------------------------------- /// /// Get the associated settings object. /// /// Associated MummySettings object. virtual MummySettings* GetSettings(); //-------------------------------------------------------------------------- /// /// Set the associated settings object. /// /// MummySettings object virtual void SetSettings(MummySettings* settings); //-------------------------------------------------------------------------- /// /// Get the current target class. /// /// Associated Class object. virtual const cable::Class* GetTargetClass(); //-------------------------------------------------------------------------- /// /// Set the current target class. /// /// Class object virtual void SetTargetClass(const cable::Class *c); virtual bool FundamentalTypeIsWrappable(const cable::Type* t); virtual bool TypeIsWrappable(const cable::Type* t); virtual bool FunctionTypeIsWrappable(const cable::FunctionType* ft); virtual bool MethodIsWrappable(const cable::Method* m, const cable::Context::Access& access); virtual bool ClassIsWrappable(const cable::Class* c); //-------------------------------------------------------------------------- /// /// Get or create a header file reader. Only uses class 'c' on the first /// call. Subsequent calls retrieve the same reader instance. /// /// Class object /// Header file reader virtual MummyLineOrientedTextFileReader* GetHeaderFileReader(const cable::Class* c); virtual void EmitMummyVersionComments(gxsys_ios::ostream &os, const char *lineCommentString); private: MummySettings* Settings; const cable::Class* TargetClass; MummyLineOrientedTextFileReader* HeaderFileReader; MummyGenerator(const MummyGenerator&); //Not implemented MummyGenerator& operator=(const MummyGenerator&); //Not implemented }; #endif mummy-1.0.3/MummyLicense.txt0000644000175000017500000000053112120621217015672 0ustar mathieumathieu/// mummy /// /// C# (+?) wrapping tool developed by the team at Kitware, Inc. /// http://www.kitware.com /// /// Built using gccxml output and the Cable libs for in-memory /// source code object model representation. /// /// (C) 2006-2007 Kitware, Inc. /// All rights reserved. /// /// Official licensing for mummy is still to be determined... mummy-1.0.3/MummyLineOrientedTextFileReader.cxx0000644000175000017500000002440512120621217021452 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyLineOrientedTextFileReader.cxx 470 2009-06-12 17:43:02Z hoffman $ // // $Author: hoffman $ // $Date: 2009-06-12 13:43:02 -0400 (Fri, 12 Jun 2009) $ // $Revision: 470 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyLineOrientedTextFileReader.h" #include "MummyLog.h" #include "MummySettings.h" #include "gxsys/RegularExpression.hxx" #include "gxsys/ios/fstream" #include "gxsys/ios/sstream" //---------------------------------------------------------------------------- MummyLineOrientedTextFileReader::MummyLineOrientedTextFileReader() { //this->FileName; // correctly constructed empty //this->Lines; // correctly constructed empty this->ExcludeMarkedLines = false; //this->BeginExcludeRegex; // correctly constructed empty //this->EndExcludeRegex; // correctly constructed empty } //---------------------------------------------------------------------------- MummyLineOrientedTextFileReader::~MummyLineOrientedTextFileReader() { } //---------------------------------------------------------------------------- gxsys_stl::string MummyLineOrientedTextFileReader::GetFileName() { return this->FileName; } //---------------------------------------------------------------------------- void MummyLineOrientedTextFileReader::SetFileName(const char *filename) { if (filename) { this->FileName = filename; } else { this->FileName = ""; } this->Update(); } //---------------------------------------------------------------------------- bool MummyLineOrientedTextFileReader::GetExcludeMarkedLines() { return this->ExcludeMarkedLines; } //---------------------------------------------------------------------------- void MummyLineOrientedTextFileReader::SetExcludeMarkedLines(bool excludeMarkedLines) { this->ExcludeMarkedLines = excludeMarkedLines; } //---------------------------------------------------------------------------- gxsys_stl::string MummyLineOrientedTextFileReader::GetBeginExcludeRegex() { return this->BeginExcludeRegex; } //---------------------------------------------------------------------------- void MummyLineOrientedTextFileReader::SetBeginExcludeRegex(const gxsys_stl::string& beginExcludeRegex) { this->BeginExcludeRegex = beginExcludeRegex; } //---------------------------------------------------------------------------- gxsys_stl::string MummyLineOrientedTextFileReader::GetEndExcludeRegex() { return this->EndExcludeRegex; } //---------------------------------------------------------------------------- void MummyLineOrientedTextFileReader::SetEndExcludeRegex(const gxsys_stl::string& endExcludeRegex) { this->EndExcludeRegex = endExcludeRegex; } //---------------------------------------------------------------------------- void MummyLineOrientedTextFileReader::Update() { gxsys_ios::ifstream file(this->GetFileName().c_str()); this->Lines.clear(); if (file) { char line[4100]; bool trackBtxEtxLevel = !this->GetBeginExcludeRegex().empty() && !this->GetEndExcludeRegex().empty(); int btxEtxLevel = 0; bool isLineComment = false; gxsys::RegularExpression reLineComment; reLineComment.compile("^[\\t ]*//"); gxsys::RegularExpression reBTX; gxsys::RegularExpression reETX; if (trackBtxEtxLevel) { reBTX.compile(this->GetBeginExcludeRegex().c_str()); reETX.compile(this->GetEndExcludeRegex().c_str()); } // // Old hard-coded values were eerily similar to BTX/ETX regexes found in // the VTK source tree in Wrapping/vtkParse.l... ;) // //reBTX.compile("^[\\t ]*//BTX.*$"); //reETX.compile("^[\\t ]*//ETX.*$"); while (!file.eof()) { line[0] = 0; file.getline(line, 4099); isLineComment = reLineComment.find(line); if (trackBtxEtxLevel && reBTX.find(line)) { btxEtxLevel++; } this->Lines.push_back(LineData(line, isLineComment, btxEtxLevel)); if (trackBtxEtxLevel && reETX.find(line)) { btxEtxLevel--; } } } #if 0 // Dump it out with Trace to see what the settings and the output // data look like... This is a Print-method-in-waiting... // gxsys_stl::ostringstream oss; oss << "FileName: " << this->FileName << gxsys_stl::endl; oss << "ExcludeMarkedLines: " << this->ExcludeMarkedLines << gxsys_stl::endl; oss << "BeginExcludeRegex: " << this->BeginExcludeRegex << gxsys_stl::endl; oss << "EndExcludeRegex: " << this->EndExcludeRegex << gxsys_stl::endl; oss << "Lines:" << gxsys_stl::endl; unsigned int i = 1; gxsys_stl::vector::iterator itLines; for (itLines = this->Lines.begin(); itLines != this->Lines.end(); ++itLines) { LineData line = *itLines; // Comment? // if (line.IsLineComment) { oss << "C | "; } else { oss << " | "; } // BTX/ETX level: // if (line.BtxEtxLevel) { oss << line.BtxEtxLevel; oss << " | "; } else { oss << " | "; } // Line number, i - 4 digits with leading zeroes: // char f = oss.fill(); gxsys_stl::streamsize w = oss.width(); oss.fill('0'); oss.width(4); oss << i; oss.fill(f); oss.width(w); // The line itself: // oss << ": " << line.Line << gxsys_stl::endl; ++i; } Trace(oss.str().c_str()); #endif } //---------------------------------------------------------------------------- unsigned int MummyLineOrientedTextFileReader::GetNumberOfLines() { return static_cast(this->Lines.size()); } //---------------------------------------------------------------------------- gxsys_stl::string MummyLineOrientedTextFileReader::GetLine(unsigned int lineNumber) { if (lineNumber<1 || lineNumber>this->GetNumberOfLines()) { LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetLine"); return ""; } return this->Lines.at(lineNumber-1).Line; } //---------------------------------------------------------------------------- bool MummyLineOrientedTextFileReader::GetIsLineComment(unsigned int lineNumber) { if (lineNumber<1 || lineNumber>this->GetNumberOfLines()) { LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetIsLineComment"); return false; } return this->Lines.at(lineNumber-1).IsLineComment; } //---------------------------------------------------------------------------- int MummyLineOrientedTextFileReader::GetBtxEtxLevel(unsigned int lineNumber) { if (lineNumber<1 || lineNumber>this->GetNumberOfLines()) { LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetBtxEtxLevel"); return 0; } return this->Lines.at(lineNumber-1).BtxEtxLevel; } //---------------------------------------------------------------------------- bool MummyLineOrientedTextFileReader::IsLineExcluded(unsigned int lineNumber) { return this->GetExcludeMarkedLines() && this->GetBtxEtxLevel(lineNumber) > 0; } //---------------------------------------------------------------------------- void MummyLineOrientedTextFileReader::GetCommentBlockBefore(unsigned int lineNumber, gxsys_stl::vector& block, unsigned int smallestAcceptableLineNumber) { if (lineNumber<2 || lineNumber>this->GetNumberOfLines()) { LogWarning(mw_NoSuchLineNumber, "lineNumber out of range in GetCommentBlockBefore"); return; } // We seek the comment block before a class or method declaration in a // header file. Like this line-numbered example from vtkObject.h: // // 52: // 53: // Description: // 54: // Create an object with Debug turned off, modified time initialized // 55: // to zero, and reference counting on. // 56: static vtkObject *New(); // 57: // // If given lineNumber==56 as input, we should compute begin==53 and end==55 // and return the comment block as a vector of line strings from // begin to end inclusive... unsigned int begin = 0; unsigned int end = 0; unsigned int i = lineNumber; // Find the first comment before lineNumber, saving its index in 'end'. // If no line comments occur before lineNumber, end will be 0. // while (0 == end && i>1) { i--; if (GetIsLineComment(i) && 0==GetBtxEtxLevel(i)) { end = i; } } // Now find the first non-comment before end, saving the index of the comment // line *after* it in 'begin'. // if (0 != end) { while (0 == begin && i>1) { i--; if (!GetIsLineComment(i) && 0==GetBtxEtxLevel(i)) { begin = i + 1; } } // Didn't find a non-comment line before 'end'... Comment block must start // right at line 1. // if (0 == begin) { begin = 1; } } // If end==0 then there are no comment lines prior to lineNumber. // if (0 == end) { LogFileLineWarningMsg(this->FileName.c_str(), lineNumber, mw_UndocumentedEntity, "No comment lines prior to line " << lineNumber << ". Undocumented class or method?"); } else if (smallestAcceptableLineNumber > begin) { block.push_back(std::string("//Undocumented Block")); } else { gxsys_stl::string s; gxsys::RegularExpression reBeginsWithWhiteSpace; reBeginsWithWhiteSpace.compile("^([\\t ]*)[^\\t ].*"); size_t from = 0; size_t to = 0; for (i= begin; i<=end; ++i) { s = GetLine(i); if (reBeginsWithWhiteSpace.find(s)) { from = reBeginsWithWhiteSpace.match(1).size(); to = s.size() - from; s = s.substr(from, to); } block.push_back(s); } } } //---------------------------------------------------------------------------- void MummyLineOrientedTextFileReader::GetFirstCommentBlock(gxsys_stl::vector& block) { // Find the first non-comment line after the first comment line and use it // to call GetCommentBlockBefore... // unsigned int i = 1; unsigned int n = this->GetNumberOfLines(); bool foundFirstComment = false; for (i= 1; i<=n; ++i) { if (this->GetIsLineComment(i) && 0==GetBtxEtxLevel(i)) { foundFirstComment = true; } else if (foundFirstComment) { this->GetCommentBlockBefore(i+1, block, 1); break; } } } mummy-1.0.3/MummyLineOrientedTextFileReader.h0000644000175000017500000002017312120621217021075 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyLineOrientedTextFileReader.h // // Author(s) : David Cole // // Copyright (C) 2007 Kitware, Inc. //---------------------------------------------------------------------------- #ifndef _MummyLineOrientedTextFileReader_h_ #define _MummyLineOrientedTextFileReader_h_ #include "MummyUtilities.h" // first mummy include for root classes #include "gxsys/stl/string" #include "gxsys/stl/vector" //---------------------------------------------------------------------------- /// /// Internal, implementation detail class that caches information associated /// with a line in a line oriented text file. Used only internally by /// MummyLineOrientedTextFileReader. /// class LineData { public: LineData(const gxsys_stl::string &line, const bool isLineComment, const int btxEtxLevel) : Line(line), IsLineComment(isLineComment), BtxEtxLevel(btxEtxLevel) { } gxsys_stl::string Line; bool IsLineComment; int BtxEtxLevel; }; //---------------------------------------------------------------------------- /// /// Class that reads a text file and caches its lines and information about /// those lines for quick queries based on line numbers. Primarily used to /// look up code comment documentation blocks just prior to class and method /// declarations in C++ header files. Initialize by calling SetFileName. /// class MummyLineOrientedTextFileReader { public: MummyLineOrientedTextFileReader(); virtual ~MummyLineOrientedTextFileReader(); //-------------------------------------------------------------------------- /// /// Get the filename. /// /// Filename as a string. virtual gxsys_stl::string GetFileName(); //-------------------------------------------------------------------------- /// /// Set the filename. /// /// Filename virtual void SetFileName(const char *filename); //-------------------------------------------------------------------------- /// /// Get whether to exclude lines between beginExcludeRegex and /// endExcludeRegex matching lines when considering lines for documentation. /// /// Exclude flag. virtual bool GetExcludeMarkedLines(); //-------------------------------------------------------------------------- /// /// Set whether to exclude lines between beginExcludeRegex and /// endExcludeRegex matching lines when considering lines for documentation. /// /// Exclude flag. virtual void SetExcludeMarkedLines(bool excludeMarkedLines); //-------------------------------------------------------------------------- /// /// Get the regular expression that delineates a line as the beginning of /// a "marked as excluded" block. /// /// "Begin excluding" regular expression virtual gxsys_stl::string GetBeginExcludeRegex(); //-------------------------------------------------------------------------- /// /// Set the regular expression that delineates a line as the beginning of /// a "marked as excluded" block. /// /// "Begin excluding" regular /// expression /// virtual void SetBeginExcludeRegex(const gxsys_stl::string& beginExcludeRegex); //-------------------------------------------------------------------------- /// /// Get the regular expression that delineates a line as the end of /// a "marked as excluded" block. /// /// "End excluding" regular expression virtual gxsys_stl::string GetEndExcludeRegex(); //-------------------------------------------------------------------------- /// /// Set the regular expression that delineates a line as the end of /// a "marked as excluded" block. /// /// "End excluding" regular /// expression /// virtual void SetEndExcludeRegex(const gxsys_stl::string& endExcludeRegex); //-------------------------------------------------------------------------- /// /// Read the current text file and cache its lines for subsequent quick /// lookup by line number. /// This allows us to retrieve the /// comment blocks just prior to a given line number and allows us to parse /// and/or transfer the documentation from the source code to the generated /// code. /// virtual void Update(); //-------------------------------------------------------------------------- /// /// Retrieve the total number of lines currently cached. /// /// The total number of lines. virtual unsigned int GetNumberOfLines(); //-------------------------------------------------------------------------- /// /// Retrieve line number 'lineNumber' as a string from the currently cached /// text file. /// Valid 'lineNumber' values are 1 through GetNumberOfLines inclusive. /// /// 1-based line number /// The line as a string. Empty string if lineNumber is invalid. virtual gxsys_stl::string GetLine(unsigned int lineNumber); //-------------------------------------------------------------------------- /// /// Query if line number 'lineNumber' is a "line comment." /// Valid 'lineNumber' values are 1 through GetNumberOfLines inclusive. /// /// 1-based line number /// Whether the line is a comment. false if lineNumber is invalid. virtual bool GetIsLineComment(unsigned int lineNumber); //-------------------------------------------------------------------------- /// /// Get the current nesting level at line number 'lineNumber' of "//BTX - /// //ETX" style wrapper exclusion comments. This should be exactly 0 or 1 /// because the old VTK wrappers start ignoring at //BTX and do not resume /// wrapping until the closing //ETX occurs. /// Valid 'lineNumber' values are 1 through GetNumberOfLines inclusive. /// /// 1-based line number /// Whether the line is in between BTX and ETX markers. 0 if lineNumber is invalid. virtual int GetBtxEtxLevel(unsigned int lineNumber); //-------------------------------------------------------------------------- /// /// Query whether the given line number should be excluded based on the /// exclude flag and the line number's BtxEtx level. /// Valid 'lineNumber' values are 1 through GetNumberOfLines inclusive. /// /// 1-based line number /// Whether the line should be excluded. virtual bool IsLineExcluded(unsigned int lineNumber); //-------------------------------------------------------------------------- /// /// Retrieve the nearest preceding block of comment lines relative to line /// number 'lineNumber'. /// Valid 'lineNumber' values are 2 through GetNumberOfLines inclusive. /// /// 1-based line number /// vector of strings, one per line /// if the comment block happens before this line an Undocumented Block is returned virtual void GetCommentBlockBefore(unsigned int lineNumber, gxsys_stl::vector& block, unsigned int smallestAcceptableLineNumber); //-------------------------------------------------------------------------- /// /// Retrieve the first block of comment lines, if any, in the file. /// /// vector of strings, one per line virtual void GetFirstCommentBlock(gxsys_stl::vector& block); private: gxsys_stl::string FileName; gxsys_stl::vector Lines; bool ExcludeMarkedLines; gxsys_stl::string BeginExcludeRegex; gxsys_stl::string EndExcludeRegex; }; #endif // _MummyLineOrientedTextFileReader_h_ mummy-1.0.3/MummyLog.h0000644000175000017500000000630412120621217014445 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyLog.h // // Author(s) : David Cole // // Copyright (C) 2006-2009 Kitware, Inc. //---------------------------------------------------------------------------- #ifndef MummyLog_h #define MummyLog_h #include "MummyUtilities.h" // first mummy include for root classes #include "gxsys/ios/iostream" /// /// Log the message value via the global utility function LogMsg and emit it /// to the given stream. /// #define LogFileLineLabelledMsg(os, file, line, label, n, m) \ if (ShouldLogMsg(n)) \ { \ LogMsg(file, line, label, n); \ os << file << "(" << line << "): " << label << ": m" << n << ": " m << gxsys_ios::endl; \ } #define LogFileLineErrorMsg(file, line, n, m) \ LogFileLineLabelledMsg(gxsys_ios::cerr, file, line, "error", n, m) #define LogFileLineWarningMsg(file, line, n, m) \ LogFileLineLabelledMsg(gxsys_ios::cerr, file, line, "warning", n, m) #define LogFileLineInfoMsg(file, line, n, m) \ LogFileLineLabelledMsg(gxsys_ios::cout, file, line, "info", n, m) // n == number // m == (C++ stream-able) message or string literal // #define LogError(n, m) \ LogFileLineErrorMsg("# ", 0, n, m) #define LogWarning(n, m) \ LogFileLineWarningMsg("# ", 0, n, m) #define LogInfo(n, m) \ LogFileLineInfoMsg("# ", 0, n, m) #define LogVerboseInfo(m) \ if (this->GetSettings()->GetVerbose()) \ { \ LogInfo(mi_VerboseInfo, m); \ } // Error (me_), warning (mw_) and info (mi_) values. // // Add new error values to the end of the me_ segment, new warnings to the // end of the mw_ segment and new info values to the end of the mi_ segment. // That way, new builds of mummy will always have the same error and warning // values as previous builds... // // DO NOT be tempted to alphabetize this list. Or, if you are tempted, resist // it with all that is in you... Keep this list ordered the same within each // segment - always! // enum MummyLogMsgValues { // Error values segment: me_ErrorValueBase = 5000, me_InternalError, me_CouldNotOpen, me_CouldNotParse, me_CouldNotValidate, me_CouldNotWrap, me_MissingRequiredCommandLineArg, me_UnexpectedGccxmlInput, me_InvalidArg, me_MoreThanOneBaseClass, me_UnknownFundamentalType, me_NoClassWrappingSettings, me_EventMethodIncorrectReturnType, me_NoVirtualMethodsAllowed, me_UnknownMapToType, me_PureVirtualMethodNotAllowed, // Warning values segment: mw_WarningValueBase = 6000, mw_InternalWarning, mw_NoSuchLineNumber, mw_UndocumentedEntity, mw_DuplicateGeneratedName, mw_ReservedMethodName, mw_UnnamedEnum, mw_MultipleTargetInterfaces, mw_CouldNotWrap, mw_PropGetReturnsVoid, mw_PropGetNotConst, mw_PropSetReturnsNonVoid, mw_PropSetUnexpectedArgCount, mw_DefaultArgumentValuesIgnored, mw_WriteOnlyProperty, mw_MissingPropGetHint, mw_MissingPropSetHint, mw_PropGetHasArgs, mw_SeriousMissingPropGetHint, mw_SeriousMissingPropSetHint, mw_UnknownAttribute, mw_MultipleHints, mw_UnknownHintDataType, // Info values segment: mi_InfoValueBase = 7000, mi_Info, mi_VerboseInfo, mi_InfoRefArgEncountered, // Always keep this one last: // me_LastMummyLogMsgValue }; #endif mummy-1.0.3/MummyMain.cxx0000644000175000017500000000110112120621217015151 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyMain.cxx 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2006-2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyApplication.h" //---------------------------------------------------------------------------- int main(int argc, char *argv[]) { MummyApplication app; return app.Main(argc, argv); } mummy-1.0.3/MummyRuntime.h0000644000175000017500000000004212120621217015340 0ustar mathieumathieu#include "Runtime/MummyRuntime.h" mummy-1.0.3/MummySettings.cxx0000644000175000017500000012037212120621217016101 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummySettings.cxx 64 2008-03-08 18:10:51Z david.cole $ // // $Author: david.cole $ // $Date: 2008-03-08 13:10:51 -0500 (Sat, 08 Mar 2008) $ // $Revision: 64 $ // // Copyright (C) 2006-2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummySettings.h" #include "MummyDummyGenerator.h" #include "MummyLineOrientedTextFileReader.h" #include "MummyLog.h" #include "MummyVersion.h" #include "cableClass.h" #include "cableNamespace.h" #include "cableSourceRepresentation.h" #include "cableVariable.h" #include "cableXMLParser.h" #include "gxsys/CommandLineArguments.hxx" #include "gxsys/RegularExpression.hxx" #include "gxsys/ios/fstream" #include "gxsys/ios/iostream" #include "gxsys/stl/algorithm" #include "gxsys/stl/map" #include "gxsys/stl/set" #include "gxsys/stl/string" #include "gxsys/stl/vector" //---------------------------------------------------------------------------- static gxsys_stl::string Mummy_SVN_STATUS(Mummy_SVN_STATUS_ENCODED); //---------------------------------------------------------------------------- class MummySettingsInternals { public: gxsys_stl::string ArgsHelpString; gxsys_stl::string CsharpFile; gxsys_stl::string CsharpUnitTestFile; gxsys_stl::string ExportLayerFile; gxsys_stl::string GccxmlFile; gxsys_stl::string Group; gxsys_stl::string Header; bool Help; gxsys_stl::string Package; gxsys_stl::string PackageVersion; gxsys_stl::vector References; bool Run; gxsys_stl::string SettingsFile; gxsys_stl::vector SuppressedWarnings; gxsys_stl::map unwrappable_classes; gxsys_stl::vector unwrappable_patterns; bool Verbose; bool Version; gxsys_stl::map wrappable_classes; gxsys_stl::vector wrappable_patterns; }; //---------------------------------------------------------------------------- MummySettings::MummySettings() { this->Internals = new MummySettingsInternals; this->Reset(); } //---------------------------------------------------------------------------- MummySettings::~MummySettings() { delete this->Internals; } //---------------------------------------------------------------------------- void MummySettings::Reset() { this->Internals->ArgsHelpString = ""; this->Internals->CsharpFile = ""; this->Internals->CsharpUnitTestFile = ""; this->Internals->ExportLayerFile = ""; this->Internals->GccxmlFile = ""; this->Internals->Group = ""; this->Internals->Header = ""; this->Internals->Help = false; this->Internals->Package = ""; this->Internals->PackageVersion = ""; this->Internals->References.clear(); this->Internals->Run = true; this->Internals->SettingsFile = ""; this->Internals->SuppressedWarnings.clear(); this->Internals->unwrappable_classes.clear(); this->Internals->unwrappable_patterns.clear(); this->Internals->Verbose = false; this->Internals->Version = false; this->Internals->wrappable_classes.clear(); this->Internals->wrappable_patterns.clear(); } //---------------------------------------------------------------------------- void MummySettings::AddArgumentHandlers(gxsys::CommandLineArguments& arguments) { arguments.AddArgument( "--settings-file", gxsys::CommandLineArguments::SPACE_ARGUMENT, &this->Internals->SettingsFile, "Input file describing mummy configuration settings, including the set of wrapped classes. Required." ); arguments.AddArgument( "--csharp-file", gxsys::CommandLineArguments::SPACE_ARGUMENT, &this->Internals->CsharpFile, "C# output file. Default value is 'ClassName.cs' in the current directory." ); arguments.AddArgument( "--export-layer-file", gxsys::CommandLineArguments::SPACE_ARGUMENT, &this->Internals->ExportLayerFile, "C++ output file. Default value is 'ClassNameEL.cxx' in the current directory." ); arguments.AddArgument( "--csharp-unit-test-file", gxsys::CommandLineArguments::SPACE_ARGUMENT, &this->Internals->CsharpUnitTestFile, "C# output file. Default value is 'ClassNameUnitTest.cs' in the current directory." ); arguments.AddArgument( "--gccxml-file", gxsys::CommandLineArguments::SPACE_ARGUMENT, &this->Internals->GccxmlFile, "Input file (output of gccxml) describing class to be wrapped. Required." ); arguments.AddCallback( "--help", gxsys::CommandLineArguments::NO_ARGUMENT, MummySettings::DisplayHelp, this, "Display (this) detailed help information." ); arguments.AddArgument( "--verbose", gxsys::CommandLineArguments::NO_ARGUMENT, &this->Internals->Verbose, "Overwhelm me with output, I don't have enough reading material... ;)" ); arguments.AddCallback( "--version", gxsys::CommandLineArguments::NO_ARGUMENT, MummySettings::DisplayVersion, this, "Display the program version." ); arguments.AddArgument( "--suppress-warnings", gxsys::CommandLineArguments::MULTI_ARGUMENT, &this->Internals->SuppressedWarnings, "Space separated list of warning numbers to suppress." ); } //---------------------------------------------------------------------------- int MummySettings::Initialize(int argc, char *argv[]) { int err = 0; gxsys::CommandLineArguments arguments; this->Reset(); arguments.Initialize(argc, argv); this->AddArgumentHandlers(arguments); // Stash big help string in case we process "--help" during the Parse: this->Internals->ArgsHelpString = arguments.GetHelp(); if (!arguments.Parse()) { err = me_CouldNotParse; LogError(err, << "Could not parse all arguments in MummySettings::Initialize. Use --help for detailed help information."); } if (!err && this->ShouldRun()) { gxsys_stl::vector::iterator wit; for (wit = this->Internals->SuppressedWarnings.begin(); wit != this->Internals->SuppressedWarnings.end(); ++wit) { SuppressMsg(*wit); } if (this->Internals->SettingsFile == "") { err = me_MissingRequiredCommandLineArg; LogError(err, << "Required setting --settings-file not given. Use --help for detailed help information."); } if (!err && this->Internals->GccxmlFile == "") { err = me_MissingRequiredCommandLineArg; LogError(err, << "Required setting --gccxml-file not given. Use --help for detailed help information."); } if (!err && this->Internals->Verbose) { LogInfo(mi_VerboseInfo, << "--verbose mode turned on."); } if (!err) { err = this->ParseSettingsFile(this->GetSettingsFileName()); } } return err; } //---------------------------------------------------------------------------- void MummySettings::AddUnwrappableClass(const ClassWrappingSettings &cws) { this->Internals->unwrappable_classes.insert(gxsys_stl::make_pair(cws.name, cws)); } //---------------------------------------------------------------------------- void MummySettings::AddWrappableClass(const ClassWrappingSettings &cws) { this->Internals->wrappable_classes.insert(gxsys_stl::make_pair(cws.name, cws)); } //---------------------------------------------------------------------------- void MummySettings::AddUnwrappablePattern(const ClassWrappingSettings &cws) { this->Internals->unwrappable_patterns.push_back(cws); } //---------------------------------------------------------------------------- struct SortBySortKey { bool operator()(const ClassWrappingSettings& c1, const ClassWrappingSettings& c2) { return c1.sortkey < c2.sortkey; } }; //---------------------------------------------------------------------------- void MummySettings::AddWrappablePattern(const ClassWrappingSettings &cws) { this->Internals->wrappable_patterns.push_back(cws); // Sort the vector by sortkey now that a new pattern has been added: // gxsys_stl::sort(this->Internals->wrappable_patterns.begin(), this->Internals->wrappable_patterns.end(), SortBySortKey()); } //---------------------------------------------------------------------------- void MummySettings::AddReference(const char *name) { if (name) { this->Internals->References.push_back(gxsys_stl::string(name)); } } //---------------------------------------------------------------------------- void MummySettings::GetReferences(gxsys_stl::vector& references) { references.clear(); references.insert(references.begin(), this->Internals->References.begin(), this->Internals->References.end()); } //---------------------------------------------------------------------------- bool MummySettings::FindClassWrappingSettings(const char *name, ClassWrappingSettings* cws) { bool found = false; if (name) { gxsys_stl::map::iterator mit; gxsys_stl::vector::iterator vit; gxsys::RegularExpression re; gxsys_stl::string s(name); mit = this->Internals->wrappable_classes.find(s); if (mit != this->Internals->wrappable_classes.end()) { found = true; if (cws) { (*cws) = mit->second; } } for (vit = this->Internals->wrappable_patterns.begin(); !found && vit != this->Internals->wrappable_patterns.end(); ++vit) { re.compile(vit->pattern.c_str()); if (re.find(s.c_str())) { found = true; if (cws) { (*cws) = *vit; } } } } return found; } //---------------------------------------------------------------------------- bool MummySettings::ClassIsWrappable(const cable::Class *c) { bool wrappable = false; // A class is wrappable if: // - it is not excluded by name or pattern match *and* // - it is included by name or pattern match if (c) { gxsys_stl::map::iterator mit; gxsys_stl::vector::iterator vit; gxsys::RegularExpression re; gxsys_stl::string s(GetFullyQualifiedNameForCPlusPlus(c)); mit = this->Internals->unwrappable_classes.find(s); if (mit != this->Internals->unwrappable_classes.end()) { return false; } for (vit = this->Internals->unwrappable_patterns.begin(); vit != this->Internals->unwrappable_patterns.end(); ++vit) { re.compile(vit->pattern.c_str()); if (re.find(s.c_str())) { return false; } } wrappable = FindClassWrappingSettings(s.c_str(), 0); } return wrappable; } //---------------------------------------------------------------------------- #define READ_MummySettings_ATTS() \ { \ if (s=="beginExcludeRegex"){attBeginExcludeRegex = atts[i+1];knownAttribute = true;} \ if (s=="countedMethodsRegex"){attCountedMethodsRegex = atts[i+1];knownAttribute = true;} \ if (s=="csharpConstructorModifier"){attCsharpConstructorModifier = atts[i+1];knownAttribute = true;} \ if (s=="defaultDisposalMethod"){attDefaultDisposalMethod = atts[i+1];knownAttribute = true;} \ if (s=="defaultFactoryMethod"){attDefaultFactoryMethod = atts[i+1];knownAttribute = true;} \ if (s=="emitDefaultFactoryMethod"){attEmitDefaultFactoryMethod = atts[i+1];knownAttribute = true;} \ if (s=="endExcludeRegex"){attEndExcludeRegex = atts[i+1];knownAttribute = true;} \ if (s=="exceptionBaseClass"){attExceptionBaseClass = atts[i+1];knownAttribute = true;} \ if (s=="exceptionCloneMethod"){attExceptionCloneMethod = atts[i+1];knownAttribute = true;} \ if (s=="exceptionInclude"){attExceptionInclude = atts[i+1];knownAttribute = true;} \ if (s=="excludeMarkedLines"){attExcludeMarkedLines = atts[i+1];knownAttribute = true;} \ if (s=="externalHints"){attExternalHints = atts[i+1];knownAttribute = true;} \ if (s=="extraCsharpCode"){attExtraCsharpCode = atts[i+1];knownAttribute = true;} \ if (s=="extraCsharpUnitTestCode"){attExtraCsharpUnitTestCode = atts[i+1];knownAttribute = true;} \ if (s=="extraExportLayerCode"){attExtraExportLayerCode = atts[i+1];knownAttribute = true;} \ if (s=="getMummyTypeEntryMethod"){attGetMummyTypeEntryMethod = atts[i+1];knownAttribute = true;} \ if (s=="getRefCountMethod"){attGetRefCountMethod = atts[i+1];knownAttribute = true;} \ if (s=="partial"){attPartial = atts[i+1];knownAttribute = true;} \ if (s=="registerBaseClass"){attRegisterBaseClass = atts[i+1];knownAttribute = true;} \ if (s=="registerMethod"){attRegisterMethod = atts[i+1];knownAttribute = true;} \ if (s=="registerInclude"){attRegisterInclude = atts[i+1];knownAttribute = true;} \ if (s=="setMummyTypeEntryMethod"){attSetMummyTypeEntryMethod = atts[i+1];knownAttribute = true;} \ if (s=="shadow"){attShadow = atts[i+1];knownAttribute = true;} \ if (s=="unRegisterMethod"){attUnRegisterMethod = atts[i+1];knownAttribute = true;} \ if (s=="wrappedObjectBase"){attWrappedObjectBase = atts[i+1];knownAttribute = true;} \ } //---------------------------------------------------------------------------- namespace cable { class SettingsParser : public XMLParser { public: cableTypeMacro(SettingsParser, XMLParser); static Pointer New() { return new Self; } MummySettings* GetSettings() { return this->Settings; } void SetSettings(MummySettings* settings) { this->Settings = settings; } protected: virtual void StartElement(const char* name, const char** atts) { gxsys_stl::string elementName(name); gxsys_stl::string attName; gxsys_stl::string attPattern; gxsys_stl::string attSortKey; gxsys_stl::string attWrappable; gxsys_stl::string attCsharpConstructorModifier(""); gxsys_stl::string attDefaultDisposalMethod(""); gxsys_stl::string attDefaultFactoryMethod(""); gxsys_stl::string attEmitDefaultFactoryMethod("false"); gxsys_stl::string attCountedMethodsRegex(""); gxsys_stl::string attShadow("false"); gxsys_stl::string attExceptionBaseClass(""); gxsys_stl::string attExceptionCloneMethod(""); gxsys_stl::string attExceptionInclude(""); gxsys_stl::string attExternalHints(""); gxsys_stl::string attExtraCsharpCode(""); gxsys_stl::string attExtraCsharpUnitTestCode(""); gxsys_stl::string attExtraExportLayerCode(""); gxsys_stl::string attPartial("false"); gxsys_stl::string attRegisterMethod(""); gxsys_stl::string attUnRegisterMethod(""); gxsys_stl::string attRegisterBaseClass(""); gxsys_stl::string attRegisterInclude(""); gxsys_stl::string attGetRefCountMethod(""); gxsys_stl::string attGetMummyTypeEntryMethod(""); gxsys_stl::string attSetMummyTypeEntryMethod(""); gxsys_stl::string attExcludeMarkedLines("false"); gxsys_stl::string attBeginExcludeRegex(""); gxsys_stl::string attEndExcludeRegex(""); gxsys_stl::string attWrappedObjectBase(""); gxsys_stl::string s; bool knownAttribute = false; if (elementName == "Class") { for (unsigned int i=0; atts[i] && atts[i+1]; i+=2) { s = atts[i]; knownAttribute = false; if (s=="name"){attName = atts[i+1];knownAttribute = true;} if (s=="wrappable"){attWrappable = atts[i+1];knownAttribute = true;} READ_MummySettings_ATTS(); if (!knownAttribute) { LogWarning(mw_UnknownAttribute, "Unknown XML attribute '" << elementName << "/@" << s << "'"); } } ClassWrappingSettings cws( attName, attPattern, attSortKey, attDefaultFactoryMethod, attEmitDefaultFactoryMethod == "false" ? false : true, attCountedMethodsRegex, attDefaultDisposalMethod, attShadow == "false" ? false : true, attExternalHints, attExtraExportLayerCode, attExtraCsharpCode, attExtraCsharpUnitTestCode, attCsharpConstructorModifier, attRegisterMethod, attUnRegisterMethod, attGetRefCountMethod, attRegisterBaseClass, attRegisterInclude, attGetMummyTypeEntryMethod, attSetMummyTypeEntryMethod, attExcludeMarkedLines == "false" ? false : true, attBeginExcludeRegex, attEndExcludeRegex, attPartial == "false" ? false : true, attExceptionBaseClass, attExceptionCloneMethod, attExceptionInclude, attWrappedObjectBase ); if (attWrappable == "false") { this->GetSettings()->AddUnwrappableClass(cws); } else { this->GetSettings()->AddWrappableClass(cws); } } if (elementName == "ClassPattern") { for (unsigned int i=0; atts[i] && atts[i+1]; i+=2) { s = atts[i]; knownAttribute = false; if (s=="pattern"){attPattern = atts[i+1];knownAttribute = true;} if (s=="wrappable"){attWrappable = atts[i+1];knownAttribute = true;} if (s=="sortkey"){attSortKey = atts[i+1];knownAttribute = true;} READ_MummySettings_ATTS(); if (!knownAttribute) { LogWarning(mw_UnknownAttribute, "Unknown XML attribute '" << elementName << "/@" << s << "'"); } } ClassWrappingSettings cws( attName, attPattern, attSortKey, attDefaultFactoryMethod, attEmitDefaultFactoryMethod == "false" ? false : true, attCountedMethodsRegex, attDefaultDisposalMethod, attShadow == "false" ? false : true, attExternalHints, attExtraExportLayerCode, attExtraCsharpCode, attExtraCsharpUnitTestCode, attCsharpConstructorModifier, attRegisterMethod, attUnRegisterMethod, attGetRefCountMethod, attRegisterBaseClass, attRegisterInclude, attGetMummyTypeEntryMethod, attSetMummyTypeEntryMethod, attExcludeMarkedLines == "false" ? false : true, attBeginExcludeRegex, attEndExcludeRegex, attPartial == "false" ? false : true, attExceptionBaseClass, attExceptionCloneMethod, attExceptionInclude, attWrappedObjectBase ); if (attWrappable == "false") { this->GetSettings()->AddUnwrappablePattern(cws); } else { this->GetSettings()->AddWrappablePattern(cws); } } if (elementName == "Reference") { for (unsigned int i=0; atts[i] && atts[i+1]; i+=2) { s = atts[i]; knownAttribute = false; if (s=="name"){attName = atts[i+1];knownAttribute = true;} if (!knownAttribute) { LogWarning(mw_UnknownAttribute, "Unknown XML attribute '" << elementName << "/@" << s << "'"); } } this->GetSettings()->AddReference(attName.c_str()); } } private: MummySettings *Settings; }; } //---------------------------------------------------------------------------- int MummySettings::ParseSettingsFile(const char *filename) { int err = 0; // The settings file shall be an XML file that lists classes explicitly // declared as wrapped or not, something like this: // // // // // // // Where the name of the class is the fully qualified C++ class name and // the only valid values for the wrapped attribute are the lower case // boolean constants "true" and "false". if (this->GetVerbose()) { LogInfo(mi_VerboseInfo, << "Using --settings-file '" << filename << "'"); } gxsys_ios::ifstream inFile(filename, std::ios_base::in|std::ios_base::binary); if (!inFile) { err = me_CouldNotOpen; LogFileLineErrorMsg(filename, 1, err, << "Could not open file: '" << filename << "'"); } if (!err) { cable::SettingsParser::Pointer parser = cable::SettingsParser::New(); parser->SetStream(&inFile); parser->SetSettings(this); if(!parser->Parse()) { err = me_CouldNotParse; LogFileLineErrorMsg(filename, 1, err, << "Could not parse file: '" << filename << "'"); } parser->SetStream(0); parser->SetSettings(0); inFile.close(); } return err; } //---------------------------------------------------------------------------- bool ParseName(const char* name, gxsys_stl::string& result) { gxsys_stl::string group = name; gxsys_stl::string::size_type l = group.find('"'); gxsys_stl::string::size_type r = group.rfind('"'); if((l != gxsys_stl::string::npos) && (r != gxsys_stl::string::npos) && (r > l)) { result = group.substr(l+1, r-l-1); return true; } return false; } //---------------------------------------------------------------------------- bool GetGroupAndPackageInformation(cable::Namespace* cns, gxsys_stl::string& groupName, gxsys_stl::vector& groupsNames, gxsys_stl::string& packageName, gxsys_stl::string& packageVersion, gxsys_stl::string& headerName, gxsys_stl::string& configFile) { // Find the group, if any. const cable::Variable* group = 0; cable::Context::Iterator lower = cns->LowerBound("group"); cable::Context::Iterator upper = cns->UpperBound("group"); if (lower != upper) { group = cable::Variable::SafeDownCast(*lower); if (!group) { LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::group is not a variable."); return false; } } // Find the groups list, if any. const cable::Variable* groups = 0; lower = cns->LowerBound("groups"); upper = cns->UpperBound("groups"); if (lower != upper) { groups = cable::Variable::SafeDownCast(*lower); if (!groups) { LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::groups is not a variable."); return false; } } // Find the package name, if any. const cable::Variable* package = 0; lower = cns->LowerBound("package"); upper = cns->UpperBound("package"); if (lower != upper) { package = cable::Variable::SafeDownCast(*lower); if (!package) { LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::package is not a variable."); return false; } } // Find the package version, if any. const cable::Variable* package_version = 0; lower = cns->LowerBound("package_version"); upper = cns->UpperBound("package_version"); if (lower != upper) { package_version = cable::Variable::SafeDownCast(*lower); if (!package_version) { LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::package_version is not a variable."); return false; } } // Find the header, if any. const cable::Variable* header = 0; lower = cns->LowerBound("header"); upper = cns->UpperBound("header"); if (lower != upper) { header = cable::Variable::SafeDownCast(*lower); if (!header) { LogError(me_UnexpectedGccxmlInput, << "Identifier _cable_::header is not a variable."); return false; } } // Parse the strings out of the found entities: // if (group) { if (!ParseName(group->GetInitializer(), groupName)) { LogError(me_CouldNotParse, << "Error parsing group name."); return false; } // Hold on to the name of the configuration file. configFile = group->GetFile(); } if (package && !ParseName(package->GetInitializer(), packageName)) { LogError(me_CouldNotParse, << "Error parsing package name."); return false; } if (package_version && !ParseName(package_version->GetInitializer(), packageVersion)) { LogError(me_CouldNotParse, << "Error parsing package_version string."); return false; } if (groups) { gxsys_stl::string gl = groups->GetInitializer(); gxsys_stl::string::size_type lpos = gl.find('"'); while((lpos != gxsys_stl::string::npos) && (lpos < gl.length())) { gxsys_stl::string::size_type rpos = gl.find_first_of(",}", lpos); gxsys_stl::string result; if((rpos == gxsys_stl::string::npos) || !ParseName(gl.substr(lpos, rpos-lpos).c_str(), result)) { LogError(me_CouldNotParse, << "Error parsing groups list."); return false; } groupsNames.push_back(result); lpos = rpos+1; } } if (header) { if (!ParseName(header->GetInitializer(), headerName)) { LogError(me_CouldNotParse, << "Error parsing header name."); return false; } } return true; } //---------------------------------------------------------------------------- int MummySettings::ProcessSource(cable::SourceRepresentation* sr) { int err = 0; if (!sr) { LogError(me_InvalidArg, << "NULL pointer!"); return me_InvalidArg; } gxsys_stl::string s; const cable::Namespace* gns = sr->GetGlobalNamespace(); // Look inside the _cable_ namespace for package, packageversion and // group settings: // cable::Context::Iterator lower = gns->LowerBound("_cable_"); cable::Context::Iterator upper = gns->UpperBound("_cable_"); cable::Namespace* cns = 0; if (lower != upper) { cns = cable::Namespace::SafeDownCast(*lower); } if (!cns) { LogError(me_UnexpectedGccxmlInput, << "No _cable_ namespace."); return me_UnexpectedGccxmlInput; } gxsys_stl::string group; gxsys_stl::vector groups; gxsys_stl::string package; gxsys_stl::string packageVersion; gxsys_stl::string header; gxsys_stl::string configFile; GetGroupAndPackageInformation(cns, group, groups, package, packageVersion, header, configFile); if (group.size() == 0) { if (package.size() == 0) { LogError(me_UnexpectedGccxmlInput, << "No group or package name specified."); return me_UnexpectedGccxmlInput; } } // Save for when clients query us later: // this->Internals->Group = group; this->Internals->Header = header; this->Internals->Package = package; this->Internals->PackageVersion = packageVersion; return err; } //---------------------------------------------------------------------------- static void IncreaseCoverage(MummySettings *settings) { // This function exists only to add test calls to functions that are // otherwise not commonly called so that they get some sort of coverage // on coverage dashboards... // Trace("IncreaseCoverage\n"); MummyDummyGenerator mg; mg.FundamentalTypeIsWrappable(0); mg.TypeIsWrappable(0); mg.FunctionTypeIsWrappable(0); mg.MethodIsWrappable(0, cable::Context::Public); mg.ClassIsWrappable(0); mg.GenerateWrappers(); GetMostRecentErrorValue(); GetNthErrorValue(-10); GetNthErrorValue(0); // valid if there have been any errors... GetNthErrorValue(GetErrorCount()-1); // valid if there have been any errors... GetNthErrorValue(GetErrorCount()); GetNthErrorValue(GetErrorCount()+10); // Can't do this... then the test that calls this code fails because there // was an "error"...... // //LogError(me_InternalError, // << "This is not really an error." << gxsys_ios::endl // << " This is IncreaseCoverage increasing the coverage of the" << gxsys_ios::endl // << " MummyUtilities error functions..." // ); //GetNthErrorValue(-10); //GetNthErrorValue(0); // valid if there have been any errors... //GetNthErrorValue(GetErrorCount()-1); // valid if there have been any errors... //GetNthErrorValue(GetErrorCount()); //GetNthErrorValue(GetErrorCount()+10); EncodeStringForXml(0); EncodeStringForXml(""); settings->GetHeader(); settings->GetPackageVersion(); MummyLineOrientedTextFileReader reader; reader.SetFileName(0); } //---------------------------------------------------------------------------- int MummySettings::DisplayHelp(const char* argument, const char* value, void* call_data) { MummySettings *settings = (MummySettings *) call_data; DisplayVersion(argument, value, call_data); // If run under a ctest driven dashboard test, emit the string that tells // ctest not to truncate the test output: // if (getenv("DART_TEST_FROM_DART")) { gxsys_ios::cout << gxsys_ios::endl; gxsys_ios::cout << "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)" << gxsys_ios::endl; } gxsys_ios::cout << gxsys_ios::endl; gxsys_ios::cout << "Command line options:" << gxsys_ios::endl; gxsys_ios::cout << settings->Internals->ArgsHelpString << gxsys_ios::endl; if (!Mummy_SVN_STATUS.empty()) { gxsys_ios::cout << gxsys_ios::endl; gxsys_ios::cout << "svn status (retrieved at CMake configure time):" << gxsys_ios::endl; gxsys_ios::cout << "===============================================" << gxsys_ios::endl; gxsys_ios::cout << Mummy_SVN_STATUS.c_str() << gxsys_ios::endl; gxsys_ios::cout << gxsys_ios::endl; } IncreaseCoverage(settings); settings->Internals->Help = true; settings->Internals->Run = false; return 1; } //---------------------------------------------------------------------------- int MummySettings::DisplayVersion(const char*, const char*, void* call_data) { MummySettings *settings = (MummySettings *) call_data; gxsys_ios::cout << settings->GetMummyVersion() << gxsys_ios::endl; settings->Internals->Version = true; settings->Internals->Run = false; return 1; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetMummyVersion() { return Mummy_FULL_VERSION_STRING; } //---------------------------------------------------------------------------- const char *MummySettings::GetSettingsFileName() { return this->Internals->SettingsFile.c_str(); } //---------------------------------------------------------------------------- const char *MummySettings::GetCsharpFileName() { return this->Internals->CsharpFile.c_str(); } //---------------------------------------------------------------------------- const char *MummySettings::GetExportLayerFileName() { return this->Internals->ExportLayerFile.c_str(); } //---------------------------------------------------------------------------- const char *MummySettings::GetCsharpUnitTestFileName() { return this->Internals->CsharpUnitTestFile.c_str(); } //---------------------------------------------------------------------------- const char *MummySettings::GetGccxmlFileName() { return this->Internals->GccxmlFile.c_str(); } //---------------------------------------------------------------------------- const char *MummySettings::GetGroup() { return this->Internals->Group.c_str(); } //---------------------------------------------------------------------------- const char *MummySettings::GetHeader() { return this->Internals->Header.c_str(); } //---------------------------------------------------------------------------- const char *MummySettings::GetPackage() { return this->Internals->Package.c_str(); } //---------------------------------------------------------------------------- const char *MummySettings::GetPackageVersion() { return this->Internals->PackageVersion.c_str(); } //---------------------------------------------------------------------------- bool MummySettings::ShouldRun() { return this->Internals->Run; } //---------------------------------------------------------------------------- bool MummySettings::GetVerbose() { return this->Internals->Verbose; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetCsharpFileName(const cable::Class* c) { gxsys_stl::string s(this->GetCsharpFileName()); if (s == "") { s = c->GetName(); s += ".cs"; } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetExportLayerFileName(const cable::Class* c) { gxsys_stl::string s(this->GetExportLayerFileName()); if (s == "") { s = c->GetName(); s += "EL.cxx"; } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetCsharpUnitTestFileName(const cable::Class* c) { gxsys_stl::string s(this->GetCsharpUnitTestFileName()); if (s == "") { s = c->GetName(); s += "UnitTest.cs"; } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetCsharpConstructorModifier(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.csharpConstructorModifier; } else { s = "ERROR_NoCsharpConstructorModifier"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetFactoryMethod(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.defaultFactoryMethod; } else { s = "ERROR_NoFactoryMethod"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- bool MummySettings::GetEmitDefaultFactoryMethod(const cable::Class* c) { bool b = false; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { b = cws.emitDefaultFactoryMethod; } else { LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return b; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetCountedMethodsRegex(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.countedMethodsRegex; } else { s = "ERROR_NoCountedMethodsRegex"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetDisposalMethod(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.defaultDisposalMethod; } else { s = "ERROR_NoDisposalMethod"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- bool MummySettings::GetUseShadow(const cable::Class* c) { bool shadow = false; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { shadow = cws.shadow; } else { LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return shadow; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetExternalHints(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.externalHints; } else { s = "ERROR_NoExternalHints"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetExtraCsharpCode(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.extraCsharpCode; } else { s = "ERROR_NoExtraCsharpCode"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetExtraExportLayerCode(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.extraExportLayerCode; } else { s = "ERROR_NoExtraExportLayerCode"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetExtraCsharpUnitTestCode(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.extraCsharpUnitTestCode; } else { s = "ERROR_NoExtraCsharpUnitTestCode"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetRegisterMethod(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.registerMethod; } else { s = "ERROR_NoRegisterMethod"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetUnRegisterMethod(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.unRegisterMethod; } else { s = "ERROR_NoUnRegisterMethod"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetRegisterBaseClass(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.registerBaseClass; } else { s = "ERROR_NoRegisterBaseClass"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string MummySettings::GetRegisterInclude(const cable::Class* c) { gxsys_stl::string s; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { s = cws.registerInclude; } else { s = "ERROR_NoRegisterInclude"; LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return s; } //---------------------------------------------------------------------------- bool MummySettings::GetPartialClass(const cable::Class* c) { bool partial = false; ClassWrappingSettings cws; if (FindClassWrappingSettings(GetFullyQualifiedNameForCPlusPlus(c).c_str(), &cws)) { partial = cws.partialClass; } else { LogError(me_NoClassWrappingSettings, << "Could not find class wrapping settings for class '" << GetFullyQualifiedNameForCPlusPlus(c).c_str() << "'"); } return partial; } mummy-1.0.3/MummySettings.h0000644000175000017500000001514112120621217015523 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummySettings.h // // Author(s) : David Cole // // Copyright (C) 2006-2007 Kitware, Inc. //---------------------------------------------------------------------------- #include "MummyUtilities.h" // first mummy include for root classes #include "gxsys/stl/string" #include "gxsys/stl/vector" class MummySettingsInternals; namespace cable { class Class; class SourceRepresentation; } namespace gxsys { class CommandLineArguments; } //---------------------------------------------------------------------------- class ClassWrappingSettings { public: gxsys_stl::string name; gxsys_stl::string pattern; gxsys_stl::string sortkey; gxsys_stl::string defaultFactoryMethod; bool emitDefaultFactoryMethod; gxsys_stl::string countedMethodsRegex; gxsys_stl::string defaultDisposalMethod; bool shadow; gxsys_stl::string externalHints; gxsys_stl::string extraExportLayerCode; gxsys_stl::string extraCsharpCode; gxsys_stl::string extraCsharpUnitTestCode; gxsys_stl::string csharpConstructorModifier; gxsys_stl::string registerMethod; gxsys_stl::string unRegisterMethod; gxsys_stl::string getRefCountMethod; gxsys_stl::string registerBaseClass; gxsys_stl::string registerInclude; gxsys_stl::string getMummyTypeEntryMethod; gxsys_stl::string setMummyTypeEntryMethod; bool excludeMarkedLines; gxsys_stl::string beginExcludeRegex; gxsys_stl::string endExcludeRegex; bool partialClass; gxsys_stl::string exceptionBaseClass; gxsys_stl::string exceptionCloneMethod; gxsys_stl::string exceptionInclude; gxsys_stl::string wrappedObjectBase; ClassWrappingSettings( gxsys_stl::string nm = gxsys_stl::string(""), gxsys_stl::string pat = gxsys_stl::string(""), gxsys_stl::string sk = gxsys_stl::string(""), gxsys_stl::string fm = gxsys_stl::string(""), bool edfm = false, gxsys_stl::string cmr = gxsys_stl::string(""), gxsys_stl::string dm = gxsys_stl::string(""), bool sh = false, gxsys_stl::string exH = gxsys_stl::string(""), gxsys_stl::string exEL = gxsys_stl::string(""), gxsys_stl::string exCS = gxsys_stl::string(""), gxsys_stl::string exCSUT = gxsys_stl::string(""), gxsys_stl::string csCM = gxsys_stl::string(""), gxsys_stl::string rm = gxsys_stl::string(""), gxsys_stl::string um = gxsys_stl::string(""), gxsys_stl::string grcm = gxsys_stl::string(""), gxsys_stl::string rbc = gxsys_stl::string(""), gxsys_stl::string ri = gxsys_stl::string(""), gxsys_stl::string gmtem = gxsys_stl::string(""), gxsys_stl::string smtem = gxsys_stl::string(""), bool eml = false, gxsys_stl::string ber = gxsys_stl::string(""), gxsys_stl::string eer = gxsys_stl::string(""), bool partial = false, gxsys_stl::string ebc = gxsys_stl::string(""), gxsys_stl::string ecm = gxsys_stl::string(""), gxsys_stl::string ei = gxsys_stl::string(""), gxsys_stl::string wob = gxsys_stl::string("") ) : name(nm), pattern(pat), sortkey(sk), defaultFactoryMethod(fm), emitDefaultFactoryMethod(edfm), countedMethodsRegex(cmr), defaultDisposalMethod(dm), shadow(sh), externalHints(exH), extraExportLayerCode(exEL), extraCsharpCode(exCS), extraCsharpUnitTestCode(exCSUT), csharpConstructorModifier(csCM), registerMethod(rm), unRegisterMethod(um), getRefCountMethod(grcm), registerBaseClass(rbc), registerInclude(ri), getMummyTypeEntryMethod(gmtem), setMummyTypeEntryMethod(smtem), excludeMarkedLines(eml), beginExcludeRegex(ber), endExcludeRegex(eer), partialClass(partial), exceptionBaseClass(ebc), exceptionCloneMethod(ecm), exceptionInclude(ei), wrappedObjectBase(wob) { } }; //---------------------------------------------------------------------------- class MummySettings { public: MummySettings(); virtual ~MummySettings(); virtual int Initialize(int argc, char *argv[]); virtual int ParseSettingsFile(const char *filename); virtual int ProcessSource(cable::SourceRepresentation* sr); static int DisplayHelp(const char* argument, const char* value, void* call_data); static int DisplayVersion(const char* argument, const char* value, void* call_data); virtual const char *GetSettingsFileName(); virtual const char *GetCsharpFileName(); virtual const char *GetExportLayerFileName(); virtual const char *GetCsharpUnitTestFileName(); virtual const char *GetGccxmlFileName(); virtual const char *GetGroup(); virtual const char *GetHeader(); virtual const char *GetPackage(); virtual const char *GetPackageVersion(); virtual bool ShouldRun(); virtual bool GetVerbose(); virtual gxsys_stl::string GetMummyVersion(); virtual void AddUnwrappableClass(const ClassWrappingSettings &cws); virtual void AddWrappableClass(const ClassWrappingSettings &cws); virtual void AddUnwrappablePattern(const ClassWrappingSettings &cws); virtual void AddWrappablePattern(const ClassWrappingSettings &cws); virtual bool FindClassWrappingSettings(const char *name, ClassWrappingSettings* cws); virtual void AddReference(const char *name); virtual void GetReferences(gxsys_stl::vector& references); virtual bool ClassIsWrappable(const cable::Class *c); virtual gxsys_stl::string GetCsharpFileName(const cable::Class* c); virtual gxsys_stl::string GetExportLayerFileName(const cable::Class* c); virtual gxsys_stl::string GetCsharpUnitTestFileName(const cable::Class* c); virtual gxsys_stl::string GetCsharpConstructorModifier(const cable::Class* c); virtual gxsys_stl::string GetFactoryMethod(const cable::Class* c); virtual bool GetEmitDefaultFactoryMethod(const cable::Class* c); virtual gxsys_stl::string GetCountedMethodsRegex(const cable::Class* c); virtual gxsys_stl::string GetDisposalMethod(const cable::Class* c); virtual bool GetUseShadow(const cable::Class* c); virtual gxsys_stl::string GetExternalHints(const cable::Class* c); virtual gxsys_stl::string GetExtraCsharpCode(const cable::Class* c); virtual gxsys_stl::string GetExtraExportLayerCode(const cable::Class* c); virtual gxsys_stl::string GetExtraCsharpUnitTestCode(const cable::Class* c); virtual gxsys_stl::string GetRegisterMethod(const cable::Class* c); virtual gxsys_stl::string GetUnRegisterMethod(const cable::Class* c); virtual gxsys_stl::string GetRegisterBaseClass(const cable::Class* c); virtual gxsys_stl::string GetRegisterInclude(const cable::Class* c); virtual bool GetPartialClass(const cable::Class* c); private: void AddArgumentHandlers(gxsys::CommandLineArguments& arguments); void Reset(); MummySettingsInternals *Internals; }; mummy-1.0.3/MummyTesting/0000755000175000017500000000000012120621217015165 5ustar mathieumathieumummy-1.0.3/MummyTesting/CMakeLists.txt0000644000175000017500000000161012120621217017723 0ustar mathieumathieuIF(csc_EXECUTABLE) # "/?" works with csc from Microsoft and its variations (gmcs and friends) # from Mono # ADD_TEST(HelpSmokeTest-csc "${csc_EXECUTABLE}" "/?") ENDIF(csc_EXECUTABLE) IF(gccxml_EXECUTABLE) ADD_TEST(HelpSmokeTest-gccxml "${gccxml_EXECUTABLE}" "--help") ADD_TEST(VersionSmokeTest-gccxml "${gccxml_EXECUTABLE}" "--version") ENDIF(gccxml_EXECUTABLE) IF(mono_EXECUTABLE) ADD_TEST(HelpSmokeTest-mono "${mono_EXECUTABLE}" "--help") ADD_TEST(VersionSmokeTest-mono "${mono_EXECUTABLE}" "--version") ENDIF(mono_EXECUTABLE) IF(EXECUTABLE_OUTPUT_PATH) SET(exefile ${EXECUTABLE_OUTPUT_PATH}/mummy) ELSE(EXECUTABLE_OUTPUT_PATH) SET(exefile mummy) ENDIF(EXECUTABLE_OUTPUT_PATH) ADD_TEST(HelpSmokeTest-mummy "${exefile}" "--help") ADD_TEST(VersionSmokeTest-mummy "${exefile}" "--version") ADD_SUBDIRECTORY(HandCrafted) ADD_SUBDIRECTORY(Simple) ADD_SUBDIRECTORY(SuppressWarnings) mummy-1.0.3/MummyTesting/HandCrafted/0000755000175000017500000000000012120621217017330 5ustar mathieumathieumummy-1.0.3/MummyTesting/HandCrafted/CMakeLists.txt0000644000175000017500000000437012120621217022074 0ustar mathieumathieu# Build as is, force static lib: # ADD_LIBRARY(handCraftedLib STATIC simple.cxx) # Forcing static lib on Linux means we have to use the -fPIC flag for compiling # sources in the target: # IF(NOT WIN32 AND NOT APPLE) SET_TARGET_PROPERTIES(handCraftedLib PROPERTIES COMPILE_FLAGS "-fPIC") ENDIF(NOT WIN32 AND NOT APPLE) # Build wrapper layers: # # Both gccxml_EXECUTABLE and mummy_EXECUTABLE should have been found by parent # project... verify: # IF(NOT gccxml_EXECUTABLE) MESSAGE(FATAL_ERROR "error: no gccxml_EXECUTABLE - cannot build wrapper layers") ENDIF(NOT gccxml_EXECUTABLE) IF(NOT mummy_EXECUTABLE) MESSAGE(FATAL_ERROR "error: no mummy_EXECUTABLE - cannot build wrapper layers") ENDIF(NOT mummy_EXECUTABLE) SET(gccxml_output "${CMAKE_CURRENT_BINARY_DIR}/simple_gccxml.xml") SET(mummy_exportlayer_output "${CMAKE_CURRENT_BINARY_DIR}/simple_exportlayer.cxx") SET(mummy_csharp_output "${CMAKE_CURRENT_BINARY_DIR}/handCraftedSimple.cs") SET(mummy_settings "${CMAKE_CURRENT_SOURCE_DIR}/handCraftedMummySettings.xml") CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/handCraftedSimple.cs" "${CMAKE_CURRENT_BINARY_DIR}/handCraftedSimpleExtra.cs" @ONLY ) CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/simple_gccxml.cxx.in" "${CMAKE_CURRENT_BINARY_DIR}/simple_gccxml.cxx" @ONLY ) ADD_CUSTOM_COMMAND( OUTPUT ${gccxml_output} COMMAND ${gccxml_EXECUTABLE} ARGS -fxml=${gccxml_output} -fxml-start=_cable_ -I${CMAKE_CURRENT_SOURCE_DIR} -DCABLE_CONFIGURATION --gccxml-compiler ${CMAKE_CXX_COMPILER} ${CMAKE_CURRENT_BINARY_DIR}/simple_gccxml.cxx DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/simple_gccxml.cxx ${CMAKE_CURRENT_SOURCE_DIR}/simple.h ${gccxml_EXECUTABLE} ) ADD_CUSTOM_COMMAND( OUTPUT ${mummy_csharp_output} ${mummy_exportlayer_output} COMMAND ${mummy_EXECUTABLE} ARGS --settings-file ${mummy_settings} --gccxml-file ${gccxml_output} --csharp-file ${mummy_csharp_output} --export-layer-file ${mummy_exportlayer_output} DEPENDS ${mummy_settings} ${gccxml_output} ${mummy_EXECUTABLE} ) # Build the "export-layer" library: # ADD_LIBRARY(handCraftedExportLayer SHARED ${mummy_exportlayer_output}) TARGET_LINK_LIBRARIES(handCraftedExportLayer handCraftedLib Kitware.mummy.Runtime.Unmanaged ) mummy-1.0.3/MummyTesting/HandCrafted/handCraftedMummySettings.xml0000644000175000017500000000020212120621217025015 0ustar mathieumathieu mummy-1.0.3/MummyTesting/HandCrafted/handCraftedSimple.cs0000644000175000017500000000012212120621217023227 0ustar mathieumathieu public string HandCraftedStringMethod() { return "HandCraftedString"; } mummy-1.0.3/MummyTesting/HandCrafted/simple.cxx0000644000175000017500000000010112120621217021335 0ustar mathieumathieu#include "simple.h" simple::simple() { } simple::~simple() { } mummy-1.0.3/MummyTesting/HandCrafted/simple.h0000644000175000017500000000010612120621217020767 0ustar mathieumathieu// comment class simple { public: simple(); virtual ~simple(); }; mummy-1.0.3/MummyTesting/HandCrafted/simple_gccxml.cxx.in0000644000175000017500000000052412120621217023310 0ustar mathieumathieu#include "simple.h" #ifdef CABLE_CONFIGURATION namespace _cable_ { const char* const package = "Kitware.mummy.Testing.HandCrafted"; const char* const package_version = "@Mummy_VERSION_MAJOR@.@Mummy_VERSION_MINOR@.@Mummy_VERSION_PATCH@"; const char* const group = ""; namespace wrappers { typedef simple simple; } } #endif mummy-1.0.3/MummyTesting/Simple/0000755000175000017500000000000012120621217016416 5ustar mathieumathieumummy-1.0.3/MummyTesting/Simple/CMakeLists.txt0000644000175000017500000000536312120621217021165 0ustar mathieumathieu# Build as is, force static lib: # ADD_LIBRARY(simpleLib STATIC simple.cxx) # Forcing static lib on Linux means we have to use the -fPIC flag for compiling # sources in the target: # IF(NOT WIN32 AND NOT APPLE) SET_TARGET_PROPERTIES(simpleLib PROPERTIES COMPILE_FLAGS "-fPIC") ENDIF(NOT WIN32 AND NOT APPLE) ADD_EXECUTABLE(simpleLibTest main.cxx) TARGET_LINK_LIBRARIES(simpleLibTest simpleLib) # Test it: # IF(EXECUTABLE_OUTPUT_PATH) SET(exefile ${EXECUTABLE_OUTPUT_PATH}/simpleLibTest) ELSE(EXECUTABLE_OUTPUT_PATH) SET(exefile simpleLibTest) ENDIF(EXECUTABLE_OUTPUT_PATH) ADD_TEST(MT-simpleLibTest "${exefile}") # Build wrapper layers: # # Both gccxml_EXECUTABLE and mummy_EXECUTABLE should have been found by parent # project... verify: # IF(NOT gccxml_EXECUTABLE) MESSAGE(FATAL_ERROR "error: no gccxml_EXECUTABLE - cannot build wrapper layers") ENDIF(NOT gccxml_EXECUTABLE) IF(NOT mummy_EXECUTABLE) MESSAGE(FATAL_ERROR "error: no mummy_EXECUTABLE - cannot build wrapper layers") ENDIF(NOT mummy_EXECUTABLE) SET(gccxml_output "${CMAKE_CURRENT_BINARY_DIR}/simple_gccxml.xml") SET(mummy_exportlayer_output "${CMAKE_CURRENT_BINARY_DIR}/simple_exportlayer.cxx") SET(mummy_csharp_output "${CMAKE_CURRENT_BINARY_DIR}/simple.cs") CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/simple_gccxml.cxx.in" "${CMAKE_CURRENT_BINARY_DIR}/simple_gccxml.cxx" @ONLY ) ADD_CUSTOM_COMMAND( OUTPUT ${gccxml_output} COMMAND ${gccxml_EXECUTABLE} ARGS -fxml=${gccxml_output} -fxml-start=_cable_ -I${CMAKE_CURRENT_SOURCE_DIR} -DCABLE_CONFIGURATION --gccxml-compiler ${CMAKE_CXX_COMPILER} ${CMAKE_CURRENT_BINARY_DIR}/simple_gccxml.cxx DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/simple_gccxml.cxx ${CMAKE_CURRENT_SOURCE_DIR}/simple.h ${gccxml_EXECUTABLE} ) ADD_CUSTOM_COMMAND( OUTPUT ${mummy_csharp_output} ${mummy_exportlayer_output} COMMAND ${mummy_EXECUTABLE} ARGS --settings-file ${CMAKE_CURRENT_SOURCE_DIR}/simpleMummySettings.xml --gccxml-file ${gccxml_output} --csharp-file ${mummy_csharp_output} --export-layer-file ${mummy_exportlayer_output} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/simpleMummySettings.xml ${gccxml_output} ${mummy_EXECUTABLE} ) # Build the "export-layer" library: # ADD_LIBRARY(simpleExportLayer SHARED ${mummy_exportlayer_output}) TARGET_LINK_LIBRARIES(simpleExportLayer Kitware.mummy.Runtime.Unmanaged simpleLib ) ADD_EXECUTABLE(simpleExportLayerTest simpleExportLayerTest.cxx) TARGET_LINK_LIBRARIES(simpleExportLayerTest simpleExportLayer ) # Test it: # IF(EXECUTABLE_OUTPUT_PATH) SET(exefile ${EXECUTABLE_OUTPUT_PATH}/simpleExportLayerTest) ELSE(EXECUTABLE_OUTPUT_PATH) SET(exefile simpleExportLayerTest) ENDIF(EXECUTABLE_OUTPUT_PATH) ADD_TEST(MT-simpleExportLayerTest "${exefile}") mummy-1.0.3/MummyTesting/Simple/main.cxx0000644000175000017500000000023612120621217020067 0ustar mathieumathieu#include "simple.h" #include int main(int, char* []) { simple instance; std::cout << "&instance: " << &instance << std::endl; return 0; } mummy-1.0.3/MummyTesting/Simple/simple.cxx0000644000175000017500000000020612120621217020431 0ustar mathieumathieu#include "simple.h" simple::simple() { } simple::~simple() { } void simple::MethodToWrap() { } void simple::MethodNotToWrap() { } mummy-1.0.3/MummyTesting/Simple/simple.h0000644000175000017500000000031712120621217020061 0ustar mathieumathieu// comment class simple { public: simple(); virtual ~simple(); void MethodToWrap(); int m_PublicData; protected: void MethodNotToWrap(); int m_ProtectedData; private: int m_PrivateData; }; mummy-1.0.3/MummyTesting/Simple/simpleExportLayerTest.cxx0000644000175000017500000000155112120621217023474 0ustar mathieumathieu#include class simple; #ifdef _WIN32 #define SIMPLE_DLL_IMPORT __declspec(dllimport) #else #define SIMPLE_DLL_IMPORT #endif extern "C" SIMPLE_DLL_IMPORT simple* simple_new(unsigned int* mteStatus, unsigned int* mteIndex, unsigned int* rawRefCount); extern "C" SIMPLE_DLL_IMPORT void simple_delete(simple* pThis); int main(int, char* []) { unsigned int mteStatus = 0; unsigned int mteIndex = 0; unsigned int rawRefCount = 0; simple* instance = simple_new(&mteStatus, &mteIndex, &rawRefCount); std::cout << "instance: " << instance << std::endl; std::cout << "mteStatus: " << mteStatus << std::endl; std::cout << "mteIndex: " << mteIndex << std::endl; std::cout << "rawRefCount: " << rawRefCount << std::endl; std::cout << "(int) rawRefCount: " << (int) rawRefCount << std::endl; simple_delete(instance); instance = 0; return 0; } mummy-1.0.3/MummyTesting/Simple/simpleMummySettings.xml0000644000175000017500000000011612120621217023175 0ustar mathieumathieu mummy-1.0.3/MummyTesting/Simple/simple_gccxml.cxx.in0000644000175000017500000000051712120621217022400 0ustar mathieumathieu#include "simple.h" #ifdef CABLE_CONFIGURATION namespace _cable_ { const char* const package = "Kitware.mummy.Testing.simple"; const char* const package_version = "@Mummy_VERSION_MAJOR@.@Mummy_VERSION_MINOR@.@Mummy_VERSION_PATCH@"; const char* const group = ""; namespace wrappers { typedef simple simple; } } #endif mummy-1.0.3/MummyTesting/SuppressWarnings/0000755000175000017500000000000012120621217020522 5ustar mathieumathieumummy-1.0.3/MummyTesting/SuppressWarnings/CMakeLists.txt0000644000175000017500000000445112120621217023266 0ustar mathieumathieuSET(MTprefix "MTSuppressWarnings") # Build as is, force static lib: # ADD_LIBRARY(${MTprefix}Lib STATIC simple.cxx) # Forcing static lib on Linux means we have to use the -fPIC flag for compiling # sources in the target: # IF(NOT WIN32 AND NOT APPLE) SET_TARGET_PROPERTIES(${MTprefix}Lib PROPERTIES COMPILE_FLAGS "-fPIC") ENDIF(NOT WIN32 AND NOT APPLE) # Build wrapper layers: # # Both gccxml_EXECUTABLE and mummy_EXECUTABLE should have been found by parent # project... verify: # IF(NOT gccxml_EXECUTABLE) MESSAGE(FATAL_ERROR "error: no gccxml_EXECUTABLE - cannot build wrapper layers") ENDIF(NOT gccxml_EXECUTABLE) IF(NOT mummy_EXECUTABLE) MESSAGE(FATAL_ERROR "error: no mummy_EXECUTABLE - cannot build wrapper layers") ENDIF(NOT mummy_EXECUTABLE) SET(gccxml_output "${CMAKE_CURRENT_BINARY_DIR}/${MTprefix}_gccxml.xml") SET(mummy_exportlayer_output "${CMAKE_CURRENT_BINARY_DIR}/${MTprefix}_exportlayer.cxx") SET(mummy_csharp_output "${CMAKE_CURRENT_BINARY_DIR}/${MTprefix}.cs") SET(mummy_settings "${CMAKE_CURRENT_SOURCE_DIR}/MummySettings.xml") CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/gccxml.cxx.in" "${CMAKE_CURRENT_BINARY_DIR}/${MTprefix}_gccxml.cxx" @ONLY ) ADD_CUSTOM_COMMAND( OUTPUT ${gccxml_output} COMMAND ${gccxml_EXECUTABLE} ARGS -fxml=${gccxml_output} -fxml-start=_cable_ -I${CMAKE_CURRENT_SOURCE_DIR} -DCABLE_CONFIGURATION --gccxml-compiler ${CMAKE_CXX_COMPILER} ${CMAKE_CURRENT_BINARY_DIR}/${MTprefix}_gccxml.cxx DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${MTprefix}_gccxml.cxx ${CMAKE_CURRENT_SOURCE_DIR}/simple.h ${gccxml_EXECUTABLE} ) # --verbose and --suppress-warnings flags intentionally added to this # test to increase mummy coverage... # ADD_CUSTOM_COMMAND( OUTPUT ${mummy_csharp_output} ${mummy_exportlayer_output} COMMAND ${mummy_EXECUTABLE} ARGS --verbose --suppress-warnings 6008 --settings-file ${mummy_settings} --gccxml-file ${gccxml_output} --csharp-file ${mummy_csharp_output} --export-layer-file ${mummy_exportlayer_output} DEPENDS ${mummy_settings} ${gccxml_output} ${mummy_EXECUTABLE} ) # Build the "export-layer" library: # ADD_LIBRARY(${MTprefix}ExportLayer SHARED ${mummy_exportlayer_output}) TARGET_LINK_LIBRARIES(${MTprefix}ExportLayer ${MTprefix}Lib Kitware.mummy.Runtime.Unmanaged ) mummy-1.0.3/MummyTesting/SuppressWarnings/MummySettings.xml0000644000175000017500000000011612120621217024067 0ustar mathieumathieu mummy-1.0.3/MummyTesting/SuppressWarnings/gccxml.cxx.in0000644000175000017500000000052412120621217023131 0ustar mathieumathieu#include "simple.h" #ifdef CABLE_CONFIGURATION namespace _cable_ { const char* const package = "Kitware.mummy.Testing.HandCrafted"; const char* const package_version = "@Mummy_VERSION_MAJOR@.@Mummy_VERSION_MINOR@.@Mummy_VERSION_PATCH@"; const char* const group = ""; namespace wrappers { typedef simple simple; } } #endif mummy-1.0.3/MummyTesting/SuppressWarnings/simple.cxx0000644000175000017500000000020612120621217022535 0ustar mathieumathieu#include "simple.h" simple::simple() { } simple::~simple() { } void simple::MethodToWrap() { } void simple::MethodNotToWrap() { } mummy-1.0.3/MummyTesting/SuppressWarnings/simple.h0000644000175000017500000000031712120621217022165 0ustar mathieumathieu// comment class simple { public: simple(); virtual ~simple(); void MethodToWrap(); int m_PublicData; protected: void MethodNotToWrap(); int m_ProtectedData; private: int m_PrivateData; }; mummy-1.0.3/MummyUtilities.cxx0000644000175000017500000006150312120621217016254 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyUtilities.cxx 470 2009-06-12 17:43:02Z hoffman $ // // $Author: hoffman $ // $Date: 2009-06-12 13:43:02 -0400 (Fri, 12 Jun 2009) $ // $Revision: 470 $ // // Copyright (C) 2006-2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyUtilities.h" #include "MummyLog.h" #include "cableClass.h" #include "cableClassType.h" #include "cableConstructor.h" #include "cableFunctionType.h" #include "cableNamed.h" #include "cablePointerType.h" #include "cableReferenceType.h" #include "cableType.h" #include "cableTypedef.h" #include "cxxFundamentalType.h" #include "gxsys/RegularExpression.hxx" #include "gxsys/SystemTools.hxx" #include "gxsys/ios/fstream" #include "gxsys/ios/sstream" #include "gxsys/stl/map" #ifdef _WIN32 #include // only for "OutputDebugString" #endif // _WIN32 #include "string.h" // strlen //---------------------------------------------------------------------------- void Trace(const char *s) { #ifdef _WIN32 OutputDebugString(s); #endif // _WIN32 //LogInfo(mi_Info, << s); } //---------------------------------------------------------------------------- void Emit(gxsys_ios::ostream &os, const char *s) { //Trace(s); os << s; } //---------------------------------------------------------------------------- void EmitInt(gxsys_ios::ostream &os, const int i) { os << i; } //---------------------------------------------------------------------------- void EmitUint(gxsys_ios::ostream &os, const unsigned int i) { os << i; } //---------------------------------------------------------------------------- void EmitIndent(gxsys_ios::ostream &os, const unsigned int n) { // See also: indentString in EmitDocumentationBlock. If we change it here, // we probably will want to change it there also... // unsigned int i = 0; for (i= 0; iGetTypeId()) { const cxx::FundamentalType *cxxft = cxx::FundamentalType::SafeDownCast( t->GetCxxType().GetType()); if (cxxft) { return tid == cxxft->GetId(); } } return false; } //---------------------------------------------------------------------------- bool IsObject(const cable::Type *t) { return cable::Type::ClassTypeId == t->GetTypeId(); } //---------------------------------------------------------------------------- bool IsVoid(const cable::Type *t) { return IsFundamental(t, cxx::FundamentalType::Void); } //---------------------------------------------------------------------------- bool HasMapToType(const cable::Type *t) { if (IsObject(t)) { return HasAttribute(cable::ClassType::SafeDownCast(t)->GetClass(), "gccxml(iwhMapToType"); } if ((cable::Type::ReferenceTypeId == t->GetTypeId()) && IsObject(cable::ReferenceType::SafeDownCast(t)->GetTarget())) { return HasAttribute(cable::ClassType::SafeDownCast( cable::ReferenceType::SafeDownCast(t)->GetTarget())->GetClass(), "gccxml(iwhMapToType"); } return false; } //---------------------------------------------------------------------------- gxsys_stl::string GetMapToType(const cable::Type *t) { gxsys_stl::string s; if (IsObject(t)) { s = ExtractMapToType(cable::ClassType::SafeDownCast(t)->GetClass()); } else if ((cable::Type::ReferenceTypeId == t->GetTypeId()) && IsObject(cable::ReferenceType::SafeDownCast(t)->GetTarget())) { s = ExtractMapToType(cable::ClassType::SafeDownCast( cable::ReferenceType::SafeDownCast(t)->GetTarget())->GetClass()); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string GetStringMethod(const cable::Type *t) { gxsys_stl::string s; if (IsObject(t)) { s = ExtractStringMethod(cable::ClassType::SafeDownCast(t)->GetClass()); } else if ((cable::Type::ReferenceTypeId == t->GetTypeId()) && IsObject(cable::ReferenceType::SafeDownCast(t)->GetTarget())) { s = ExtractStringMethod(cable::ClassType::SafeDownCast( cable::ReferenceType::SafeDownCast(t)->GetTarget())->GetClass()); } return s; } //---------------------------------------------------------------------------- bool IsCharPointer(const cable::Type *t) { return IsFundamentalPointer(t, cxx::FundamentalType::Char); } //---------------------------------------------------------------------------- bool IsCharPointerPointer(const cable::Type *t) { return IsFundamentalPointerPointer(t, cxx::FundamentalType::Char); } //---------------------------------------------------------------------------- bool IsFundamentalPointer(const cable::Type *t, cxx::FundamentalType::Id tid) { if (cable::Type::PointerTypeId == t->GetTypeId()) { return IsFundamental(cable::PointerType::SafeDownCast(t)->GetTarget(), tid); } return false; } //---------------------------------------------------------------------------- bool IsFundamentalPointerPointer(const cable::Type *t, cxx::FundamentalType::Id tid) { if (cable::Type::PointerTypeId == t->GetTypeId()) { return IsFundamentalPointer(cable::PointerType::SafeDownCast(t)->GetTarget(), tid); } return false; } //---------------------------------------------------------------------------- bool IsObjectPointer(const cable::Type *t) { if (cable::Type::PointerTypeId == t->GetTypeId()) { return IsObject(cable::PointerType::SafeDownCast(t)->GetTarget()); } return false; } //---------------------------------------------------------------------------- bool IsObjectPointerReference(const cable::Type *t) { if (cable::Type::ReferenceTypeId == t->GetTypeId()) { return IsObjectPointer(cable::ReferenceType::SafeDownCast(t)->GetTarget()); } return false; } //---------------------------------------------------------------------------- bool IsVoidPointer(const cable::Type *t) { return IsFundamentalPointer(t, cxx::FundamentalType::Void); } //---------------------------------------------------------------------------- const char *GetAccessString(cable::Context::Access access) { if (cable::Context::Public == access) return "public"; if (cable::Context::Protected == access) return "protected"; if (cable::Context::Private == access) return "private"; LogError(me_InvalidArg, << "ERROR_invalid_input_to_GetAccessString"); return "ERROR_invalid_input_to_GetAccessString"; } //---------------------------------------------------------------------------- const cable::Class *GetParentClass(const cable::Class *c) { const cable::Class *parent = 0; if (c) { gxsys_stl::vector bases; size_t basecount = 0; gxsys_stl::vector::iterator it; c->GetBaseClasses(bases); basecount = bases.size(); if (0 == basecount) { } else if (1 == basecount) { parent = *bases.begin(); } else { LogError( me_MoreThanOneBaseClass, << "GetParentClass returning 0 because there is more than one base for class '" << c->GetName() << "'" ); } } return parent; } //---------------------------------------------------------------------------- bool ClassIsA(const cable::Class *c, const gxsys_stl::string& parent) { bool isa = false; const cable::Class *cIt = c; while (!isa && cIt != NULL) { if (GetFullyQualifiedNameForCPlusPlus(cIt) == parent) { isa = true; } else { cIt = GetParentClass(cIt); } } return isa; } //---------------------------------------------------------------------------- bool ValidateBaseClasses(const cable::Class *c) { bool validated = false; gxsys_stl::vector bases; size_t basecount = 0; gxsys_stl::vector::iterator it; c->GetBaseClasses(bases); basecount = bases.size(); if (0 == basecount) { validated = true; } else if (1 == basecount) { it = bases.begin(); validated = ValidateBaseClasses(*it); } else { LogError( me_MoreThanOneBaseClass, << "ValidateBaseClasses returning false because there is more than one base for class '" << c->GetName() << "'" ); } return validated; } //---------------------------------------------------------------------------- gxsys_stl::string GetSimpleName(const cable::Named *n) { gxsys_stl::string s; if (n) { s = n->GetName(); } else { s = "ERROR_invalid_input_to_GetSimpleName"; LogError(me_InvalidArg, << s.c_str()); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string GetFullyQualifiedName(const cable::Named *n, const char *sep) { gxsys_stl::string s; if (n && sep && n->GetContext()) { s = GetFullyQualifiedName(n->GetContext(), sep); // Do not emit a "leading separator" at global scope: // if (s == "::") { s = ""; } else { s += sep; } s += n->GetName(); } else if (n && sep) { s = n->GetName(); } else { s = "ERROR_invalid_input_to_GetFullyQualifiedName"; LogError(me_InvalidArg, << s.c_str()); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string GetFullyQualifiedLengthPrefixedName(const cable::Named *n, const char *sep) { gxsys_stl::string s; if (n && sep && n->GetContext()) { s = GetFullyQualifiedLengthPrefixedName(n->GetContext(), sep); // Do not emit a "leading separator" at global scope: // if (s == "::") { s = ""; } else { s += sep; } gxsys_ios::ostringstream oss; oss << strlen(n->GetName()); s += oss.str(); s += n->GetName(); } else if (n && sep) { s = n->GetName(); } else { s = "ERROR_invalid_input_to_GetFullyQualifiedLengthPrefixedName"; LogError(me_InvalidArg, << s.c_str()); } return s; } //---------------------------------------------------------------------------- gxsys_stl::string GetFullyQualifiedNameForCPlusPlus(const cable::Named *n) { return GetFullyQualifiedName(n, "::"); } //---------------------------------------------------------------------------- gxsys_stl::string GetFullyQualifiedNameForCSharp(const cable::Named *n) { return GetFullyQualifiedName(n, "."); } //---------------------------------------------------------------------------- gxsys_stl::string GetFullyQualifiedCPlusPlusTypeIdName(const cable::Named *n) { gxsys_stl::string s("ERROR_unknown_compiler_in_GetFullyQualifiedCPlusPlusTypeIdName"); #if defined(_MSC_VER) s = "class "; s += GetFullyQualifiedNameForCPlusPlus(n); #elif defined(__GNUC__) s = GetFullyQualifiedLengthPrefixedName(n, ""); #endif return s; } //---------------------------------------------------------------------------- bool EquivalentTypedefNameExists(const cable::Class* c, const cable::FunctionType *target, gxsys_stl::string& s) { s = ""; // Look through the typedefs of the target class and return the name of the // first one found that matches the function pointer type inside of 't'... for (cable::Context::Iterator it = c->Begin(); it != c->End() && s == ""; ++it) { cable::Typedef *td = cable::Typedef::SafeDownCast(*it); if (td && (cable::Context::Public == it.GetAccess())) { gxsys_stl::string tname(td->GetName()); cable::PointerType *pt = cable::PointerType::SafeDownCast(td->GetType()); cable::FunctionType *ft = 0; if (pt) { ft = cable::FunctionType::SafeDownCast(pt->GetTarget()); } if (ft && ft == target) { s = tname; } } } return (s != ""); } //---------------------------------------------------------------------------- bool HasAttribute(const cable::SourceObject *o, const char *attr) { gxsys_stl::string atts(o->GetAttributes()); if (atts != "") { if (gxsys_stl::string::npos != atts.find(attr)) { return true; } } return false; } //---------------------------------------------------------------------------- bool IsUtilityClass(const cable::Class *c) { return HasAttribute(c, "gccxml(iwhUtility)"); } //---------------------------------------------------------------------------- gxsys_stl::string ExtractAttribute(const gxsys_stl::string& atts, const gxsys_stl::string& attBase) { gxsys_stl::string extracted; bool hasAtt = false; if (gxsys_stl::string::npos != atts.find(gxsys_stl::string("gccxml(") + attBase)) { hasAtt = true; } if (hasAtt) { gxsys::RegularExpression re; re.compile((gxsys_stl::string("(gccxml\\(")+attBase+")([^\\)]*)(\\))").c_str()); if (re.find(atts.c_str())) { extracted = re.match(2); } } return extracted; } //---------------------------------------------------------------------------- gxsys_stl::string ExtractAttribute(const cable::SourceObject *o, const gxsys_stl::string& attBase) { gxsys_stl::string atts(o->GetAttributes()); return ExtractAttribute(atts, attBase); } //---------------------------------------------------------------------------- gxsys_stl::string ExtractArraySize(const gxsys_stl::string& atts) { return ExtractAttribute(atts, "iwhArraySize"); } //---------------------------------------------------------------------------- gxsys_stl::string ExtractImplementsInterface(const gxsys_stl::string& atts) { return ExtractAttribute(atts, "iwhImplementsInterface"); } //---------------------------------------------------------------------------- gxsys_stl::string ExtractMapToType(const cable::SourceObject *o) { return ExtractAttribute(o, "iwhMapToType"); } //---------------------------------------------------------------------------- gxsys_stl::string ExtractStringMethod(const cable::SourceObject *o) { return ExtractAttribute(o, "iwhStringMethod"); } //---------------------------------------------------------------------------- gxsys_stl::string GetMappedTypeName(const cable::Class *c, bool fullyQualified) { gxsys_stl::string typeName(ExtractMapToType(c)); if (typeName == "string") { typeName = "string"; } else { if (fullyQualified) { typeName = GetFullyQualifiedNameForCSharp(c); } else { typeName = GetSimpleName(c); } } return typeName; } //---------------------------------------------------------------------------- gxsys_stl::string GetWrappedClassName(const cable::Class *c) { return GetMappedTypeName(c, false); } //---------------------------------------------------------------------------- gxsys_stl::string GetWrappedClassNameFullyQualified(const cable::Class *c) { return GetMappedTypeName(c, true); } //---------------------------------------------------------------------------- static gxsys_stl::map suppressed_msg_values; //---------------------------------------------------------------------------- void SuppressMsg(const int n) { suppressed_msg_values[n] = n; } //---------------------------------------------------------------------------- bool ShouldLogMsg(const int n) { gxsys_stl::map::iterator it = suppressed_msg_values.find(n); return it == suppressed_msg_values.end(); } //---------------------------------------------------------------------------- static gxsys_stl::vector error_values; //---------------------------------------------------------------------------- void LogMsg(const gxsys_stl::string&, const unsigned long, const gxsys_stl::string& label, const int n) { if (label == "error") { if (n) { error_values.push_back(n); } else { gxsys_ios::cerr << "error: 'error' LogMsg n value should be non-zero..."; error_values.push_back(me_InternalError); } } } //---------------------------------------------------------------------------- int GetErrorCount() { return static_cast(error_values.size()); } //---------------------------------------------------------------------------- int GetNthErrorValue(int n) { if (n >= 0 && n < GetErrorCount()) { return error_values[n]; } return 0; } //---------------------------------------------------------------------------- int GetFirstErrorValue() { return GetNthErrorValue(0); } //---------------------------------------------------------------------------- int GetMostRecentErrorValue() { return GetNthErrorValue(GetErrorCount()-1); } //---------------------------------------------------------------------------- const cable::Constructor* FindNonAbstractPublicDefaultConstructor(const cable::Class *c) { const cable::Constructor* ctor = 0; if (!c->GetAbstract()) { for (cable::Context::Iterator it = c->Begin(); 0 == ctor && it != c->End(); ++it) { cable::Constructor *ctorCandidate = cable::Constructor::SafeDownCast(*it); if (ctorCandidate && cable::Context::Public == it.GetAccess() && 0 == ctorCandidate->GetFunctionType()->GetNumberOfRequiredArguments()) { ctor = ctorCandidate; break; } } } return ctor; } //---------------------------------------------------------------------------- gxsys_stl::string GetCPlusPlusZeroInitializerExpression(const cable::Type *t) { gxsys_stl::string s; switch (t->GetTypeId()) { case cable::Type::ClassTypeId: s = "memset"; break; case cable::Type::EnumerationTypeId: s = "cast"; break; case cable::Type::FundamentalTypeId: case cable::Type::PointerTypeId: s = "0"; break; default: s = "error: unhandled cable::Type in GetCPlusPlusZeroInitializerExpression"; LogError(me_InternalError, << s.c_str()); break; } return s; } //---------------------------------------------------------------------------- gxsys_stl::string GetCsharpZeroInitializerExpression(const cable::Type *t) { gxsys_stl::string s; switch (t->GetTypeId()) { case cable::Type::ClassTypeId: s = "null"; break; case cable::Type::EnumerationTypeId: s = "cast"; break; case cable::Type::FundamentalTypeId: case cable::Type::PointerTypeId: s = "0"; break; default: s = "error: unhandled cable::Type in GetCsharpZeroInitializerExpression"; LogError(me_InternalError, << s.c_str()); break; } return s; } //---------------------------------------------------------------------------- bool BlockContains(const gxsys_stl::vector& block, const char *value) { gxsys_stl::vector::const_iterator blockIt; for (blockIt = block.begin(); blockIt!=block.end(); ++blockIt) { if (strstr(blockIt->c_str(), value)) { return true; } } return false; } //---------------------------------------------------------------------------- bool ShouldEmitComment(const char *comment) { gxsys::RegularExpression re; re.compile("//[\\t ]*Description:[\\t ]*"); if (re.find(comment)) { return false; } return true; } //---------------------------------------------------------------------------- gxsys_stl::string EncodeStringForXml(const char *s) { gxsys_stl::string encoded; if (s) { size_t i = 0; size_t n = strlen(s); for (i= 0; i' : encoded.append(">"); break; case '<' : encoded.append("<"); break; case '"' : encoded.append("""); break; default : encoded += s[i]; break; } } } return encoded; } // Valid XML doc tags are: // //"c" //"code" //"description" //"example" //"exception " //"include" //"item" //"list" //"listheader" //"para" //"param" //"paramref" //"permission" //"remarks" //"returns" //"see" //"seealso" //"summary" //"term" //"typeparam" //"typeparamref" //"value" //---------------------------------------------------------------------------- void EmitDocumentationBlock(gxsys_ios::ostream &os, const gxsys_stl::vector& block, const unsigned int indent, bool isClassDoc) { // See also: EmitIndent. If we change indentString here, // we probably will want to change it there also... // gxsys::String indentString = ""; for (unsigned int i= 0; i tagBody; gxsys_stl::vector::const_iterator blockIt; gxsys_stl::string line; bool isXmlBlock = (BlockContains(block, "") && BlockContains(block, "")) || (BlockContains(block, "") && BlockContains(block, "")); gxsys::RegularExpression descRE; descRE.compile(gxsys_stl::string("Description:").c_str()); gxsys::RegularExpression nameRE; nameRE.compile(gxsys_stl::string("\\.NAME").c_str()); gxsys::RegularExpression seeRE; seeRE.compile(gxsys_stl::string("\\.SECTION[\\t ]+[Ss][Ee][Ee][\\t ]+[Aa][Ll][Ss][Oo]").c_str()); gxsys::RegularExpression secRE; secRE.compile(gxsys_stl::string("\\.SECTION").c_str()); gxsys::RegularExpression noSpaceRE; noSpaceRE.compile(gxsys_stl::string("[^ ]+").c_str()); for (blockIt = block.begin(); blockIt!=block.end(); ++blockIt) { line = *blockIt; if (isClassDoc && !isXmlBlock) { //If it matches a .NAME section add to summary if (nameRE.find(line)) { gxsys::SystemTools::ReplaceString(line,nameRE.match(0).c_str(),""); xmlTag = "summary"; } //If it matches a .SECTION see also section add to see also else if (seeRE.find(line)) { gxsys::SystemTools::ReplaceString(line,seeRE.match(0).c_str(),""); xmlTag = "seealso"; } //If it matches a .SECTION * section add to remarks else if (secRE.find(line)) { gxsys::SystemTools::ReplaceString(line,secRE.match(0).c_str(),""); xmlTag = "remarks"; } //If it matches a Description: section add to summary else if (descRE.find(line)) { gxsys::SystemTools::ReplaceString(line,descRE.match(0).c_str(),""); xmlTag = "summary"; } } if (ShouldEmitComment(line.c_str())) { if (isXmlBlock) { EmitIndent(os, indent); if (gxsys::SystemTools::StringStartsWith(line.c_str(), "///")) { Emit(os, line.c_str()); } else if (gxsys::SystemTools::StringStartsWith(line.c_str(), "//")) { Emit(os, "/"); Emit(os, line.c_str()); } else { Emit(os, "///"); Emit(os, line.c_str()); } Emit(os,"\n"); } else { line = EncodeStringForXml(line.c_str()); //handle code in comments gxsys::SystemTools::ReplaceString(line,"\\code",""); gxsys::SystemTools::ReplaceString(line,"\\endcode",""); if (gxsys::SystemTools::StringStartsWith(line.c_str(), "///")) { tagBody[xmlTag]+=indentString+line+"\n"; } else if (gxsys::SystemTools::StringStartsWith(line.c_str(), "//")) { tagBody[xmlTag]+=indentString+"/"+line+"\n"; } else { tagBody[xmlTag]+=indentString+"///"+line+"\n"; } } } } if(tagBody["summary"] != "") { gxsys::String beginTag = indentString+"/// \n"; gxsys::String endTag = indentString+"/// \n"; Emit(os,beginTag.c_str()); Emit(os,(tagBody["summary"]).c_str()); Emit(os,endTag.c_str()); } if(tagBody["remarks"] != "") { gxsys::String beginTag = indentString+"/// \n"; gxsys::String endTag = indentString+"/// \n"; Emit(os,beginTag.c_str()); Emit(os,(tagBody["remarks"]).c_str()); Emit(os,endTag.c_str()); } if(tagBody["seealso"] != "") { gxsys::String beginTag = indentString+"/// \n"; gxsys::String endTag = indentString+"/// \n"; Emit(os, beginTag.c_str()); Emit(os, tagBody["seealso"].c_str()); Emit(os, endTag.c_str()); } } //---------------------------------------------------------------------------- gxsys_stl::string ExtractDerivedName(const char *s, const cable::Named *n, bool verbose) { gxsys_stl::string name; gxsys_stl::string derivedName; gxsys_stl::string c1to2; gxsys_stl::string c1to3; if (s) { name = s; } if (s && strlen(s)>2) { c1to2 = name.substr(0, 2); } if (s && strlen(s)>3) { c1to3 = name.substr(0, 3); } if ((c1to3 == "Get") || (c1to3 == "get")) { derivedName = name.substr(3); } else if ((c1to3 == "Set") || (c1to3 == "set")) { derivedName = name.substr(3); } else if (c1to2 == "m_") { derivedName = name.substr(2); } else { derivedName = name; if (n && verbose) { LogFileLineInfoMsg(n->GetFile(), n->GetLine(), mi_VerboseInfo, "ExtractDerivedName could not extract derivedName from name: " << name << ". Using name as-is..."); } } return derivedName; } mummy-1.0.3/MummyUtilities.h0000644000175000017500000001037412120621217015701 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyUtilities.h // // Author(s) : David Cole // // Copyright (C) 2006-2007 Kitware, Inc. //---------------------------------------------------------------------------- #ifndef MummyUtilities_h #define MummyUtilities_h // Suppress nearly meaningless warnings: // #ifdef _MSC_VER #pragma warning(disable:4127) // 4127 is suppressed because it warns on every single stl container iteration // loop that the "conditional expression is constant"... #endif #include "cableContext.h" #include "cxxFundamentalType.h" #include "gxsys/ios/iosfwd" #include "gxsys/stl/string" namespace cable { class Class; class Constructor; class FunctionType; class Type; } void Trace(const char *s); void Emit(gxsys_ios::ostream &os, const char *s); void EmitInt(gxsys_ios::ostream &os, const int i); void EmitUint(gxsys_ios::ostream &os, const unsigned int i); void EmitIndent(gxsys_ios::ostream &os, const unsigned int n = 1); void EmitFile(gxsys_ios::ostream &os, const char *filename); void WriteToFile(const char *filename, const char *s); bool IsChar(const cable::Type *t); bool IsFundamental(const cable::Type *t, cxx::FundamentalType::Id tid); bool IsObject(const cable::Type *t); bool IsVoid(const cable::Type *t); bool HasMapToType(const cable::Type *t); gxsys_stl::string GetMapToType(const cable::Type *t); gxsys_stl::string GetStringMethod(const cable::Type *t); bool IsCharPointer(const cable::Type *t); bool IsCharPointerPointer(const cable::Type *t); bool IsFundamentalPointer(const cable::Type *t, cxx::FundamentalType::Id tid); bool IsFundamentalPointerPointer(const cable::Type *t, cxx::FundamentalType::Id tid); bool IsObjectPointer(const cable::Type *t); bool IsObjectPointerReference(const cable::Type *t); bool IsVoidPointer(const cable::Type *t); const char *GetAccessString(cable::Context::Access access); const cable::Class *GetParentClass(const cable::Class *c); bool ClassIsA(const cable::Class *c, const gxsys_stl::string& parent); bool ValidateBaseClasses(const cable::Class *c); gxsys_stl::string GetSimpleName(const cable::Named *n); gxsys_stl::string GetFullyQualifiedName(const cable::Named *n, const char *sep); gxsys_stl::string GetFullyQualifiedNameForCPlusPlus(const cable::Named *n); gxsys_stl::string GetFullyQualifiedNameForCSharp(const cable::Named *n); gxsys_stl::string GetFullyQualifiedCPlusPlusTypeIdName(const cable::Named *n); bool EquivalentTypedefNameExists(const cable::Class* c, const cable::FunctionType *target, gxsys_stl::string& s); bool HasAttribute(const cable::SourceObject *o, const char *attr); bool IsUtilityClass(const cable::Class *c); gxsys_stl::string ExtractAttribute(const gxsys_stl::string& atts, const gxsys_stl::string& attBase); gxsys_stl::string ExtractAttribute(const cable::SourceObject *o, const gxsys_stl::string& attBase); gxsys_stl::string ExtractArraySize(const gxsys_stl::string& atts); gxsys_stl::string ExtractImplementsInterface(const gxsys_stl::string& atts); gxsys_stl::string ExtractMapToType(const cable::SourceObject *o); gxsys_stl::string ExtractStringMethod(const cable::SourceObject *o); gxsys_stl::string GetMappedTypeName(const cable::Class *c, bool fullyQualified); gxsys_stl::string GetWrappedClassName(const cable::Class *c); gxsys_stl::string GetWrappedClassNameFullyQualified(const cable::Class *c); void SuppressMsg(const int n); bool ShouldLogMsg(const int n); void LogMsg(const gxsys_stl::string& file, const unsigned long line, const gxsys_stl::string& label, const int n); int GetErrorCount(); int GetFirstErrorValue(); int GetNthErrorValue(int n); int GetMostRecentErrorValue(); const cable::Constructor* FindNonAbstractPublicDefaultConstructor(const cable::Class *c); gxsys_stl::string GetCPlusPlusZeroInitializerExpression(const cable::Type *t); gxsys_stl::string GetCsharpZeroInitializerExpression(const cable::Type *t); bool BlockContains(const gxsys_stl::vector& block, const char *value); bool ShouldEmitComment(const char *comment); gxsys_stl::string EncodeStringForXml(const char *s); void EmitDocumentationBlock(gxsys_ios::ostream &os, const gxsys_stl::vector& block, const unsigned int indent, bool isClassDoc = false); gxsys_stl::string ExtractDerivedName(const char *s, const cable::Named *n, bool verbose); #endif mummy-1.0.3/MummyVersion.h.in0000644000175000017500000000332012120621217015751 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyVersion.h // // Author(s) : David Cole // // Copyright (C) 2006-2009 Kitware, Inc. //---------------------------------------------------------------------------- #define Mummy_VERSION_MAJOR @Mummy_VERSION_MAJOR@ #define Mummy_VERSION_MINOR @Mummy_VERSION_MINOR@ #define Mummy_VERSION_PATCH @Mummy_VERSION_PATCH@ #define Mummy_VERSION_SVN_REVISION @Mummy_VERSION_SVN_REVISION@ #define Mummy_VERSION_STRING "@Mummy_VERSION_STRING@" #define Mummy_FULL_VERSION_STRING "@Mummy_FULL_VERSION_STRING@" // "SCS" == source control system (svn, cvs, etc) // #define Mummy_SCS_Author "@Mummy_SCS_Author@" #define Mummy_SCS_Date "@Mummy_SCS_Date@" #define Mummy_SCS_Id "@Mummy_SCS_Id@" #define Mummy_SCS_Revision "@Mummy_SCS_Revision@" #define Mummy_SCS_URL "@Mummy_SCS_URL@" // "WC" == working copy variables extracted from 'svn info' using the // Subversion_WC_INFO CMake macro courtesy of FIND_PACKAGE(Subversion) // #define Mummy_SVN_VERSION "@Subversion_VERSION_SVN@" #define Mummy_WC_URL "@Mummy_WC_URL@" #define Mummy_WC_REVISION "@Mummy_WC_REVISION@" #define Mummy_WC_LAST_CHANGED_AUTHOR "@Mummy_WC_LAST_CHANGED_AUTHOR@" #define Mummy_WC_LAST_CHANGED_REV "@Mummy_WC_LAST_CHANGED_REV@" #define Mummy_WC_LAST_CHANGED_DATE "@Mummy_WC_LAST_CHANGED_DATE@" // 'svn status' info: // #define Mummy_SVN_STATUS_BRIEF "@Mummy_SVN_STATUS_BRIEF@" #define Mummy_SVN_STATUS_ENCODED "@Mummy_SVN_STATUS_ENCODED@" // raw 'svn info' and 'svn status' results: // #if 0 // @Mummy_WC_INFO@ // // @Mummy_SVN_STATUS@ // #endif // CableSwig revision info: // #define Mummy_CableSwig_CVS_REVISION "@Mummy_CableSwig_CVS_REVISION@" mummy-1.0.3/MummyVersion.rc.in0000644000175000017500000000400012120621217016122 0ustar mathieumathieu//---------------------------------------------------------------------------- // @MummyRC_RC_FILE_NAME@ // // Author(s) : David Cole // // Copyright (C) 2006-2008 Kitware, Inc. //---------------------------------------------------------------------------- #include "MummyVersion.h" #include "windows.h" VS_VERSION_INFO VERSIONINFO FILEVERSION Mummy_VERSION_MAJOR,Mummy_VERSION_MINOR,Mummy_VERSION_PATCH,Mummy_VERSION_SVN_REVISION PRODUCTVERSION Mummy_VERSION_MAJOR,Mummy_VERSION_MINOR,Mummy_VERSION_PATCH,Mummy_VERSION_SVN_REVISION FILEOS VOS__WINDOWS32 FILETYPE VFT_APP FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "@MummyRC_FILE_DESCRIPTION@\0" VALUE "OriginalFilename", "@MummyRC_ORIGINAL_FILENAME@\0" VALUE "CompanyName", "Kitware Inc.\0" VALUE "FileVersion", Mummy_FULL_VERSION_STRING "\0" VALUE "LegalCopyright", "Copyright (c) 2006-2008 Kitware Inc. All rights reserved.\0" VALUE "ProductName", Mummy_FULL_VERSION_STRING "\0" VALUE "ProductVersion", Mummy_FULL_VERSION_STRING "\0" VALUE "Mummy_SCS_Author", Mummy_SCS_Author "\0" VALUE "Mummy_SCS_Date", Mummy_SCS_Date "\0" VALUE "Mummy_SCS_Id", Mummy_SCS_Id "\0" VALUE "Mummy_SCS_Revision", Mummy_SCS_Revision "\0" VALUE "Mummy_SCS_URL", Mummy_SCS_URL "\0" VALUE "Mummy_SVN_VERSION", Mummy_SVN_VERSION "\0" VALUE "Mummy_WC_URL", Mummy_WC_URL "\0" VALUE "Mummy_WC_REVISION", Mummy_WC_REVISION "\0" VALUE "Mummy_WC_LAST_CHANGED_AUTHOR", Mummy_WC_LAST_CHANGED_AUTHOR "\0" VALUE "Mummy_WC_LAST_CHANGED_REV", Mummy_WC_LAST_CHANGED_REV "\0" VALUE "Mummy_WC_LAST_CHANGED_DATE", Mummy_WC_LAST_CHANGED_DATE "\0" VALUE "Mummy_SVN_STATUS_BRIEF", Mummy_SVN_STATUS_BRIEF "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END mummy-1.0.3/Runtime/0000755000175000017500000000000012120621217014146 5ustar mathieumathieumummy-1.0.3/Runtime/AssemblyInfo.cs.in0000644000175000017500000000271212120621217017477 0ustar mathieumathieuusing System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Kitware.mummy.Runtime")] [assembly: AssemblyDescription("@Mummy_FULL_VERSION_STRING@")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Kitware Inc.")] [assembly: AssemblyProduct("mummy")] [assembly: AssemblyCopyright("Copyright ©2006-2008 Kitware Inc. All rights reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(true)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("fd028b59-3d0d-410e-b0bf-f6705820f429")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // [assembly: AssemblyVersion("@Mummy_VERSION_MAJOR@.@Mummy_VERSION_MINOR@.@Mummy_VERSION_PATCH@.@Mummy_VERSION_SVN_REVISION@")] [assembly: AssemblyFileVersion("@Mummy_VERSION_MAJOR@.@Mummy_VERSION_MINOR@.@Mummy_VERSION_PATCH@.@Mummy_VERSION_SVN_REVISION@")] mummy-1.0.3/Runtime/CMakeLists.txt0000644000175000017500000001214012120621217016704 0ustar mathieumathieuPROJECT(MummyRuntime) SET(MummyRC_RC_FILE_NAME "MummyRuntime.rc") SET(MummyRC_FILE_DESCRIPTION "${Mummy_FULL_VERSION_STRING} - mummy runtime dll") SET(MummyRC_ORIGINAL_FILENAME "${CMAKE_SHARED_LIBRARY_PREFIX}Kitware.mummy.Runtime.Unmanaged${CMAKE_SHARED_LIBRARY_SUFFIX}") CONFIGURE_FILE( "${Mummy_SOURCE_DIR}/MummyVersion.rc.in" "${CMAKE_CURRENT_BINARY_DIR}/${MummyRC_RC_FILE_NAME}" @ONLY ) ADD_LIBRARY( Kitware.mummy.Runtime.Unmanaged SHARED MummyRuntime.cxx MummyRuntime.h MummyTypeEntry.cxx MummyTypeEntry.h "${CMAKE_CURRENT_BINARY_DIR}/MummyRuntime.rc" ) INSTALL(TARGETS Kitware.mummy.Runtime.Unmanaged DESTINATION "bin" ) # This string should be the same string as the C++ return value from this code: # MRSmokeTest *test; # return typeid(*test).name(); # SET(MRSMOKETEST_CLASS_NAME_KEY "ERROR_unknown_MRSmokeTest_class_name_key") IF(CMAKE_COMPILER_IS_GNUCXX) SET(MRSMOKETEST_CLASS_NAME_KEY "11MRSmokeTest") ENDIF(CMAKE_COMPILER_IS_GNUCXX) IF(MSVC) SET(MRSMOKETEST_CLASS_NAME_KEY "class MRSmokeTest") ENDIF(MSVC) CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/AssemblyInfo.cs.in" "${CMAKE_CURRENT_BINARY_DIR}/AssemblyInfo.cs" @ONLY ) CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/MummyRuntime.cs.in" "${CMAKE_CURRENT_BINARY_DIR}/MummyRuntime.cs" @ONLY ) CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/MRSmokeTest.cs.in" "${CMAKE_CURRENT_BINARY_DIR}/MRSmokeTest.cs" @ONLY ) # If a real strong name signing keyfile has not been predefined, # then use the public key file in the source tree to /delaysign # .NET assemblies... # IF(NOT Mummy_SNKEYFILE) GET_FILENAME_COMPONENT(Mummy_SNKEYFILE "${CMAKE_CURRENT_SOURCE_DIR}/Kitware.mummy.Runtime.pub.snk" ABSOLUTE) ENDIF(NOT Mummy_SNKEYFILE) MESSAGE(STATUS "Mummy_SNKEYFILE='${Mummy_SNKEYFILE}'") ADD_CSHARP_LIBRARY( "Kitware.mummy.Runtime" # name of library "Kitware.mummy.Runtime.Unmanaged" # list of CMake targets that need to build first "" # list of csc "/reference:" args "${CMAKE_SHARED_LIBRARY_PREFIX}Kitware.mummy.Runtime.Unmanaged${CMAKE_SHARED_LIBRARY_SUFFIX}" # list of csc "/linkresource:" args "${Mummy_SNKEYFILE}" # strong name signing keyfile # Source files: "${CMAKE_CURRENT_BINARY_DIR}/AssemblyInfo.cs" "${CMAKE_CURRENT_BINARY_DIR}/MummyRuntime.cs" "${CMAKE_CURRENT_SOURCE_DIR}/WrappedException.cs" "${CMAKE_CURRENT_SOURCE_DIR}/WrappedObject.cs" ) ADD_LIBRARY(MRSmokeTest SHARED MRSmokeTest.cxx) TARGET_LINK_LIBRARIES(MRSmokeTest Kitware.mummy.Runtime.Unmanaged) ADD_EXECUTABLE(MRSmokeTestMain MRSmokeTestMain.cxx) TARGET_LINK_LIBRARIES(MRSmokeTestMain MRSmokeTest) ADD_CSHARP_LIBRARY( "Kitware.mummy.Runtime.SmokeTest" "Kitware.mummy.Runtime;MRSmokeTest" "Kitware.mummy.Runtime" "" "" "${CMAKE_CURRENT_BINARY_DIR}/MRSmokeTest.cs" ) ADD_CSHARP_EXECUTABLE( "Kitware.mummy.Runtime.SmokeTestMain" "Kitware.mummy.Runtime.SmokeTest" "Kitware.mummy.Runtime.SmokeTest;Kitware.mummy.Runtime" "" "" "${CMAKE_CURRENT_SOURCE_DIR}/MRSmokeTestMain.cs" ) ADD_CSHARP_EXECUTABLE( "Kitware.mummy.Runtime.CreateTestMain" "Kitware.mummy.Runtime.SmokeTest" "Kitware.mummy.Runtime.SmokeTest;Kitware.mummy.Runtime" "" "" "${CMAKE_CURRENT_SOURCE_DIR}/CreateTestMain.cs" ) #MESSAGE(STATUS "Mummy_BUILD_TESTING='${Mummy_BUILD_TESTING}'") IF(Mummy_BUILD_TESTING) SET(testexe MRSmokeTestMain) IF(EXECUTABLE_OUTPUT_PATH) SET(exefile ${EXECUTABLE_OUTPUT_PATH}/${Mummy_TESTING_CONFIG_PREFIX}${testexe}) ELSE(EXECUTABLE_OUTPUT_PATH) SET(exefile ${testexe}) ENDIF(EXECUTABLE_OUTPUT_PATH) ADD_TEST(mummyRuntimeTest-${testexe}-NoArgs "${exefile}") ADD_TEST(mummyRuntimeTest-${testexe} "${exefile}" "20000") IF(Mummy_RUN_LONG_TESTS) ADD_TEST(mummyRuntimeTest-${testexe}-mega "${exefile}" "1000000") ENDIF(Mummy_RUN_LONG_TESTS) IF(csc_EXECUTABLE) # # C# executables are named with ".exe" even on Mono (Linux / Mac)... # SET(testexe Kitware.mummy.Runtime.SmokeTestMain.exe) IF(EXECUTABLE_OUTPUT_PATH) SET(exefile ${EXECUTABLE_OUTPUT_PATH}/${Mummy_TESTING_CONFIG_PREFIX}${testexe}) ELSE(EXECUTABLE_OUTPUT_PATH) SET(exefile ${testexe}) ENDIF(EXECUTABLE_OUTPUT_PATH) ADD_CSHARP_TEST(mummyRuntimeTest-${testexe}-NoArgs "${exefile}") FOREACH(flag strong weak evensplit pseudorandom) ADD_CSHARP_TEST(mummyRuntimeTest-${testexe}-${flag} "${exefile}" "20000" "--${flag}") IF(Mummy_RUN_LONG_TESTS) ADD_CSHARP_TEST(mummyRuntimeTest-${testexe}-${flag}-mega "${exefile}" "1000000" "--${flag}") ENDIF(Mummy_RUN_LONG_TESTS) ENDFOREACH(flag) SET(testexe Kitware.mummy.Runtime.CreateTestMain.exe) IF(EXECUTABLE_OUTPUT_PATH) SET(exefile ${EXECUTABLE_OUTPUT_PATH}/${Mummy_TESTING_CONFIG_PREFIX}${testexe}) ELSE(EXECUTABLE_OUTPUT_PATH) SET(exefile ${testexe}) ENDIF(EXECUTABLE_OUTPUT_PATH) ADD_CSHARP_TEST(mummyRuntimeTest-${testexe}-NoArgs "${exefile}") ADD_CSHARP_TEST(mummyRuntimeTest-${testexe} "${exefile}" "20000") IF(Mummy_RUN_LONG_TESTS) ADD_CSHARP_TEST(mummyRuntimeTest-${testexe}-mega "${exefile}" "1000000") ENDIF(Mummy_RUN_LONG_TESTS) ENDIF(csc_EXECUTABLE) ENDIF(Mummy_BUILD_TESTING) mummy-1.0.3/Runtime/CreateTestMain.cs0000644000175000017500000000711012120621217017344 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: CreateTestMain.cs 109 2008-05-07 15:14:27Z david.cole $ // // $Author: david.cole $ // $Date: 2008-05-07 11:14:27 -0400 (Wed, 07 May 2008) $ // $Revision: 109 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kitware.mummy.Runtime { /// /// public class CreateTestMain { /// /// public static void Main(string[] args) { int i = 0; int n = 10000; if (args.Length>0) { n = System.Convert.ToInt32(args[0]); } Kitware.mummy.Runtime.MRSmokeTest test = new Kitware.mummy.Runtime.MRSmokeTest(true); Kitware.mummy.Runtime.Methods.Trace(System.String.Format("test.GetCppThis().Handle: {0}", test.GetCppThis().Handle)); Kitware.mummy.Runtime.Methods.Trace(System.String.Format("test.GetCppThis().Wrapper: {0}", test.GetCppThis().Wrapper)); Kitware.mummy.Runtime.MRSmokeTest testClone = test.Clone(); Kitware.mummy.Runtime.Methods.Trace(System.String.Format("testClone.GetCppThis().Handle: {0}", testClone.GetCppThis().Handle)); Kitware.mummy.Runtime.Methods.Trace(System.String.Format("testClone.GetCppThis().Wrapper: {0}", testClone.GetCppThis().Wrapper)); // After calling Clone, there should be a valid CreateWrappedObject type index // of 0 registered with the mummy.Runtime... Try to create an object and see // what we get: // Kitware.mummy.Runtime.Methods.Trace("create..."); bool created; object obj = Kitware.mummy.Runtime.Methods.CreateWrappedObject( // uint status, uint index, uint rawRefCount, System.IntPtr rawCppThis, bool callDisposalMethod 0, 0, 0, System.IntPtr.Zero, true, out created); Kitware.mummy.Runtime.Methods.Trace(System.String.Format("obj: {0}", obj)); test = (Kitware.mummy.Runtime.MRSmokeTest) obj; Kitware.mummy.Runtime.Methods.Trace(System.String.Format("test.GetCppThis().Handle: {0}", test.GetCppThis().Handle)); Kitware.mummy.Runtime.Methods.Trace(System.String.Format("test.GetCppThis().Wrapper: {0}", test.GetCppThis().Wrapper)); // Do it again to verify that the type got cached during the first call to Create... // obj = Kitware.mummy.Runtime.Methods.CreateWrappedObject( 0, 0, 0, System.IntPtr.Zero, true, out created); Kitware.mummy.Runtime.Methods.Trace(System.String.Format("obj: {0}", obj)); test = (Kitware.mummy.Runtime.MRSmokeTest) obj; Kitware.mummy.Runtime.Methods.Trace(System.String.Format("test.GetCppThis().Handle: {0}", test.GetCppThis().Handle)); Kitware.mummy.Runtime.Methods.Trace(System.String.Format("test.GetCppThis().Wrapper: {0}", test.GetCppThis().Wrapper)); // now loop (like in the other smoke test) the number of times given on // the command line so we can compare performance of this create methodology // with the performance of a strictly "new-based" strategy... // for (i= 0; i /// public class MRSmokeTest : Kitware.mummy.Runtime.WrappedObject { /// /// Automatically generated type registration mechanics. /// public new static readonly string MRClassNameKey = "@MRSMOKETEST_CLASS_NAME_KEY@"; /// /// Automatically generated type registration mechanics. /// public new const string MRFullTypeName = "Kitware.mummy.Runtime.MRSmokeTest"; /// /// Automatically generated type registration mechanics. /// static MRSmokeTest() { Kitware.mummy.Runtime.Methods.RegisterType( System.Reflection.Assembly.GetExecutingAssembly(), MRClassNameKey, System.Type.GetType(MRFullTypeName) ); } /// /// Automatically generated constructor - called from generated code. /// DO NOT call directly. /// public MRSmokeTest(IntPtr rawCppThis, bool callDisposalMethod, bool strong) : base(rawCppThis, callDisposalMethod, strong) { } [DllImport("@CMAKE_SHARED_LIBRARY_PREFIX@MRSmokeTest@CMAKE_SHARED_LIBRARY_SUFFIX@", EntryPoint = "MRSmokeTest_new")] internal static extern IntPtr MRSmokeTest_new(); /// /// public MRSmokeTest(bool strong) : this(MRSmokeTest_new(), true, strong) { } [DllImport("@CMAKE_SHARED_LIBRARY_PREFIX@MRSmokeTest@CMAKE_SHARED_LIBRARY_SUFFIX@", EntryPoint = "MRSmokeTest_delete")] internal static extern void MRSmokeTest_delete(HandleRef pThis); /// /// protected override void Dispose(bool disposing) { if (this.GetCallDisposalMethod()) { MRSmokeTest_delete(this.GetCppThis()); this.ClearCppThis(); } base.Dispose(disposing); } [DllImport("@CMAKE_SHARED_LIBRARY_PREFIX@MRSmokeTest@CMAKE_SHARED_LIBRARY_SUFFIX@", EntryPoint = "MRSmokeTest_Clone_01")] internal static extern IntPtr MRSmokeTest_Clone_01(HandleRef pThis); /// /// public MRSmokeTest Clone() { MRSmokeTest rv = null; IntPtr rvp = MRSmokeTest_Clone_01(this.GetCppThis()); if (IntPtr.Zero != rvp) { rv = new MRSmokeTest(rvp, true, false); } return rv; } } } mummy-1.0.3/Runtime/MRSmokeTest.cxx0000644000175000017500000000272512120621217017055 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MRSmokeTest.cxx 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MRSmokeTest.h" #include "MummyRuntime.h" #include //---------------------------------------------------------------------------- MRSmokeTest::MRSmokeTest() { } //---------------------------------------------------------------------------- MRSmokeTest::~MRSmokeTest() { } //---------------------------------------------------------------------------- MRSmokeTest* MRSmokeTest::Clone() { MRSmokeTest* rv = new MRSmokeTest; Kitware::mummy::Runtime::GetTypeEntry(rv, typeid(*rv).name()); return rv; } //---------------------------------------------------------------------------- extern "C" MRSMOKETEST_EXPORT MRSmokeTest* MRSmokeTest_new() { MRSmokeTest* rv = new MRSmokeTest; return rv; } //---------------------------------------------------------------------------- extern "C" MRSMOKETEST_EXPORT void MRSmokeTest_delete(MRSmokeTest* pThis) { delete pThis; } //---------------------------------------------------------------------------- extern "C" MRSMOKETEST_EXPORT MRSmokeTest* MRSmokeTest_Clone_01(MRSmokeTest* pThis) { MRSmokeTest* rv = pThis->Clone(); return rv; } mummy-1.0.3/Runtime/MRSmokeTest.h0000644000175000017500000000136112120621217016475 0ustar mathieumathieu/* ----------------------------------------------------------------------------- * MRSmokeTest.h * * Author(s) : David Cole * * Copyright (C) 2007 Kitware, Inc. * ----------------------------------------------------------------------------- */ #ifndef mummy_MRSmokeTest_h #define mummy_MRSmokeTest_h #ifdef _WIN32 #ifdef MRSmokeTest_EXPORTS #define MRSMOKETEST_EXPORT __declspec(dllexport) #else #define MRSMOKETEST_EXPORT __declspec(dllimport) #endif #endif #ifndef MRSMOKETEST_EXPORT #define MRSMOKETEST_EXPORT #endif class MRSMOKETEST_EXPORT MRSmokeTest { public: MRSmokeTest(); virtual ~MRSmokeTest(); MRSmokeTest* Clone(); private: MRSmokeTest(const MRSmokeTest&); const MRSmokeTest& operator=(const MRSmokeTest&); }; #endif mummy-1.0.3/Runtime/MRSmokeTestMain.cs0000644000175000017500000000452112120621217017461 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MRSmokeTestMain.cs 470 2009-06-12 17:43:02Z hoffman $ // // $Author: hoffman $ // $Date: 2009-06-12 13:43:02 -0400 (Fri, 12 Jun 2009) $ // $Revision: 470 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kitware.mummy.Runtime { /// /// public class SmokeTestMain { /// /// public static void Main(string[] args) { int i = 0; int n = 10000; bool strong = false; bool evensplit = false; bool pseudorandom = false; if (args.Length>0) { n = System.Convert.ToInt32(args[0]); } if (args.Length>1) { if ("--strong" == args[1]) { strong = true; } else if ("--evensplit" == args[1]) { evensplit = true; } else if ("--pseudorandom" == args[1]) { pseudorandom = true; } } Kitware.mummy.Runtime.MRSmokeTest test = new Kitware.mummy.Runtime.MRSmokeTest(strong); Kitware.mummy.Runtime.MRSmokeTest testClone = test.Clone(); Kitware.mummy.Runtime.Methods.Trace("looping..."); for (i= 0; i 0.5 ? true : false); } test = new Kitware.mummy.Runtime.MRSmokeTest(strong); } if (null == testClone) { throw new System.Exception("error: testClone is null!"); } test = null; testClone = null; uint teCount = Kitware.mummy.Runtime.Methods.GetTypeEntryCount(); Kitware.mummy.Runtime.Methods.Trace(System.String.Format("teCount: {0}", teCount)); Kitware.mummy.Runtime.Methods.Trace("about to call System.GC.Collect()..."); System.GC.Collect(); Kitware.mummy.Runtime.Methods.Trace("done with System.GC.Collect()..."); } } } mummy-1.0.3/Runtime/MRSmokeTestMain.cxx0000644000175000017500000000611512120621217017657 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MRSmokeTestMain.cxx 418 2009-03-19 19:41:27Z hoffman $ // // $Author: hoffman $ // $Date: 2009-03-19 15:41:27 -0400 (Thu, 19 Mar 2009) $ // $Revision: 418 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MRSmokeTest.h" #include "MummyRuntime.h" #include #include "stdlib.h" // atoi //---------------------------------------------------------------------------- int main(int argc, char* argv[]) { int err = 0; int i = 0; int n = 10000; if (argc>1) { n = atoi(argv[1]); } // Call ObjectRefCountChanged with bogus parameters (NULL // pointer, silly ref counts) to make sure it's robust... // Kitware::mummy::Runtime::ObjectRefCountChanged(0, 333, 444); // Call Verify *before* the loop: // std::cout << "Calling Kitware::mummy::Runtime::Verify" << std::endl; Kitware::mummy::Runtime::Verify(); std::cout << "n: " << n << std::endl; for (i= 0; iClone(); Kitware::mummy::Runtime::LookupInstanceTypeEntry(test); Kitware::mummy::Runtime::LookupInstanceTypeEntry(clone); delete clone; delete test; } // Valid calls (as long as there is at least one entry by now...): // std::cout << "Testing mummy::Runtime methods with valid calls..." << std::endl; MRSmokeTest* test2 = new MRSmokeTest; MRSmokeTest* clone2 = test2->Clone(); Kitware::mummy::Runtime::ObjectRefCountChanged(test2, 1, 2); Kitware::mummy::Runtime::LookupInstanceTypeEntry(test2); Kitware::mummy::Runtime::LookupInstanceTypeEntry(clone2); Kitware::mummy::Runtime::GetTypeEntryByIndex(0); Kitware::mummy::Runtime::GetTypeEntryClassNameKey(0); Kitware::mummy::Runtime::ObjectRefCountChanged(test2, 2, 1); delete clone2; delete test2; std::cout << "Calling Kitware::mummy::Runtime::Print" << std::endl; std::cout << Kitware::mummy::Runtime::Print() << std::endl; std::cout << "Calling Kitware::mummy::Runtime::Verify" << std::endl; Kitware::mummy::Runtime::Verify(); std::cout << "Calling Kitware::mummy::Runtime::GetTypeEntryByIndex(0)" << std::endl; Kitware::mummy::TypeEntry* entry = Kitware::mummy::Runtime::GetTypeEntryByIndex(0); if (entry) { std::cout << "entry:" << std::endl; std::cout << entry->Print() << std::endl; entry->GetObjectRefCountChangedCallback(); } else { std::cout << "error: no entry found at index 0" << std::endl; err = 1; } // Invalid calls (unless there are somehow 4 billion++ entries...): // std::cout << "Testing mummy::Runtime methods with invalid calls..." << std::endl; Kitware::mummy::Runtime::ObjectRefCountChanged(0, 0, 0); Kitware::mummy::Runtime::LookupInstanceTypeEntry(0); Kitware::mummy::Runtime::GetTypeEntryByIndex((Kitware::mummy::Runtime::TypeEntryIndex) -1); Kitware::mummy::Runtime::GetTypeEntryClassNameKey((Kitware::mummy::Runtime::TypeEntryIndex) -1); std::cout << "Test done" << std::endl; return err; } mummy-1.0.3/Runtime/MummyRuntime.cs.in0000644000175000017500000007131012120621217017554 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyRuntime.cs.in 470 2009-06-12 17:43:02Z hoffman $ // // $Author: hoffman $ // $Date: 2009-06-12 13:43:02 -0400 (Fri, 12 Jun 2009) $ // $Revision: 470 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- using System.Runtime.InteropServices; // DllImport and HandleRef both live here // Online .NET Framework help at: // http://msdn2.microsoft.com/en-us/library/d11h6832(VS.80).aspx namespace Kitware.mummy.Runtime { /// /// public class Methods { // Construct exactly one instance of Runtime when this dll is loaded. // This object is a singleton. // private static Methods Instance = new Methods(); // Map of "System.IntPtr" to "object" -- added to and removed from // by instances/methods of WrappedObject: // private System.Collections.Hashtable WrappedObjectsTable = null; private uint WrappedObjectsTableHits = 0; private uint WrappedObjectsTableMisses = 0; // Map of "string" to "System.Type" -- added to by client dlls // that have create-able types: // private System.Collections.Hashtable RegisteredTypes = null; // Collection of assemblies that implement registered types: // private System.Collections.Hashtable RegisteredAssemblies = null; // Direct index based array of "System.Type" -- added to "on demand" // as a type is requested... // private System.Collections.ArrayList IndexedConstructors = null; // Delegate/Id of callback handler for tracking refcount changes on // the unmanaged side: // private delegate void ObjectRefCountChangedCallback(System.IntPtr arg0, uint arg1, uint arg2); private ObjectRefCountChangedCallback Callback = null; private uint CallbackId = System.UInt32.MaxValue; // Flag for whether or not to call Trace from methods defined in this // file: // private static bool TraceInternalCalls = false; // Flags for whether or not to emit to console or debugger output window // when Trace is called: // private static bool TraceToConsoleError = true; private static bool TraceToConsoleOut = false; private static bool TraceToDebug = true; //------------------------------------------------------------------------- /// /// Export layer functions for 'Runtime' are exported from /// the DLL named by the value of this variable. /// public const string RuntimeEL_dll = "@CMAKE_SHARED_LIBRARY_PREFIX@Kitware.mummy.Runtime.Unmanaged@CMAKE_SHARED_LIBRARY_SUFFIX@"; //------------------------------------------------------------------------- /// /// private Methods() { } //------------------------------------------------------------------------- /// /// ~Methods() { ForceRemoveCallbacksImpl(); } //------------------------------------------------------------------------- /// /// public static void Trace(string s) { if (TraceToConsoleError) { System.Console.Error.WriteLine(s); } if (TraceToConsoleOut) { System.Console.Out.WriteLine(s); } if (TraceToDebug) { System.Diagnostics.Debug.WriteLine(s); } } //------------------------------------------------------------------------- /// /// private void Instance_ObjectRefCountChangedCallback(System.IntPtr rawCppThis, uint oldCount, uint newCount) { if (2==newCount && 1==oldCount) { // Becoming a "strongly referenced object" on the unmanaged side. Keep // a strong reference to it in the table: this.EnsureStrongTableReference(rawCppThis); } else if (1==newCount && 2==oldCount) { // Only our table-held managed wrapper is left referencing the object // on the unmanaged side. Convert our table-held reference to a weak // reference: this.EnsureWeakTableReference(rawCppThis); } } //------------------------------------------------------------------------- /// /// private void EnsureStrongTableReference(System.IntPtr rawCppThis) { if (null != this.WrappedObjectsTable) { lock(this.WrappedObjectsTable.SyncRoot) { if (this.WrappedObjectsTable.ContainsKey(rawCppThis)) { System.WeakReference wr = this.WrappedObjectsTable[rawCppThis] as System.WeakReference; if (null != wr) { // Replace the WeakReference with the actual object: this.WrappedObjectsTable[rawCppThis] = wr.Target; if (TraceInternalCalls) { Trace(System.String.Format("rawCppThis '0x{0:x8}' converted to strong table reference", (long)rawCppThis)); } } } } } } //------------------------------------------------------------------------- /// /// private void EnsureWeakTableReference(System.IntPtr rawCppThis) { if (null != this.WrappedObjectsTable) { lock(this.WrappedObjectsTable.SyncRoot) { if (this.WrappedObjectsTable.ContainsKey(rawCppThis)) { object obj = this.WrappedObjectsTable[rawCppThis]; System.WeakReference wr = obj as System.WeakReference; if (null == wr) { // Replace the actual object with a WeakReference: this.WrappedObjectsTable[rawCppThis] = new System.WeakReference(obj); if (TraceInternalCalls) { Trace(System.String.Format("rawCppThis '0x{0:x8}' converted to weak table reference", (long)rawCppThis)); } } } } } } //------------------------------------------------------------------------- /// /// private void AddTableReferenceImpl(System.IntPtr rawCppThis, object obj, bool strong) { if (rawCppThis == System.IntPtr.Zero) { throw new System.Exception(System.String.Format("error: A 'null' rawCppThis pointer may not be used as a WrappedObjectsTable key.")); } if (null == this.WrappedObjectsTable) { this.WrappedObjectsTable = new System.Collections.Hashtable(); this.Callback = new ObjectRefCountChangedCallback(this.Instance_ObjectRefCountChangedCallback); this.CallbackId = AddObjectRefCountChangedCallback(this.Callback); } lock(this.WrappedObjectsTable.SyncRoot) { if (this.WrappedObjectsTable.ContainsKey(rawCppThis)) { System.WeakReference wr = this.WrappedObjectsTable[rawCppThis] as System.WeakReference; if (null == wr) { throw new System.Exception(System.String.Format("error: Duplicate rawCppThis - existing strong reference. Attempting to add '0x{0:x8}' again.", (long)rawCppThis)); } if (wr.IsAlive) { if (strong) { throw new System.Exception(System.String.Format("error: Duplicate rawCppThis - weak reference that is still alive. Attempting to add '0x{0:x8}' again.", (long)rawCppThis)); } else { // For now, early in the "table-fied mummy" adoption process, allow // a weak reference to replace another weak reference. The assumption // here is that the C++ object has gone away and is being replaced by // another C++ object since the C++ object allocator is likely to reuse // the same pointer value for a subsequent allocation... // // Ideally, we should have had a refcount on that object, but some mummy // wrapped objects are not refcounted and some do not have fully proper // bug-free refcounting yet... // Trace(""); Trace(System.String.Format("error: potential refcounting error: Duplicate rawCppThis - weak reference that is still alive. Attempting to add '0x{0:x8}' again.", (long)rawCppThis)); Trace(System.String.Format(" Allowing new wrapped object to take over table key...")); Trace(System.String.Format(" Original object should *not* have been destroyed while we still had it in our table without notifying us...")); Trace(""); } } } if (strong) { this.WrappedObjectsTable[rawCppThis] = obj; if (TraceInternalCalls) { Trace(System.String.Format("rawCppThis '0x{0:x8}' added as strong table reference", (long)rawCppThis)); } } else { this.WrappedObjectsTable[rawCppThis] = new System.WeakReference(obj); if (TraceInternalCalls) { Trace(System.String.Format("rawCppThis '0x{0:x8}' added as weak table reference", (long)rawCppThis)); } } } } //------------------------------------------------------------------------- /// /// public static void AddTableReference(System.IntPtr rawCppThis, object obj, bool strong) { Instance.AddTableReferenceImpl(rawCppThis, obj, strong); } //------------------------------------------------------------------------- /// /// private void RemoveTableReferenceImpl(System.IntPtr rawCppThis) { if (null != this.WrappedObjectsTable) { lock(this.WrappedObjectsTable.SyncRoot) { this.WrappedObjectsTable.Remove(rawCppThis); if (TraceInternalCalls) { Trace(System.String.Format("rawCppThis '0x{0:x8}' removed", (long)rawCppThis)); } } } } //------------------------------------------------------------------------- /// /// public static void RemoveTableReference(System.IntPtr rawCppThis) { Instance.RemoveTableReferenceImpl(rawCppThis); } //------------------------------------------------------------------------- [DllImport(RuntimeEL_dll, EntryPoint = "Kitware_mummy_Runtime_AddObjectRefCountChangedCallback")] private static extern uint Kitware_mummy_Runtime_AddObjectRefCountChangedCallback(ObjectRefCountChangedCallback cb); /// /// private static uint AddObjectRefCountChangedCallback(ObjectRefCountChangedCallback cb) { uint rv = Kitware_mummy_Runtime_AddObjectRefCountChangedCallback(cb); return rv; } //------------------------------------------------------------------------- [DllImport(RuntimeEL_dll, EntryPoint = "Kitware_mummy_Runtime_GetTypeEntryCount")] internal static extern uint Kitware_mummy_Runtime_GetTypeEntryCount(); /// /// public static uint GetTypeEntryCount() { uint rv = Kitware_mummy_Runtime_GetTypeEntryCount(); return rv; } //------------------------------------------------------------------------- [DllImport(RuntimeEL_dll, EntryPoint = "Kitware_mummy_Runtime_GetTypeEntryClassNameKey")] internal static extern System.IntPtr Kitware_mummy_Runtime_GetTypeEntryClassNameKey(uint mteIndex); /// /// public static string GetTypeEntryClassNameKey(uint mteIndex) { string rv = Marshal.PtrToStringAnsi(Kitware_mummy_Runtime_GetTypeEntryClassNameKey(mteIndex)); return rv; } //------------------------------------------------------------------------- [DllImport(RuntimeEL_dll, EntryPoint = "Kitware_mummy_Runtime_RemoveObjectRefCountChangedCallback")] internal static extern void Kitware_mummy_Runtime_RemoveObjectRefCountChangedCallback(uint cbid); /// /// private static void RemoveObjectRefCountChangedCallback(uint cbid) { Kitware_mummy_Runtime_RemoveObjectRefCountChangedCallback(cbid); } /// /// Wrapped classes need to call RegisterType somehow from their static class /// initialization. The first time the RegisterType method sees a given assembly /// it will force all the static constructors in that assumbly to execute at that /// time. This has the effect of forcing all RegisterType calls for a whole assembly /// as a result of the first RegisterType call from that assembly. After which point, /// any creatable class located in that assembly should be available in the /// RegisteredTypes table. /// private void ForceReferenceStaticConstructors(System.Reflection.Assembly assembly, string classNameKey) { if (TraceInternalCalls) { Trace(System.String.Format("Force loading types from assembly: {0}", assembly.GetName().FullName)); } foreach(System.Type et in assembly.GetExportedTypes()) { if (et.IsClass) { System.Reflection.FieldInfo fi = et.GetField("MRClassNameKey"); if (null != fi && fi.IsStatic) { // Referencing the static field by calling fi.GetValue forces the // static constructor to be called, which then calls us back with // a RegisterType call. // string s = fi.GetValue(null) as string; if (null == s) { throw new System.Exception(System.String.Format("error: could not get field value MRClassNameKey for class '{0}'.", et.Name)); } } } } } private void RegisterTypeImpl(System.Reflection.Assembly assembly, string classNameKey, System.Type t) { if (null == this.RegisteredAssemblies) { this.RegisteredAssemblies = new System.Collections.Hashtable(); } if (null == this.RegisteredTypes) { this.RegisteredTypes = new System.Collections.Hashtable(); } if (null == this.RegisteredAssemblies[assembly]) { this.RegisteredAssemblies[assembly] = assembly; ForceReferenceStaticConstructors(assembly, classNameKey); } if (null != this.RegisteredTypes[classNameKey]) { throw new System.Exception(System.String.Format("error: RegisterType called more than once with classNameKey='{0}'. Class key duplicated in multiple assemblies? Static initializer called more than once?", classNameKey)); } this.RegisteredTypes[classNameKey] = t; } /// /// public static void RegisterType(System.Reflection.Assembly assembly, string classNameKey, System.Type t) { Instance.RegisterTypeImpl(assembly, classNameKey, t); } //------------------------------------------------------------------------- /// /// private uint ClassNameKeyToIndex(string classNameKey) { // david.cole::fix - TODO - make this another table that does a // quicker lookup than this stupid for loop of the index based on // the classNameKey... // bool found = false; uint i = 0; uint n = GetTypeEntryCount(); for (i = 0; !found && i < n; ++i) { if (classNameKey == GetTypeEntryClassNameKey(i)) { return i; } } // Invalid mteIndex value: // return System.UInt32.MaxValue; } //------------------------------------------------------------------------- /// /// private System.Reflection.ConstructorInfo GetConstructorInfo(uint mteIndex) { System.Reflection.ConstructorInfo ci = null; // First look in IndexedConstructors if possible: // if (null != this.IndexedConstructors) { if (mteIndex < this.IndexedConstructors.Count) { ci = (System.Reflection.ConstructorInfo)this.IndexedConstructors[(int)mteIndex]; if (null != ci) { if (TraceInternalCalls) { Trace("info: found ci in IndexedConstructors"); } } } } // ci not in IndexedConstructors; call over to unmanaged side to get the // classNameKey for this mteIndex and lookup by classNameKey in // RegisteredTypes and get the correct constructor. Then save ci in // IndexedConstructors to make subsequent lookups fast. // if (null == ci) { string classNameKey = GetTypeEntryClassNameKey(mteIndex); System.Type t = null; if (null != this.RegisteredTypes) { t = (System.Type) this.RegisteredTypes[classNameKey]; } if (null == t) { throw new System.Exception(System.String.Format( "error: could not get registered type - mteIndex='{0}' classNameKey='{1}'", mteIndex, classNameKey)); } // Get a constructor for type t with 3 params of the expected types: // System.Type[] ctorParamTypes = new System.Type[3]; ctorParamTypes[0] = System.Type.GetType("System.IntPtr"); ctorParamTypes[1] = System.Type.GetType("System.Boolean"); ctorParamTypes[2] = System.Type.GetType("System.Boolean"); ci = t.GetConstructor(ctorParamTypes); if (null == ci) { throw new System.Exception( "error: expected 3 parameter constructor is unavailable - is it public?"); } // Save ci in IndexedConstructors to make future lookups lightning fast: // if (TraceInternalCalls) { Trace( System.String.Format("info: found ci via RegisteredTypes lookup - mteIndex: {0} - classNameKey: {1}", mteIndex, classNameKey)); } if (null == this.IndexedConstructors) { this.IndexedConstructors = new System.Collections.ArrayList(128); } if (mteIndex < this.IndexedConstructors.Count && null != this.IndexedConstructors[(int)mteIndex]) { throw new System.Exception(System.String.Format( "error: IndexedConstructors table already has a non-null entry at mteIndex {0}", mteIndex)); } // Add null ConstructorInfo objects to our list until we can call [(int)mteIndex] // without getting the "list not big enough to set at that index" exception... // The null values may get overwritten later when those types are required for // CreateWrappedObject calls. Or maybe not. // while (mteIndex >= this.IndexedConstructors.Count) { this.IndexedConstructors.Add(null); } this.IndexedConstructors[(int)mteIndex] = ci; } if (null == ci) { throw new System.Exception("error: mteIndex yields null System.Type in GetSystemType..."); } return ci; } /// /// Factory method to create a wrapped object from a registered TypeEntry. /// Client dlls that provide objects should register their known types via /// RegisterType prior to any possible call to CreateWrappedObject. /// private object CreateWrappedObjectImpl(uint mteStatus, uint mteIndex, uint rawRefCount, System.IntPtr rawCppThis, bool callDisposalMethod, out bool created) { object obj = null; if (null != this.WrappedObjectsTable) { lock(this.WrappedObjectsTable.SyncRoot) { obj = this.WrappedObjectsTable[rawCppThis]; System.WeakReference wr = obj as System.WeakReference; if (null != wr) { obj = wr.Target; } } } if (null != obj) { created = false; ++WrappedObjectsTableHits; } else { created = true; ++WrappedObjectsTableMisses; // Get a constructor info for the type of the object we're supposed // to create via mteIndex: // System.Reflection.ConstructorInfo ci = GetConstructorInfo(mteIndex); // Invoke the constructor with parameters: bool strong = true; if (0 == mteStatus || rawRefCount < 2) { strong = false; } object[] ctorParams = new object[3]; ctorParams[0] = rawCppThis; ctorParams[1] = callDisposalMethod; ctorParams[2] = strong; obj = ci.Invoke(ctorParams); } return obj; } //------------------------------------------------------------------------- /// /// Used for the quickest table-based creation possible where we know the /// mteIndex directly. /// public static object CreateWrappedObject(uint mteStatus, uint mteIndex, uint rawRefCount, System.IntPtr rawCppThis, bool callDisposalMethod, out bool found) { return Instance.CreateWrappedObjectImpl(mteStatus, mteIndex, rawRefCount, rawCppThis, callDisposalMethod, out found); } //------------------------------------------------------------------------- /// /// private object CreateWrappedObjectImpl(string classNameKey, System.IntPtr rawCppThis, bool callDisposalMethod, out bool found) { uint mteIndex = ClassNameKeyToIndex(classNameKey); return this.CreateWrappedObjectImpl(0, mteIndex, 1, rawCppThis, callDisposalMethod, out found); } //------------------------------------------------------------------------- /// /// Used for EventArgs creation where we know the class name, but not the /// mteIndex. /// public static object CreateWrappedObject(string classNameKey, System.IntPtr rawCppThis, bool callDisposalMethod, out bool found) { return Instance.CreateWrappedObjectImpl(classNameKey, rawCppThis, callDisposalMethod, out found); } //------------------------------------------------------------------------- /// /// public static string PrintIndexedConstructorsTable() { int i; string s = ""; if (null != Instance && null != Instance.IndexedConstructors) { s = System.String.Format("{0}\n Instance.IndexedConstructors details:", s); s = System.String.Format("{0}\n Count: {1}", s, Instance.IndexedConstructors.Count); i = 0; lock (Instance.IndexedConstructors.SyncRoot) { foreach (System.Reflection.ConstructorInfo ci in Instance.IndexedConstructors) { s = System.String.Format("{0}\n Entry: {1}", s, i); s = System.String.Format("{0}\n ci: {1}", s, ci); ++i; } } } Trace(s); return s; } //------------------------------------------------------------------------- /// /// public static string PrintRegisteredAssembliesTable() { int i; string s = ""; if (null != Instance && null != Instance.RegisteredAssemblies) { s = System.String.Format("{0}\n Instance.RegisteredAssemblies details:", s); s = System.String.Format("{0}\n Count: {1}", s, Instance.RegisteredAssemblies.Count); i = 0; lock (Instance.RegisteredAssemblies.SyncRoot) { foreach (System.Collections.DictionaryEntry de in Instance.RegisteredAssemblies) { s = System.String.Format("{0}\n Entry: {1}", s, i); s = System.String.Format("{0}\n Key: {1}", s, de.Key); s = System.String.Format("{0}\n Value: {1}", s, de.Value); ++i; } } } Trace(s); return s; } //------------------------------------------------------------------------- /// /// public static string PrintRegisteredTypesTable() { int i; string s = ""; if (null != Instance) { if (null != Instance.RegisteredTypes) { s = System.String.Format("{0}\n Instance.RegisteredTypes details:", s); s = System.String.Format("{0}\n Count: {1}", s, Instance.RegisteredTypes.Count); i = 0; lock (Instance.RegisteredTypes.SyncRoot) { foreach (System.Collections.DictionaryEntry de in Instance.RegisteredTypes) { s = System.String.Format("{0}\n Entry: {1}", s, i); s = System.String.Format("{0}\n Key: {1}", s, de.Key); s = System.String.Format("{0}\n Value: {1}", s, de.Value); ++i; } } } } Trace(s); return s; } //------------------------------------------------------------------------- /// /// public static string PrintWrappedObjectsTable() { int i; string s = ""; if (null != Instance && null != Instance.WrappedObjectsTable) { s = System.String.Format("{0}\n Instance.WrappedObjectsTable details:", s); s = System.String.Format("{0}\n Count: {1}", s, Instance.WrappedObjectsTable.Count); i = 0; lock (Instance.WrappedObjectsTable.SyncRoot) { foreach (System.Collections.DictionaryEntry de in Instance.WrappedObjectsTable) { s = System.String.Format("{0}\n Entry: {1}", s, i); s = System.String.Format("{0}\n Key: 0x{1:x8}", s, (long)(System.IntPtr)de.Key); s = System.String.Format("{0}\n Value: {1}", s, de.Value); ++i; } } } Trace(s); return s; } //------------------------------------------------------------------------- /// /// public static string Print(bool details) { string s = System.String.Format(" Instance: {0}", Instance); if (null != Instance) { s = System.String.Format("{0}\n Instance.WrappedObjectsTable: {1}", s, Instance.WrappedObjectsTable); s = System.String.Format("{0}\n Instance.WrappedObjectsTableHits: {1}", s, Instance.WrappedObjectsTableHits); s = System.String.Format("{0}\n Instance.WrappedObjectsTableMisses: {1}", s, Instance.WrappedObjectsTableMisses); s = System.String.Format("{0}\n Instance.RegisteredTypes: {1}", s, Instance.RegisteredTypes); s = System.String.Format("{0}\n Instance.RegisteredAssemblies: {1}", s, Instance.RegisteredAssemblies); s = System.String.Format("{0}\n Instance.IndexedConstructors: {1}", s, Instance.IndexedConstructors); s = System.String.Format("{0}\n Instance.CallbackId: {1}", s, Instance.CallbackId); } s = System.String.Format("{0}\n TraceInternalCalls: {1}", s, TraceInternalCalls); s = System.String.Format("{0}\n TraceToConsoleError: {1}", s, TraceToConsoleError); s = System.String.Format("{0}\n TraceToConsoleOut: {1}", s, TraceToConsoleOut); s = System.String.Format("{0}\n TraceToDebug: {1}", s, TraceToDebug); Trace(s); if (details) { s = System.String.Format("{0}\n\n{1}", s, PrintIndexedConstructorsTable()); s = System.String.Format("{0}\n\n{1}", s, PrintRegisteredAssembliesTable()); s = System.String.Format("{0}\n\n{1}", s, PrintRegisteredTypesTable()); s = System.String.Format("{0}\n\n{1}", s, PrintWrappedObjectsTable()); } return s; } //------------------------------------------------------------------------- /// /// public static string Print() { return Print(true); } //------------------------------------------------------------------------- /// /// public static bool Verify() { return true; } //------------------------------------------------------------------------- /// /// public static void ForceClearWrappedObjectsTable() { if (null != Instance.WrappedObjectsTable) { Instance.WrappedObjectsTable.Clear(); } } //------------------------------------------------------------------------- /// /// private void ForceRemoveCallbacksImpl() { if (System.UInt32.MaxValue != this.CallbackId) { RemoveObjectRefCountChangedCallback(this.CallbackId); this.Callback = null; this.CallbackId = System.UInt32.MaxValue; } } //------------------------------------------------------------------------- /// /// public static void ForceRemoveCallbacks() { Instance.ForceRemoveCallbacksImpl(); } } } mummy-1.0.3/Runtime/MummyRuntime.cxx0000644000175000017500000001505312120621217017346 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyRuntime.cxx 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyRuntime.h" #include #include #include //---------------------------------------------------------------------------- namespace Kitware { namespace mummy { //---------------------------------------------------------------------------- Runtime Runtime::Instance; //---------------------------------------------------------------------------- class RuntimeInternals { public: std::map TypeEntriesMap; std::vector TypeEntriesVector; Runtime::TypeEntryIndex NextTypeEntryIndex; std::map Callbacks; unsigned int NextCallbackId; }; //---------------------------------------------------------------------------- Runtime::Runtime() { this->Internals = new RuntimeInternals; //this->Internals->TypeEntriesMap.clear(); // as initialized... //this->Internals->TypeEntriesVector.clear(); // as initialized... this->Internals->NextTypeEntryIndex = 0; //this->Internals->Callbacks.clear(); // as initialized... this->Internals->NextCallbackId = 0; } //---------------------------------------------------------------------------- Runtime::~Runtime() { std::vector::iterator it; for ( it = this->Internals->TypeEntriesVector.begin(); it != this->Internals->TypeEntriesVector.end(); ++it) { delete *it; } this->Internals->TypeEntriesMap.clear(); this->Internals->TypeEntriesVector.clear(); delete this->Internals; this->Internals = 0; } //---------------------------------------------------------------------------- TypeEntry* Runtime::GetTypeEntry(void*, const char* classNameKey) { TypeEntry* entry = 0; //if (obj) // { // entry = LookupInstanceTypeEntry(obj); // } //if (0 == entry) // { entry = LookupClassTypeEntry(classNameKey); // } return entry; } //---------------------------------------------------------------------------- TypeEntry* Runtime::LookupInstanceTypeEntry(void*) { // If this ever gets implemented to do an "external associative" // instance based lookup... uncomment the code in GetTypeEntry. // Only do it if instance based lookup might be faster than the // classNameKey lookup we already have... // return 0; } //---------------------------------------------------------------------------- TypeEntry* Runtime::LookupClassTypeEntry(const char* classNameKey) { TypeEntry* entry = Instance.Internals->TypeEntriesMap[classNameKey]; if (0 == entry) { entry = new TypeEntry(classNameKey, Instance.Internals->NextTypeEntryIndex); Instance.Internals->TypeEntriesMap[classNameKey] = entry; Instance.Internals->TypeEntriesVector.push_back(entry); ++Instance.Internals->NextTypeEntryIndex; } return entry; } //---------------------------------------------------------------------------- TypeEntry* Runtime::GetTypeEntryByIndex(TypeEntryIndex index) { if (indexTypeEntriesVector.size()) { return Instance.Internals->TypeEntriesVector[index]; } // david.cole::fix -- todo -- throw exception instead of returning non-data...? return 0; } //---------------------------------------------------------------------------- Runtime::TypeEntryIndex Runtime::GetTypeEntryCount() { return static_cast( Instance.Internals->TypeEntriesVector.size()); } //---------------------------------------------------------------------------- const char* Runtime::GetTypeEntryClassNameKey(TypeEntryIndex index) { if (indexTypeEntriesVector.size()) { return Instance.Internals->TypeEntriesVector[index]->GetClassNameKey(); } // david.cole::fix -- todo -- throw exception instead of returning non-data...? return ""; } //---------------------------------------------------------------------------- unsigned int Runtime::AddObjectRefCountChangedCallback(ObjectRefCountChangedCallback cb) { unsigned int cbid = Instance.Internals->NextCallbackId; Instance.Internals->Callbacks[cbid] = cb; ++Instance.Internals->NextCallbackId; return cbid; } //---------------------------------------------------------------------------- void Runtime::RemoveObjectRefCountChangedCallback(unsigned int cbid) { Instance.Internals->Callbacks.erase(cbid); } //---------------------------------------------------------------------------- void Runtime::ObjectRefCountChanged(void *obj, unsigned int oldCount, unsigned int newCount) { std::map::iterator cbit; cbit = Instance.Internals->Callbacks.begin(); while (cbit != Instance.Internals->Callbacks.end()) { (*cbit->second)(obj, oldCount, newCount); ++cbit; } } //---------------------------------------------------------------------------- const char* Runtime::Print() { // david.cole::fix -- todo -- implement this... return ""; } //---------------------------------------------------------------------------- bool Runtime::Verify() { // david.cole::fix -- todo -- implement this fully... if (Instance.Internals->TypeEntriesMap.size() != Instance.Internals->TypeEntriesVector.size()) { return false; } return true; } //---------------------------------------------------------------------------- } } //---------------------------------------------------------------------------- // ...and the built-in export layer: //---------------------------------------------------------------------------- extern "C" MUMMY_RUNTIME_EXPORT Kitware::mummy::Runtime::TypeEntryIndex Kitware_mummy_Runtime_GetTypeEntryCount() { return Kitware::mummy::Runtime::GetTypeEntryCount(); } extern "C" MUMMY_RUNTIME_EXPORT const char* Kitware_mummy_Runtime_GetTypeEntryClassNameKey(Kitware::mummy::Runtime::TypeEntryIndex index) { return Kitware::mummy::Runtime::GetTypeEntryClassNameKey(index); } extern "C" MUMMY_RUNTIME_EXPORT void Kitware_mummy_Runtime_RemoveObjectRefCountChangedCallback(unsigned int cbid) { return Kitware::mummy::Runtime::RemoveObjectRefCountChangedCallback(cbid); } extern "C" MUMMY_RUNTIME_EXPORT unsigned int Kitware_mummy_Runtime_AddObjectRefCountChangedCallback(Kitware::mummy::Runtime::ObjectRefCountChangedCallback cb) { return Kitware::mummy::Runtime::AddObjectRefCountChangedCallback(cb); } mummy-1.0.3/Runtime/MummyRuntime.h0000644000175000017500000000453312120621217016774 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyRuntime.h // // Author(s) : David Cole // // Copyright (C) 2007 Kitware, Inc. //---------------------------------------------------------------------------- #ifndef mummy_MummyRuntime_h #define mummy_MummyRuntime_h #include #ifdef _WIN32 #ifdef Kitware_mummy_Runtime_Unmanaged_EXPORTS #define MUMMY_RUNTIME_EXPORT __declspec(dllexport) #else #define MUMMY_RUNTIME_EXPORT __declspec(dllimport) #endif #define MUMMY_RUNTIME_CC __stdcall #endif #ifndef MUMMY_RUNTIME_EXPORT #define MUMMY_RUNTIME_EXPORT #endif #ifndef MUMMY_RUNTIME_CC #define MUMMY_RUNTIME_CC #endif namespace Kitware { namespace mummy { class Runtime; class RuntimeInternals; class TypeEntry; class TypeEntryInternals; class MUMMY_RUNTIME_EXPORT Runtime { public: typedef unsigned int TypeEntryIndex; static TypeEntry* GetTypeEntry(void* obj, const char* classNameKey); static TypeEntry* LookupInstanceTypeEntry(void* obj); static TypeEntry* LookupClassTypeEntry(const char* classNameKey); static TypeEntry* GetTypeEntryByIndex(TypeEntryIndex index); static TypeEntryIndex GetTypeEntryCount(); static const char* GetTypeEntryClassNameKey(TypeEntryIndex index); typedef void (MUMMY_RUNTIME_CC *ObjectRefCountChangedCallback)(void* obj, unsigned int oldCount, unsigned int newCount); static unsigned int AddObjectRefCountChangedCallback(ObjectRefCountChangedCallback cb); static void RemoveObjectRefCountChangedCallback(unsigned int cbid); static void MUMMY_RUNTIME_CC ObjectRefCountChanged(void* obj, unsigned int oldCount, unsigned int newCount); static const char* Print(); static bool Verify(); private: static Runtime Instance; Runtime(); virtual ~Runtime(); RuntimeInternals* Internals; Runtime(const Runtime&); const Runtime& operator=(const Runtime&); }; class MUMMY_RUNTIME_EXPORT TypeEntry { public: TypeEntry(const char* classNameKey, const Runtime::TypeEntryIndex& index); virtual ~TypeEntry(); const char* GetClassNameKey() const; Runtime::TypeEntryIndex GetIndex() const; Runtime::ObjectRefCountChangedCallback GetObjectRefCountChangedCallback() const; const char* Print() const; private: TypeEntryInternals* Internals; TypeEntry(); TypeEntry(const TypeEntry&); const TypeEntry& operator=(const TypeEntry&); }; } } #endif mummy-1.0.3/Runtime/MummySettings.xml.in0000644000175000017500000000072012120621217020121 0ustar mathieumathieu mummy-1.0.3/Runtime/MummyTypeEntry.cs0000644000175000017500000000346112120621217017471 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyTypeEntry.cs 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- //using System; //using System.Runtime.InteropServices; // DllImport and HandleRef both live here //namespace Kitware.mummy.Runtime //{ /// /// //public class TypeEntry : WrappedObject //{ /// /// Automatically generated constructor - called from generated code. /// DO NOT call directly. /// // internal TypeEntry(IntPtr rawCppThis, bool callDisposalMethod) : base(rawCppThis, callDisposalMethod) // { // } /// /// Automatically generated protected Dispose method - called from /// public Dispose or the C# destructor. DO NOT call directly. /// // protected override void Dispose(bool disposing) // { // base.Dispose(disposing); // } // [DllImport(Runtime.RuntimeEL_dll, EntryPoint = "mummy_TypeEntry_GetClassNameKey_01")] // internal static extern IntPtr mummy_TypeEntry_GetClassNameKey_01(HandleRef pThis); /// /// // public string GetClassNameKey() // { // string rv = Marshal.PtrToStringAnsi(mummy_TypeEntry_GetClassNameKey_01(this.GetCppThis())); // return rv; // } // [DllImport(Runtime.RuntimeEL_dll, EntryPoint = "mummy_TypeEntry_GetIndex_02")] // internal static extern uint mummy_TypeEntry_GetIndex_02(HandleRef pThis); /// /// // public uint GetIndex() // { // uint rv = mummy_TypeEntry_GetIndex_02(this.GetCppThis()); // return rv; // } //} //} mummy-1.0.3/Runtime/MummyTypeEntry.cxx0000644000175000017500000000436512120621217017672 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: MummyTypeEntry.cxx 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- #include "MummyTypeEntry.h" #include //---------------------------------------------------------------------------- namespace Kitware { namespace mummy { //---------------------------------------------------------------------------- class TypeEntryInternals { public: std::string ClassNameKey; Runtime::TypeEntryIndex Index; Runtime::ObjectRefCountChangedCallback ObjectRefCountChangedCallback; }; //---------------------------------------------------------------------------- TypeEntry::TypeEntry(const char* classNameKey, const Runtime::TypeEntryIndex& index) { this->Internals = new TypeEntryInternals; if (classNameKey) { this->Internals->ClassNameKey = classNameKey; } else { //this->Internals->ClassNameKey = ""; // as initialized... } this->Internals->Index = index; this->Internals->ObjectRefCountChangedCallback = Runtime::ObjectRefCountChanged; } //---------------------------------------------------------------------------- TypeEntry::~TypeEntry() { delete this->Internals; this->Internals = 0; } //---------------------------------------------------------------------------- const char* TypeEntry::GetClassNameKey() const { return this->Internals->ClassNameKey.c_str(); } //---------------------------------------------------------------------------- Runtime::TypeEntryIndex TypeEntry::GetIndex() const { return this->Internals->Index; } //---------------------------------------------------------------------------- Runtime::ObjectRefCountChangedCallback TypeEntry::GetObjectRefCountChangedCallback() const { return this->Internals->ObjectRefCountChangedCallback; } //---------------------------------------------------------------------------- const char* TypeEntry::Print() const { // david.cole::fix -- todo -- implement this... return ""; } //---------------------------------------------------------------------------- } } mummy-1.0.3/Runtime/MummyTypeEntry.h0000644000175000017500000000053012120621217017305 0ustar mathieumathieu//---------------------------------------------------------------------------- // MummyTypeEntry.h // // Author(s) : David Cole // // Copyright (C) 2007 Kitware, Inc. //---------------------------------------------------------------------------- #ifndef mummy_MummyTypeEntry_h #define mummy_MummyTypeEntry_h #include "MummyRuntime.h" #endif mummy-1.0.3/Runtime/WrappedException.cs0000644000175000017500000001146012120621217017760 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: WrappedException.cs 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- namespace Kitware.mummy.Runtime { /// /// Base class for mummy-generated C# classes. /// public class WrappedException : System.Exception, System.IDisposable { //------------------------------------------------------------------------ /// /// MRClassNameKey should be the value that is returned by the C++ RTTI /// function typeid(*obj).name() for an unmanaged C++ object. /// public static readonly string MRClassNameKey = "no equivalent unmanaged class"; //------------------------------------------------------------------------ /// /// MRFullTypeName should be the same as the fully qualified name of this /// C# class... /// public const string MRFullTypeName = "Kitware.mummy.Runtime.WrappedException"; //------------------------------------------------------------------------ /// /// A subclass should call Kitware.mummy.Runtime.Methods.RegisterType /// from its static constructor. /// static WrappedException() { } //------------------------------------------------------------------------ private System.Runtime.InteropServices.HandleRef CppThis; private bool CallDisposalMethod; //------------------------------------------------------------------------ /// /// Protected constructor. Only called from derived classes. /// protected WrappedException(System.IntPtr rawCppThis, bool callDisposalMethod, bool strong) { this.SetCppThis(rawCppThis, callDisposalMethod, strong); } /// /// Finalizer/destructor. Called automatically by the garbage collector. /// ~WrappedException() { this.Dispose(false); } /// /// Get the HandleRef that links the C++ 'this' pointer of the /// underlying unmanaged object to 'this'. /// public System.Runtime.InteropServices.HandleRef GetCppThis() { return this.CppThis; } /// /// Set the C++ 'this' pointer of the underlying unmanaged object. DO NOT /// CALL THIS METHOD DIRECTLY. This method is called automatically as /// needed by generated code. /// protected void SetCppThis(System.IntPtr rawCppThis, bool callDisposalMethod, bool strong) { this.CppThis = new System.Runtime.InteropServices.HandleRef(this, rawCppThis); this.CallDisposalMethod = callDisposalMethod; if (rawCppThis != System.IntPtr.Zero) { Kitware.mummy.Runtime.Methods.AddTableReference(rawCppThis, this, strong); } } /// /// Clear the C++ 'this' pointer of the underlying unmanaged object. DO /// NOT CALL THIS METHOD DIRECTLY. This method is called automatically as /// needed by generated code. /// protected void ClearCppThis() { if (this.CppThis.Handle != System.IntPtr.Zero) { Kitware.mummy.Runtime.Methods.RemoveTableReference(this.CppThis.Handle); } this.CppThis = new System.Runtime.InteropServices.HandleRef(); this.CallDisposalMethod = false; } /// /// Returns true if this instance of WrappedException is responsible for /// calling an unmanaged disposal method when it is being disposed of. /// DO NOT CALL THIS METHOD DIRECTLY. This method is called automatically /// as needed by generated code. /// protected bool GetCallDisposalMethod() { return this.CallDisposalMethod; } //------------------------------------------------------------------------ /// /// Public implementation of IDisposable. You can call this method prior /// to a WrappedException going out of scope (and prior to the garbage /// collector processing it) to force an early disconnection from the /// underlying unmanaged object. After calling this method, any attempt /// to cross the boundary to unmanaged code will likely result in an /// exception. If you do call this method, it should be the last thing /// you do with a WrappedException... /// public void Dispose() { this.Dispose(true); System.GC.SuppressFinalize(this); } /// /// Generated subclasses override this method to call a disposal method /// in the unmanaged code. /// protected virtual void Dispose(bool disposing) { } } } mummy-1.0.3/Runtime/WrappedObject.cs0000644000175000017500000001140012120621217017222 0ustar mathieumathieu//---------------------------------------------------------------------------- // // $Id: WrappedObject.cs 2 2007-12-17 18:15:56Z david.cole $ // // $Author: david.cole $ // $Date: 2007-12-17 13:15:56 -0500 (Mon, 17 Dec 2007) $ // $Revision: 2 $ // // Copyright (C) 2007 Kitware, Inc. // //---------------------------------------------------------------------------- namespace Kitware.mummy.Runtime { /// /// Base class for mummy-generated C# classes. /// public class WrappedObject : System.IDisposable { //------------------------------------------------------------------------ /// /// MRClassNameKey should be the value that is returned by the C++ RTTI /// function typeid(*obj).name() for an unmanaged C++ object. /// public static readonly string MRClassNameKey = "no equivalent unmanaged class"; //------------------------------------------------------------------------ /// /// MRFullTypeName should be the same as the fully qualified name of this /// C# class... /// public const string MRFullTypeName = "Kitware.mummy.Runtime.WrappedObject"; //------------------------------------------------------------------------ /// /// A subclass should call Kitware.mummy.Runtime.Methods.RegisterType /// from its static constructor. /// static WrappedObject() { } //------------------------------------------------------------------------ private System.Runtime.InteropServices.HandleRef CppThis; private bool CallDisposalMethod; //------------------------------------------------------------------------ /// /// Protected constructor. Only called from derived classes. /// protected WrappedObject(System.IntPtr rawCppThis, bool callDisposalMethod, bool strong) { this.SetCppThis(rawCppThis, callDisposalMethod, strong); } /// /// Finalizer/destructor. Called automatically by the garbage collector. /// ~WrappedObject() { this.Dispose(false); } /// /// Get the HandleRef that links the C++ 'this' pointer of the /// underlying unmanaged object to 'this'. /// public System.Runtime.InteropServices.HandleRef GetCppThis() { return this.CppThis; } /// /// Set the C++ 'this' pointer of the underlying unmanaged object. DO NOT /// CALL THIS METHOD DIRECTLY. This method is called automatically as /// needed by generated code. /// protected void SetCppThis(System.IntPtr rawCppThis, bool callDisposalMethod, bool strong) { this.CppThis = new System.Runtime.InteropServices.HandleRef(this, rawCppThis); this.CallDisposalMethod = callDisposalMethod; if (rawCppThis != System.IntPtr.Zero) { Kitware.mummy.Runtime.Methods.AddTableReference(rawCppThis, this, strong); } } /// /// Clear the C++ 'this' pointer of the underlying unmanaged object. DO /// NOT CALL THIS METHOD DIRECTLY. This method is called automatically as /// needed by generated code. /// protected void ClearCppThis() { if (this.CppThis.Handle != System.IntPtr.Zero) { Kitware.mummy.Runtime.Methods.RemoveTableReference(this.CppThis.Handle); } this.CppThis = new System.Runtime.InteropServices.HandleRef(); this.CallDisposalMethod = false; } /// /// Returns true if this instance of WrappedObject responsible for /// calling an unmanaged disposal method when it is being disposed of. /// DO NOT CALL THIS METHOD DIRECTLY. This method is called automatically /// as needed by generated code. /// protected bool GetCallDisposalMethod() { return this.CallDisposalMethod; } //------------------------------------------------------------------------ /// /// Public implementation of IDisposable. You can call this method prior /// to a WrappedObject going out of scope (and prior to the garbage /// collector processing it) to force an early disconnection from the /// underlying unmanaged object. After calling this method, any attempt /// to cross the boundary to unmanaged code will likely result in an /// exception. If you do call this method, it should be the last thing /// you do with a WrappedObject... /// public void Dispose() { this.Dispose(true); System.GC.SuppressFinalize(this); } /// /// Generated subclasses override this method to call a disposal method /// in the unmanaged code. /// protected virtual void Dispose(bool disposing) { } } } mummy-1.0.3/Runtime/WrappedObject.cs.in0000644000175000017500000001203012120621217017627 0ustar mathieumathieu//---------------------------------------------------------------------------- // // This file is hand-written and configured into the build using CMake. // // Input to configure step is: // "@CMAKE_CURRENT_SOURCE_DIR@/WrappedObject.cs.in" // // WrappedObject is the hand-crafted base class for all mummy-generated C# // classes. mummy-generated classes should *all* derive from WrappedObject // *or* be strictly Value objects (C# structs)... // //---------------------------------------------------------------------------- using System; using System.Runtime.InteropServices; // DllImport and HandleRef both live here //---------------------------------------------------------------------------- namespace mummy { /// /// Hand-crafted base class for mummy-generated C# classes. /// public class WrappedObject : IDisposable { //------------------------------------------------------------------------ // For each _cable_::group listed in any gccxml input file (the .cxx.in // files that get configured and then sent through gccxml) there needs to // be a const string variable here that names the export-layer dll from // which a class's export layer functions are exported... // // For example, for a group = "vtkCommon" there needs to be a variable // named @CMAKE_SHARED_LIBRARY_PREFIX@vtkCommonEL_dll and its value needs to be the actual name of the // dll file that it represents... (which is either @CMAKE_SHARED_LIBRARY_PREFIX@vtkEL@CMAKE_SHARED_LIBRARY_SUFFIX@ or // @CMAKE_SHARED_LIBRARY_PREFIX@vtkCommonEL@CMAKE_SHARED_LIBRARY_SUFFIX@ depending on if you build one big export layer dll or // one for each kit...) //------------------------------------------------------------------------ //------------------------------------------------------------------------ /// /// Export layer functions for 'Runtime' are exported from /// the DLL named by the value of this variable. /// protected const string RuntimeEL_dll = "@CMAKE_SHARED_LIBRARY_PREFIX@Kitware.mummy.Runtime.Unmanaged@CMAKE_SHARED_LIBRARY_SUFFIX@"; //------------------------------------------------------------------------ private HandleRef CppThis; private bool CallDisposalMethod; //------------------------------------------------------------------------ /// /// Protected constructor. Only called from derived classes. /// protected WrappedObject(IntPtr rawCppThis, bool callDisposalMethod) { this.CppThis = new HandleRef(this, rawCppThis); this.CallDisposalMethod = callDisposalMethod; } /// /// Finalizer/destructor. Called automatically by the garbage collector. /// ~WrappedObject() { this.Dispose(false); } /// /// Get the HandleRef that links the C++ 'this' pointer of the /// underlying unmanaged object to 'this'. /// public HandleRef GetCppThis() { return this.CppThis; } /// /// Set the C++ 'this' pointer of the underlying unmanaged object. DO NOT /// CALL THIS METHOD DIRECTLY. This method is called automatically as /// needed by generated code. /// protected void SetCppThis(IntPtr rawCppThis, bool callDisposalMethod) { this.CppThis = new HandleRef(this, rawCppThis); this.CallDisposalMethod = callDisposalMethod; } /// /// Clear the C++ 'this' pointer of the underlying unmanaged object. DO /// NOT CALL THIS METHOD DIRECTLY. This method is called automatically as /// needed by generated code. /// protected void ClearCppThis() { this.CppThis = new HandleRef(); this.CallDisposalMethod = false; } /// /// Returns true if this instance of WrappedObject responsible for /// calling an unmanaged disposal method when it is being disposed of. /// DO NOT CALL THIS METHOD DIRECTLY. This method is called automatically /// as needed by generated code. /// protected bool GetCallDisposalMethod() { return this.CallDisposalMethod; } //------------------------------------------------------------------------ /// /// Public implementation of IDisposable. You can call this method prior /// to a WrappedObject going out of scope (and prior to the garbage /// collector processing it) to force an early disconnection from the /// underlying unmanaged object. After calling this method, any attempt /// to cross the boundary to unmanaged code will likely result in an /// exception. If you do call this method, it should be the last thing /// you do with a WrappedObject... /// public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } /// /// Generated subclasses override this method to call a disposal method /// in the unmanaged code. /// protected virtual void Dispose(bool disposing) { } } } mummy-1.0.3/Runtime/gccxml.cxx.in0000644000175000017500000000053412120621217016556 0ustar mathieumathieu#include "@wcfc_Header@" #ifdef CABLE_CONFIGURATION namespace _cable_ { const char* const package = "mummy.Runtime"; const char* const package_version = "@Mummy_VERSION_MAJOR@.@Mummy_VERSION_MINOR@.@Mummy_VERSION_PATCH@"; const char* const group = "Runtime"; namespace wrappers { typedef @wcfc_Class@ @wcfc_ClassName@; } } #endif mummy-1.0.3/SvnMacros.cmake0000644000175000017500000000432512120621217015444 0ustar mathieumathieuMACRO(SVN_IGNORE si_workingdir si_ignore) FIND_PROGRAM(svn_EXECUTABLE svn "C:/Program Files/Subversion/bin" "C:/Program Files (x86)/Subversion/bin" "C:/cygwin/bin" "/usr/bin" "/usr/local/bin" ) IF(NOT svn_EXECUTABLE) MESSAGE(FATAL_ERROR "ERROR: svn is required to use the SVN_IGNORE CMake macro.") ENDIF(NOT svn_EXECUTABLE) MARK_AS_ADVANCED(svn_EXECUTABLE) EXECUTE_PROCESS( COMMAND "${svn_EXECUTABLE}" "propset" "svn:ignore" "${si_ignore}" "." WORKING_DIRECTORY "${si_workingdir}" RESULT_VARIABLE si_svn_rv ) IF(NOT "${si_svn_rv}" STREQUAL "0") MESSAGE(SEND_ERROR "ERROR: svn propset command returned '${si_svn_rv}'") ENDIF(NOT "${si_svn_rv}" STREQUAL "0") ENDMACRO(SVN_IGNORE) MACRO(SVN_INFO si_workingdir si_svn_info_var) FIND_PROGRAM(svn_EXECUTABLE svn "C:/Program Files/Subversion/bin" "C:/Program Files (x86)/Subversion/bin" "C:/cygwin/bin" "/usr/bin" "/usr/local/bin" ) IF(NOT svn_EXECUTABLE) MESSAGE(FATAL_ERROR "ERROR: svn is required to use the SVN_INFO CMake macro.") ENDIF(NOT svn_EXECUTABLE) MARK_AS_ADVANCED(svn_EXECUTABLE) EXECUTE_PROCESS( COMMAND "${svn_EXECUTABLE}" "info" WORKING_DIRECTORY "${si_workingdir}" OUTPUT_VARIABLE ${si_svn_info_var} RESULT_VARIABLE si_svn_rv ) IF(NOT "${si_svn_rv}" STREQUAL "0") MESSAGE(SEND_ERROR "ERROR: svn info command returned '${si_svn_rv}'") ENDIF(NOT "${si_svn_rv}" STREQUAL "0") ENDMACRO(SVN_INFO) MACRO(SVN_STATUS si_workingdir si_svn_status_var) FIND_PROGRAM(svn_EXECUTABLE svn "C:/Program Files/Subversion/bin" "C:/Program Files (x86)/Subversion/bin" "C:/cygwin/bin" "/usr/bin" "/usr/local/bin" ) IF(NOT svn_EXECUTABLE) MESSAGE(FATAL_ERROR "ERROR: svn is required to use the SVN_STATUS CMake macro.") ENDIF(NOT svn_EXECUTABLE) MARK_AS_ADVANCED(svn_EXECUTABLE) EXECUTE_PROCESS( COMMAND "${svn_EXECUTABLE}" "status" WORKING_DIRECTORY "${si_workingdir}" OUTPUT_VARIABLE ${si_svn_status_var} RESULT_VARIABLE si_svn_rv ) IF(NOT "${si_svn_rv}" STREQUAL "0") MESSAGE(SEND_ERROR "ERROR: svn status command returned '${si_svn_rv}'") ENDIF(NOT "${si_svn_rv}" STREQUAL "0") ENDMACRO(SVN_STATUS)