pax_global_header00006660000000000000000000000064146675206350014530gustar00rootroot0000000000000052 comment=7a5deb54ee165aa157e33937420c933d0c2c41c6 diegoferigo-cmake-build-extension-7a5deb5/000077500000000000000000000000001466752063500206765ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/.github/000077500000000000000000000000001466752063500222365ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/.github/workflows/000077500000000000000000000000001466752063500242735ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/.github/workflows/python.yml000066400000000000000000000057051466752063500263460ustar00rootroot00000000000000name: Python CI/CD on: push: pull_request: release: types: - published jobs: build-and-test: name: 'Python${{ matrix.python-version }}@${{ matrix.os }}' runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: python-version: - 3.8 - 3.9 - "3.10" - "3.11" - "3.12" os: - ubuntu-20.04 - macos-latest - windows-latest include: - optional: false steps: - uses: actions/checkout@master - run: git fetch --prune --unshallow - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install cmake-build-extensions run: pip install wheel && pip install -v .[all] - name: Example dependencies [Windows] if: contains(matrix.os, 'windows') shell: bash run: | choco install -y swig vcpkg install --triplet x64-windows eigen3 - name: Example dependencies [macOS] if: contains(matrix.os, 'macOS') run: | brew install swig eigen # https://cibuildwheel.readthedocs.io/en/stable/cpp_standards echo "MACOSX_DEPLOYMENT_TARGET=10.14" >> $GITHUB_ENV - name: Example dependencies [Ubuntu] if: contains(matrix.os, 'ubuntu') run: | sudo apt update sudo apt install build-essential swig libeigen3-dev - name: Build and install example continue-on-error: ${{ matrix.optional }} working-directory: example run: pip install -v .[all] env: # Pretend to be using cibuildwheel CIBUILDWHEEL: 1 - name: Test example continue-on-error: ${{ matrix.optional }} working-directory: example run: pytest publish: name: Publish to PyPI needs: build-and-test runs-on: ubuntu-20.04 steps: - uses: actions/checkout@master - run: git fetch --prune --unshallow - name: Set up Python uses: actions/setup-python@v2 with: python-version: 3.8 - name: Install Python tools run: pip install build - name: Create distributions run: python -m build -o dist/ - name: Inspect dist folder run: ls -lah dist/ - name: Check wheel run: test $(find dist/ -name *-none-any.whl | wc -l) -gt 0 - name: Upload artifacts uses: actions/upload-artifact@v2 with: path: dist/* name: dist - name: Publish to PyPI if: | github.repository == 'diegoferigo/cmake-build-extension' && ((github.event_name == 'push' && github.ref == 'refs/heads/master') || (github.event_name == 'release')) uses: pypa/gh-action-pypi-publish@master with: user: __token__ password: ${{ secrets.PYPI_TOKEN }} skip_existing: true diegoferigo-cmake-build-extension-7a5deb5/.gitignore000066400000000000000000000034651466752063500226760ustar00rootroot00000000000000.idea *.swp *.old *.bak CMakeLists.txt.user* # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ diegoferigo-cmake-build-extension-7a5deb5/LICENSE000066400000000000000000000020551466752063500217050ustar00rootroot00000000000000MIT License Copyright (c) 2020 Diego Ferigo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diegoferigo-cmake-build-extension-7a5deb5/README.md000066400000000000000000000231541466752063500221620ustar00rootroot00000000000000# cmake-build-extension [![Version](https://img.shields.io/pypi/v/cmake-build-extension.svg)][pypi] [![Python versions](https://img.shields.io/pypi/pyversions/cmake-build-extension.svg)][pypi] [![Status](https://img.shields.io/pypi/status/cmake-build-extension.svg)][pypi] [![Format](https://img.shields.io/pypi/format/cmake-build-extension.svg)][pypi] [![License](https://img.shields.io/pypi/l/cmake-build-extension.svg)][pypi] [![Python CI/CD](https://github.com/diegoferigo/cmake-build-extension/workflows/Python%20CI/CD/badge.svg)][ci_cd] [pypi]: https://pypi.org/project/cmake-build-extension/ [ci_cd]: https://github.com/diegoferigo/cmake-build-extension/actions/workflows/python.yml **Setuptools extension to build and package CMake projects.** This project aims to simplify the integration of C++ projects based on CMake with Python packaging tools. CMake provides out-of-the-box support to either [SWIG][swig] and [pybind11][pybind11], that are two among the most used projects to create Python bindings from C++ sources. [swig]: https://github.com/swig/swig [pybind11]: https://github.com/pybind/pybind11 If you have any experience with these hybrid projects, you know the challenges to make packaging right! This project takes inspiration from pre-existing examples ([`pybind/cmake_example`][pybind11_example], among many others) and provides a simple, flexible, and reusable setuptools extension with the following features: - Bridge between CMake projects and Python packaging. - Configure and build the CMake project from `setup.py`. - Install the CMake project in the resulting Python package. - Allow passing custom CMake options. - Allow creating a top-level `__init__.py`. - Expose C++ executables to the Python environment. - Provide a context manager to import reliably CPython modules on all major OSs. - Disable the C++ extension in editable installations (requiring to manually call CMake to install the C++ project). [pybind11_example]: https://github.com/pybind/cmake_example Have a look to the [example](example/) for an overview of what can be done with this extension. It shows how to create SWIG and pybind11 bindings for a project composed by a small C++ library with NumPy support and an executable. ### Advanced features 1. This extension supports creating packages [PEP517] and [PEP518] compliant ([more details][pyproject]). 2. If the CMake project [exports the targets][export_targets], downstream projects can: 1. Extend their `CMAKE_MODULE_PATH` with the root of your installed Python package, that could be obtained with: ```bash python -c "import , pathlib; print(pathlib.Path(.__file__).parent)" ``` and consume the exported CMake targets. 1. Use `cmake-build-extension` with the `cmake_depends_on` option and link against the exported CMake targets during the downstream packaging. Note that the second feature allows distributing C++ dependencies through PyPI. The resulting package structure is similar to other projects like [pybind11][pybind11_pypi] and [CasADi][casadi_pypi]. Be aware that ensuring ABI compatibility could be problematic in edge cases, and the usage of a proper [compatible release pattern][pep440] (`~=`) could be necessary. [pep440]: https://www.python.org/dev/peps/pep-0440/#compatible-release [pep517]: https://www.python.org/dev/peps/pep-0517/ [pep518]: https://www.python.org/dev/peps/pep-0518/ [pyproject]: https://snarky.ca/what-the-heck-is-pyproject-toml/ [export_targets]: https://cmake.org/cmake/help/git-stage/guide/importing-exporting/index.html [pybind11_pypi]: https://pypi.org/project/pybind11/ [casadi_pypi]: https://pypi.org/project/casadi/ ## Installation From PyPI: ```bash pip install cmake-build-extension ``` From the repository: ```bash pip install git+https://github.com/diegoferigo/cmake-build-extension ``` ## Usage Once both CMake project and `setup.py|setup.cfg|pyproject.toml` of your hybrid package are correctly configured to use the resources provided by cmake-build-extension, the following commands can be used: ```bash # ============ # Create sdist # ============ # Calling setup.py python setup.py sdist # Using pypa/build python -m build --sdist # ============ # Create wheel # ============ # Calling setup.py python setup.py bdist_wheel # Using pip pip wheel -w dist/ . # Using pypa/build python -m build --wheel # ========================================================== # Create wheel or install package passing additional options # ========================================================== # Calling setup.py python setup.py {bdist_wheel|install} build_ext -D"BAR=Foo;VAR=TRUE" # Using pip pip {wheel|install} --global-option="build_ext" --global-option="-DBAR=Foo;VAR=TRUE" . # Using pypa/build (only wheel creation) python -m build --wheel "-C--global-option=build_ext" "-C--global-option=-DBAR=Foo;VAR=TRUE" ``` ## Caveats ### `manylinux*` support This extension, beyond packaging the hybrid C++ / Python project, also allows the inclusion of the exported CMake targets in the resulting wheel. This result depends on how the CMake project is configured, and whether the [exported targets][exp_imp_wiki] are installed together with the other files. [exp_imp_wiki]: https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/Exporting-and-Importing-Targets Such hybrid packages can then be uploaded to PyPI. Though, on GNU/Linux, the generated wheel is not compliant by default with any [`manylinux*`][manylinux] standard. Tools such [auditwheel][auditwheel] exist to fix these wheels, but they require running on selected distributions. Luckily, other projects like [cibuildwheel][cibuildwheel] greatly simplify the process in CI. [manylinux]: https://github.com/pypa/manylinux [auditwheel]: https://github.com/pypa/auditwheel [cibuildwheel]: https://github.com/joerick/cibuildwheel This being said, `manylinux*` guidelines could still work against you. In fact, wheels supporting `manylinux2010|manylinux2014` are built [with gcc4][pep599_manylinux2014] that does not support the new C++11 ABIs. In few words, this means that the exported libraries bundled in the wheel cannot be imported in a downstream project using relatively new C++ standards! For more details visit [robotology/idyntree#776](https://github.com/robotology/idyntree/issues/776). [pep599_manylinux2014]: https://www.python.org/dev/peps/pep-0599/#the-manylinux2014-policy Luckily, the situation changed thanks to the finalization of [PEP600][pep600], i.e. `manylinuxX_YY` :tada: If you build a PEP600 compliant wheel (nowadays compatible with most of the commonly used distributions), your exported CMake project bundled in the wheel can be successfully imported downstream. If you want to support this use case, make sure to produce and distribute wheels compliant with PEP600. [pep600]: https://www.python.org/dev/peps/pep-0600/ ### Loading CPython modules in Windows Python 3.8 [changed][changelog_3_8] how DLL are resolved. By default, modules that could be imported in Python 3.7 stopped working, and using the new [`os.add_dll_directory`][add_dll_directory] is now necessary. In order to streamline the process, `cmake-build-extension` implements a context manager that can be used to import reliably the bindings module: ```python import cmake_build_extension with cmake_build_extension.build_extension_env(): from . import bindings ``` It will take care to temporarily fix the search path. For more details, refer to [#8][windows_import_issue] and [#12][windows_import_pr]. [changelog_3_8]: https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew [add_dll_directory]: https://docs.python.org/3/library/os.html#os.add_dll_directory [windows_import_issue]: https://github.com/diegoferigo/cmake-build-extension/issues/8 [windows_import_pr]: https://github.com/diegoferigo/cmake-build-extension/pull/12 ### `setup.py|setup.cfg|pyproject.toml` files in subfolder Sometimes hybrid projects are C++ centric, and keeping these files in the top-level folder is not desirable. In this setup, however, problems occur if the main `CMakeLists.txt` is kept in the top-level folder (see [pypa/build#322][sdist_issue]). To solve this problem, `cmake-build-extension` provides custom commands to create source distribution. You can use one of the following custom `sdist` options in `setup.py`: ```python setuptools.setup( cmdclass=dict( # [...] # Pack the whole git folder: sdist=cmake_build_extension.GitSdistFolder, # Pack only the git tree: sdist=cmake_build_extension.GitSdistTree, # Or, inherit from cmake_build_extension.sdist_command.GitSdistABC and # make your own custom sdist including only the files you are interested ), ) ``` [sdist_issue]: https://github.com/pypa/build/issues/322 ## Downstream projects If the provided example is not enough complex, find here below a list of projects using `cmake-build-extension`: - [`robotology/idyntree`](https://github.com/robotology/idyntree/) - [`robotology/yarp`](https://github.com/robotology/yarp/) - [`robotology/ycm`](https://github.com/robotology/ycm/) - [`diegoferigo/gazebo-yarp-synchronizer`](https://github.com/diegoferigo/gazebo-yarp-synchronizer) - [`robotology/gym-ignition@scenario`](https://github.com/robotology/gym-ignition/tree/devel/scenario) - [`dic-iit/gazebo-scenario-plugins`](https://github.com/dic-iit/gazebo-scenario-plugins/) - [`dic-iit/bipedal-locomotion-framework`](https://github.com/dic-iit/bipedal-locomotion-framework) - [`artivis/manif`](https://github.com/artivis/manif) ## Contributing Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. ## License [MIT](https://choosealicense.com/licenses/mit/) diegoferigo-cmake-build-extension-7a5deb5/example/000077500000000000000000000000001466752063500223315ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/example/.clang-format000066400000000000000000000060501466752063500247050ustar00rootroot00000000000000--- Language: Cpp # BasedOnStyle: WebKit AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: false AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: true BinPackArguments: false BinPackParameters: false BraceWrapping: AfterClass: true AfterControlStatement: false AfterEnum: true AfterFunction: true AfterNamespace: false AfterObjCDeclaration: false AfterStruct: true AfterUnion: false BeforeCatch: true BeforeElse: true IndentBraces: false SplitEmptyFunction: false SplitEmptyRecord: false SplitEmptyNamespace: false BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Custom BreakBeforeInheritanceComma: true BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: true BreakConstructorInitializers: BeforeComma BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true ColumnLimit: 80 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH IncludeBlocks: Preserve IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 - Regex: '.*' Priority: 1 IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: true IndentWidth: 4 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: true MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: All ObjCBlockIndentWidth: 4 ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true PenaltyBreakAssignment: 2 PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Left ReflowComments: true SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: true SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 TabWidth: 4 UseTab: Never ... diegoferigo-cmake-build-extension-7a5deb5/example/CMakeLists.txt000066400000000000000000000072131466752063500250740ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.18.2) project(MyMath VERSION 1.0) # C++ standard set(CMAKE_CXX_STANDARD 17) set(CMAKE_C_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Common installation directories include(GNUInstallDirs) # Use -fPIC even if statically compiled set(CMAKE_POSITION_INDEPENDENT_CODE ON) # ============ # math library # ============ # Create the mymath library add_library(mymath src/mymath.h src/mymath.cpp) add_library(MyMath::mymath ALIAS mymath) set_target_properties(mymath PROPERTIES PUBLIC_HEADER src/mymath.h) target_include_directories(mymath PUBLIC $ $) # ======================= # print_answer executable # ======================= # Create the print_answer executable add_executable(print_answer src/print_answer.cpp) # ======= # Install # ======= # See official documentation on exporting targets: # https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html#exporting-targets # Install the target with C++ code install( TARGETS mymath print_answer EXPORT MyMathTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) # Install the exported targets install( EXPORT MyMathTargets FILE MyMathTargets.cmake NAMESPACE MyMath:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyMath) # Create a CMake package include(CMakePackageConfigHelpers) # Prepare the Config.cmake.in content set(PACKAGE_INIT_MACRO "@PACKAGE_INIT@") set(CONFIG_CMAKE_IN "\ @PACKAGE_INIT_MACRO@\n\ include(\"\${CMAKE_CURRENT_LIST_DIR}/MyMathTargets.cmake\")\n\ check_required_components(MyMath)\n" ) # Create Config.cmake.in file(CONFIGURE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Config.cmake.in CONTENT ${CONFIG_CMAKE_IN} @ONLY) # Create MyMathConfig.cmake configure_package_config_file( ${CMAKE_CURRENT_BINARY_DIR}/Config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/MyMathConfig.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyMath) # Create MyMathConfigVersion.cmake write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/MyMathConfigVersion.cmake" VERSION "${version}" COMPATIBILITY AnyNewerVersion ) # Install CMake package files install(FILES "${CMAKE_CURRENT_BINARY_DIR}/MyMathConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/MyMathConfigVersion.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyMath ) # =============== # Python bindings # =============== # Find Python3 and NumPy find_package(Python3 COMPONENTS Interpreter Development.Module NumPy REQUIRED) # Handle where to install the resulting Python package if(CALL_FROM_SETUP_PY) # The CMakeExtension will set CMAKE_INSTALL_PREFIX to the root # of the resulting wheel archive set(MYMATH_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) else() # The Python package is installed directly in the folder of the # detected interpreter (system, user, or virtualenv) set(MYMATH_INSTALL_PREFIX ${Python3_SITELIB}) endif() # ============= # SWIG bindings # ============= if(EXAMPLE_WITH_SWIG) # Rename the executable set_target_properties(print_answer PROPERTIES OUTPUT_NAME print_answer_swig) # Add the bindings add_subdirectory(bindings_swig) endif() # ================= # Pybind11 bindings # ================= if(EXAMPLE_WITH_PYBIND11) # Rename the executable set_target_properties(print_answer PROPERTIES OUTPUT_NAME print_answer_pybind11) # Add the bindings add_subdirectory(bindings_pybind11) endif() diegoferigo-cmake-build-extension-7a5deb5/example/README.md000066400000000000000000000000001466752063500235760ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/example/bindings_pybind11/000077500000000000000000000000001466752063500256355ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/example/bindings_pybind11/CMakeLists.txt000066400000000000000000000013611466752063500303760ustar00rootroot00000000000000find_package(pybind11 REQUIRED) find_package(Eigen3 REQUIRED NO_MODULE) # ======= # Library # ======= # Create the pybind11 library pybind11_add_module(pybind11_bindings MODULE bindings.cpp) target_link_libraries(pybind11_bindings PRIVATE MyMath::mymath Eigen3::Eigen) # The name of the shared library must match the module name set_target_properties(pybind11_bindings PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mymath OUTPUT_NAME "bindings") # ======= # Install # ======= # Install the pybind11 library install( TARGETS pybind11_bindings COMPONENT bindings LIBRARY DESTINATION ${MYMATH_INSTALL_PREFIX} ARCHIVE DESTINATION ${MYMATH_INSTALL_PREFIX} RUNTIME DESTINATION ${MYMATH_INSTALL_PREFIX}) diegoferigo-cmake-build-extension-7a5deb5/example/bindings_pybind11/bindings.cpp000066400000000000000000000015701466752063500301410ustar00rootroot00000000000000#include "mymath.h" #include #include #include #include #include // Create the Python module PYBIND11_MODULE(bindings, module) { namespace py = ::pybind11; module.doc() = "mymath bindings"; // These methods accept numpy array but return float / list module.def("dot", &mymath::dot, py::arg("vector1"), py::arg("vector2")); module.def("normalize", &mymath::normalize, py::arg("data")); // In order to return directly a numpy object, we can pass through Eigen module.def( "normalize_numpy", [](const std::vector& data) -> Eigen::VectorXd { const auto output = mymath::normalize(data); return Eigen::Map( const_cast(output.data()), output.size()); }, py::arg("data")); } diegoferigo-cmake-build-extension-7a5deb5/example/bindings_swig/000077500000000000000000000000001466752063500251575ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/example/bindings_swig/CMakeLists.txt000066400000000000000000000031111466752063500277130ustar00rootroot00000000000000# Set SWIG policies cmake_policy(SET CMP0078 NEW) cmake_policy(SET CMP0086 NEW) find_package(SWIG 4.0 REQUIRED) set(UseSWIG_MODULE_VERSION 2) include(${SWIG_USE_FILE}) # ======= # Library # ======= # The name of the shared library must match the module name set_source_files_properties(bindings.i PROPERTIES CPLUSPLUS ON SWIG_MODULE_NAME "bindings") # Create the SWIG library swig_add_library(swig_bindings TYPE MODULE LANGUAGE python OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/mymath OUTFILE_DIR ${CMAKE_CURRENT_BINARY_DIR} SOURCES bindings.i) target_link_libraries(swig_bindings PRIVATE MyMath::mymath Python3::NumPy) set_target_properties(swig_bindings PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mymath) set_property(TARGET swig_bindings PROPERTY SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE) # Enable parsing the doxygen comments set_property(TARGET swig_bindings PROPERTY SWIG_COMPILE_OPTIONS -doxygen) # Add dependency to numpy.i set_property( TARGET swig_bindings PROPERTY SWIG_DEPENDS numpy.i) # ======= # Install # ======= # Get the autogenerated Python file get_property(WRAPPER_PY_FILE TARGET swig_bindings PROPERTY SWIG_SUPPORT_FILES) # Install the autogenerated Python file install( FILES ${WRAPPER_PY_FILE} DESTINATION ${MYMATH_INSTALL_PREFIX} COMPONENT bindings) # Install the SWIG library install( TARGETS swig_bindings COMPONENT bindings LIBRARY DESTINATION ${MYMATH_INSTALL_PREFIX} ARCHIVE DESTINATION ${MYMATH_INSTALL_PREFIX} RUNTIME DESTINATION ${MYMATH_INSTALL_PREFIX}) diegoferigo-cmake-build-extension-7a5deb5/example/bindings_swig/bindings.i000066400000000000000000000037061466752063500271340ustar00rootroot00000000000000// Documentation: https://numpy.org/doc/stable/reference/swig.interface-file.html %module(package="mathlib") mymath %{ #define SWIG_FILE_WITH_INIT #include "mymath.h" %} %naturalvar; // Convert all exceptions to RuntimeError %include "exception.i" %exception { try { $action } catch (const std::exception& e) { SWIG_exception(SWIG_RuntimeError, e.what()); } } // Convert std::vector <-> python containers %include %template(VectorD) std::vector; // Doxygen typemaps %typemap(doctype) std::vector "Iterable[float]"; // Necessary for type hinting %pythonbegin %{ from typing import Iterable %} // Include numpy.i typemaps %include "numpy.i" // Initialize NumPy %init %{ import_array(); %} // Apply the NumPy typemaps to the following signatures %apply (double* IN_ARRAY1, int DIM1) {(double* in_1, unsigned size_in_1)}; %apply (double* IN_ARRAY1, int DIM1) {(double* in_2, unsigned size_in_2)}; %apply (double** ARGOUTVIEWM_ARRAY1, int* DIM1) {(double** out_1, int* size_out_1)}; // Create manually additional functions to allow using directly NumPy types // without the need to alter the original C++ library %inline %{ namespace numpy { double dot_numpy(double* in_1, unsigned size_in_1, double* in_2, unsigned size_in_2) { const std::vector vector1(in_1, in_1 + size_in_1); const std::vector vector2(in_2, in_2 + size_in_2); return mymath::dot(vector1, vector2); } void normalize_numpy(double* in_1, unsigned size_in_1, double** out_1, int* size_out_1) { const std::vector vector(in_1, in_1 + size_in_1); auto result = mymath::normalize(vector); *out_1 = static_cast(malloc(result.size() * sizeof(double))); std::copy(result.begin(), result.end(), *out_1); *size_out_1 = result.size(); } } %} // Include the header with the symbols to wrap %include "mymath.h" diegoferigo-cmake-build-extension-7a5deb5/example/bindings_swig/numpy.i000066400000000000000000003256231466752063500265140ustar00rootroot00000000000000/* -*- C -*- (not really, but good for syntax highlighting) */ /* * Copyright (c) 2005-2015, NumPy Developers. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * * Neither the name of the NumPy Developers nor the names of any * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef SWIGPYTHON %{ #ifndef SWIG_FILE_WITH_INIT #define NO_IMPORT_ARRAY #endif #include "stdio.h" #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include %} /**********************************************************************/ %fragment("NumPy_Backward_Compatibility", "header") { %#if NPY_API_VERSION < 0x00000007 %#define NPY_ARRAY_DEFAULT NPY_DEFAULT %#define NPY_ARRAY_FARRAY NPY_FARRAY %#define NPY_FORTRANORDER NPY_FORTRAN %#endif } /**********************************************************************/ /* The following code originally appeared in * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was * translated from C++ to C by John Hunter. Bill Spotz has modified * it to fix some minor bugs, upgrade from Numeric to numpy (all * versions), add some comments and functionality, and convert from * direct code insertion to SWIG fragments. */ %fragment("NumPy_Macros", "header") { /* Macros to extract array attributes. */ %#if NPY_API_VERSION < 0x00000007 %#define is_array(a) ((a) && PyArray_Check((PyArrayObject*)a)) %#define array_type(a) (int)(PyArray_TYPE((PyArrayObject*)a)) %#define array_numdims(a) (((PyArrayObject*)a)->nd) %#define array_dimensions(a) (((PyArrayObject*)a)->dimensions) %#define array_size(a,i) (((PyArrayObject*)a)->dimensions[i]) %#define array_strides(a) (((PyArrayObject*)a)->strides) %#define array_stride(a,i) (((PyArrayObject*)a)->strides[i]) %#define array_data(a) (((PyArrayObject*)a)->data) %#define array_descr(a) (((PyArrayObject*)a)->descr) %#define array_flags(a) (((PyArrayObject*)a)->flags) %#define array_clearflags(a,f) (((PyArrayObject*)a)->flags) &= ~f %#define array_enableflags(a,f) (((PyArrayObject*)a)->flags) = f %#define array_is_fortran(a) (PyArray_ISFORTRAN((PyArrayObject*)a)) %#else %#define is_array(a) ((a) && PyArray_Check(a)) %#define array_type(a) PyArray_TYPE((PyArrayObject*)a) %#define array_numdims(a) PyArray_NDIM((PyArrayObject*)a) %#define array_dimensions(a) PyArray_DIMS((PyArrayObject*)a) %#define array_strides(a) PyArray_STRIDES((PyArrayObject*)a) %#define array_stride(a,i) PyArray_STRIDE((PyArrayObject*)a,i) %#define array_size(a,i) PyArray_DIM((PyArrayObject*)a,i) %#define array_data(a) PyArray_DATA((PyArrayObject*)a) %#define array_descr(a) PyArray_DESCR((PyArrayObject*)a) %#define array_flags(a) PyArray_FLAGS((PyArrayObject*)a) %#define array_enableflags(a,f) PyArray_ENABLEFLAGS((PyArrayObject*)a,f) %#define array_clearflags(a,f) PyArray_CLEARFLAGS((PyArrayObject*)a,f) %#define array_is_fortran(a) (PyArray_IS_F_CONTIGUOUS((PyArrayObject*)a)) %#endif %#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS((PyArrayObject*)a)) %#define array_is_native(a) (PyArray_ISNOTSWAPPED((PyArrayObject*)a)) } /**********************************************************************/ %fragment("NumPy_Utilities", "header") { /* Given a PyObject, return a string describing its type. */ const char* pytype_string(PyObject* py_obj) { if (py_obj == NULL ) return "C NULL value"; if (py_obj == Py_None ) return "Python None" ; if (PyCallable_Check(py_obj)) return "callable" ; if (PyString_Check( py_obj)) return "string" ; if (PyInt_Check( py_obj)) return "int" ; if (PyFloat_Check( py_obj)) return "float" ; if (PyDict_Check( py_obj)) return "dict" ; if (PyList_Check( py_obj)) return "list" ; if (PyTuple_Check( py_obj)) return "tuple" ; return "unknown type"; } /* Given a NumPy typecode, return a string describing the type. */ const char* typecode_string(int typecode) { static const char* type_names[25] = {"bool", "byte", "unsigned byte", "short", "unsigned short", "int", "unsigned int", "long", "unsigned long", "long long", "unsigned long long", "float", "double", "long double", "complex float", "complex double", "complex long double", "object", "string", "unicode", "void", "ntypes", "notype", "char", "unknown"}; return typecode < 24 ? type_names[typecode] : type_names[24]; } /* Make sure input has correct numpy type. This now just calls PyArray_EquivTypenums(). */ int type_match(int actual_type, int desired_type) { return PyArray_EquivTypenums(actual_type, desired_type); } %#ifdef SWIGPY_USE_CAPSULE void free_cap(PyObject * cap) { void* array = (void*) PyCapsule_GetPointer(cap,SWIGPY_CAPSULE_NAME); if (array != NULL) free(array); } %#endif } /**********************************************************************/ %fragment("NumPy_Object_to_Array", "header", fragment="NumPy_Backward_Compatibility", fragment="NumPy_Macros", fragment="NumPy_Utilities") { /* Given a PyObject pointer, cast it to a PyArrayObject pointer if * legal. If not, set the python error string appropriately and * return NULL. */ PyArrayObject* obj_to_array_no_conversion(PyObject* input, int typecode) { PyArrayObject* ary = NULL; if (is_array(input) && (typecode == NPY_NOTYPE || PyArray_EquivTypenums(array_type(input), typecode))) { ary = (PyArrayObject*) input; } else if is_array(input) { const char* desired_type = typecode_string(typecode); const char* actual_type = typecode_string(array_type(input)); PyErr_Format(PyExc_TypeError, "Array of type '%s' required. Array of type '%s' given", desired_type, actual_type); ary = NULL; } else { const char* desired_type = typecode_string(typecode); const char* actual_type = pytype_string(input); PyErr_Format(PyExc_TypeError, "Array of type '%s' required. A '%s' was given", desired_type, actual_type); ary = NULL; } return ary; } /* Convert the given PyObject to a NumPy array with the given * typecode. On success, return a valid PyArrayObject* with the * correct type. On failure, the python error string will be set and * the routine returns NULL. */ PyArrayObject* obj_to_array_allow_conversion(PyObject* input, int typecode, int* is_new_object) { PyArrayObject* ary = NULL; PyObject* py_obj; if (is_array(input) && (typecode == NPY_NOTYPE || PyArray_EquivTypenums(array_type(input),typecode))) { ary = (PyArrayObject*) input; *is_new_object = 0; } else { py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_ARRAY_DEFAULT); /* If NULL, PyArray_FromObject will have set python error value.*/ ary = (PyArrayObject*) py_obj; *is_new_object = 1; } return ary; } /* Given a PyArrayObject, check to see if it is contiguous. If so, * return the input pointer and flag it as not a new object. If it is * not contiguous, create a new PyArrayObject using the original data, * flag it as a new object and return the pointer. */ PyArrayObject* make_contiguous(PyArrayObject* ary, int* is_new_object, int min_dims, int max_dims) { PyArrayObject* result; if (array_is_contiguous(ary)) { result = ary; *is_new_object = 0; } else { result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, array_type(ary), min_dims, max_dims); *is_new_object = 1; } return result; } /* Given a PyArrayObject, check to see if it is Fortran-contiguous. * If so, return the input pointer, but do not flag it as not a new * object. If it is not Fortran-contiguous, create a new * PyArrayObject using the original data, flag it as a new object * and return the pointer. */ PyArrayObject* make_fortran(PyArrayObject* ary, int* is_new_object) { PyArrayObject* result; if (array_is_fortran(ary)) { result = ary; *is_new_object = 0; } else { Py_INCREF(array_descr(ary)); result = (PyArrayObject*) PyArray_FromArray(ary, array_descr(ary), %#if NPY_API_VERSION < 0x00000007 NPY_FORTRANORDER); %#else NPY_ARRAY_F_CONTIGUOUS); %#endif *is_new_object = 1; } return result; } /* Convert a given PyObject to a contiguous PyArrayObject of the * specified type. If the input object is not a contiguous * PyArrayObject, a new one will be created and the new object flag * will be set. */ PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, int typecode, int* is_new_object) { int is_new1 = 0; int is_new2 = 0; PyArrayObject* ary2; PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode, &is_new1); if (ary1) { ary2 = make_contiguous(ary1, &is_new2, 0, 0); if ( is_new1 && is_new2) { Py_DECREF(ary1); } ary1 = ary2; } *is_new_object = is_new1 || is_new2; return ary1; } /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the * specified type. If the input object is not a Fortran-ordered * PyArrayObject, a new one will be created and the new object flag * will be set. */ PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input, int typecode, int* is_new_object) { int is_new1 = 0; int is_new2 = 0; PyArrayObject* ary2; PyArrayObject* ary1 = obj_to_array_allow_conversion(input, typecode, &is_new1); if (ary1) { ary2 = make_fortran(ary1, &is_new2); if (is_new1 && is_new2) { Py_DECREF(ary1); } ary1 = ary2; } *is_new_object = is_new1 || is_new2; return ary1; } } /* end fragment */ /**********************************************************************/ %fragment("NumPy_Array_Requirements", "header", fragment="NumPy_Backward_Compatibility", fragment="NumPy_Macros") { /* Test whether a python object is contiguous. If array is * contiguous, return 1. Otherwise, set the python error string and * return 0. */ int require_contiguous(PyArrayObject* ary) { int contiguous = 1; if (!array_is_contiguous(ary)) { PyErr_SetString(PyExc_TypeError, "Array must be contiguous. A non-contiguous array was given"); contiguous = 0; } return contiguous; } /* Test whether a python object is (C_ or F_) contiguous. If array is * contiguous, return 1. Otherwise, set the python error string and * return 0. */ int require_c_or_f_contiguous(PyArrayObject* ary) { int contiguous = 1; if (!(array_is_contiguous(ary) || array_is_fortran(ary))) { PyErr_SetString(PyExc_TypeError, "Array must be contiguous (C_ or F_). A non-contiguous array was given"); contiguous = 0; } return contiguous; } /* Require that a numpy array is not byte-swapped. If the array is * not byte-swapped, return 1. Otherwise, set the python error string * and return 0. */ int require_native(PyArrayObject* ary) { int native = 1; if (!array_is_native(ary)) { PyErr_SetString(PyExc_TypeError, "Array must have native byteorder. " "A byte-swapped array was given"); native = 0; } return native; } /* Require the given PyArrayObject to have a specified number of * dimensions. If the array has the specified number of dimensions, * return 1. Otherwise, set the python error string and return 0. */ int require_dimensions(PyArrayObject* ary, int exact_dimensions) { int success = 1; if (array_numdims(ary) != exact_dimensions) { PyErr_Format(PyExc_TypeError, "Array must have %d dimensions. Given array has %d dimensions", exact_dimensions, array_numdims(ary)); success = 0; } return success; } /* Require the given PyArrayObject to have one of a list of specified * number of dimensions. If the array has one of the specified number * of dimensions, return 1. Otherwise, set the python error string * and return 0. */ int require_dimensions_n(PyArrayObject* ary, int* exact_dimensions, int n) { int success = 0; int i; char dims_str[255] = ""; char s[255]; for (i = 0; i < n && !success; i++) { if (array_numdims(ary) == exact_dimensions[i]) { success = 1; } } if (!success) { for (i = 0; i < n-1; i++) { sprintf(s, "%d, ", exact_dimensions[i]); strcat(dims_str,s); } sprintf(s, " or %d", exact_dimensions[n-1]); strcat(dims_str,s); PyErr_Format(PyExc_TypeError, "Array must have %s dimensions. Given array has %d dimensions", dims_str, array_numdims(ary)); } return success; } /* Require the given PyArrayObject to have a specified shape. If the * array has the specified shape, return 1. Otherwise, set the python * error string and return 0. */ int require_size(PyArrayObject* ary, npy_intp* size, int n) { int i; int success = 1; size_t len; char desired_dims[255] = "["; char s[255]; char actual_dims[255] = "["; for(i=0; i < n;i++) { if (size[i] != -1 && size[i] != array_size(ary,i)) { success = 0; } } if (!success) { for (i = 0; i < n; i++) { if (size[i] == -1) { sprintf(s, "*,"); } else { sprintf(s, "%ld,", (long int)size[i]); } strcat(desired_dims,s); } len = strlen(desired_dims); desired_dims[len-1] = ']'; for (i = 0; i < n; i++) { sprintf(s, "%ld,", (long int)array_size(ary,i)); strcat(actual_dims,s); } len = strlen(actual_dims); actual_dims[len-1] = ']'; PyErr_Format(PyExc_TypeError, "Array must have shape of %s. Given array has shape of %s", desired_dims, actual_dims); } return success; } /* Require the given PyArrayObject to to be Fortran ordered. If the * the PyArrayObject is already Fortran ordered, do nothing. Else, * set the Fortran ordering flag and recompute the strides. */ int require_fortran(PyArrayObject* ary) { int success = 1; int nd = array_numdims(ary); int i; npy_intp * strides = array_strides(ary); if (array_is_fortran(ary)) return success; int n_non_one = 0; /* Set the Fortran ordered flag */ const npy_intp *dims = array_dimensions(ary); for (i=0; i < nd; ++i) n_non_one += (dims[i] != 1) ? 1 : 0; if (n_non_one > 1) array_clearflags(ary,NPY_ARRAY_CARRAY); array_enableflags(ary,NPY_ARRAY_FARRAY); /* Recompute the strides */ strides[0] = strides[nd-1]; for (i=1; i < nd; ++i) strides[i] = strides[i-1] * array_size(ary,i-1); return success; } } /* Combine all NumPy fragments into one for convenience */ %fragment("NumPy_Fragments", "header", fragment="NumPy_Backward_Compatibility", fragment="NumPy_Macros", fragment="NumPy_Utilities", fragment="NumPy_Object_to_Array", fragment="NumPy_Array_Requirements") { } /* End John Hunter translation (with modifications by Bill Spotz) */ /* %numpy_typemaps() macro * * This macro defines a family of 75 typemaps that allow C arguments * of the form * * 1. (DATA_TYPE IN_ARRAY1[ANY]) * 2. (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) * 3. (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) * * 4. (DATA_TYPE IN_ARRAY2[ANY][ANY]) * 5. (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) * 6. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) * 7. (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) * 8. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) * * 9. (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) * 10. (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 11. (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 12. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) * 13. (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 14. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) * * 15. (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) * 16. (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 17. (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 18. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) * 19. (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 20. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) * * 21. (DATA_TYPE INPLACE_ARRAY1[ANY]) * 22. (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) * 23. (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) * * 24. (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) * 25. (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) * 26. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) * 27. (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) * 28. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) * * 29. (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) * 30. (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 31. (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 32. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) * 33. (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) * 34. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) * * 35. (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) * 36. (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 37. (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 38. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) * 39. (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) * 40. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) * * 41. (DATA_TYPE ARGOUT_ARRAY1[ANY]) * 42. (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) * 43. (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) * * 44. (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) * * 45. (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) * * 46. (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) * * 47. (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) * 48. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) * * 49. (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) * 50. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) * 51. (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) * 52. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) * * 53. (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) * 54. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) * 55. (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) * 56. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) * * 57. (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) * 58. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) * 59. (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) * 60. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) * * 61. (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) * 62. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) * * 63. (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) * 64. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) * 65. (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) * 66. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) * * 67. (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) * 68. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) * 69. (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) * 70. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) * * 71. (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) * 72. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) * 73. (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) * 74. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) * * 75. (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) * * where "DATA_TYPE" is any type supported by the NumPy module, and * "DIM_TYPE" is any int-like type suitable for specifying dimensions. * The difference between "ARRAY" typemaps and "FARRAY" typemaps is * that the "FARRAY" typemaps expect Fortran ordering of * multidimensional arrays. In python, the dimensions will not need * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1" * typemaps). The IN_ARRAYs can be a numpy array or any sequence that * can be converted to a numpy array of the specified type. The * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The * ARGOUT_ARRAYs will be returned as new numpy arrays of the * appropriate type. * * These typemaps can be applied to existing functions using the * %apply directive. For example: * * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)}; * double prod(double* series, int length); * * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) * {(int rows, int cols, double* matrix )}; * void floor(int rows, int cols, double* matrix, double f); * * %apply (double IN_ARRAY3[ANY][ANY][ANY]) * {(double tensor[2][2][2] )}; * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) * {(double low[2][2][2] )}; * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) * {(double upp[2][2][2] )}; * void luSplit(double tensor[2][2][2], * double low[2][2][2], * double upp[2][2][2] ); * * or directly with * * double prod(double* IN_ARRAY1, int DIM1); * * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f); * * void luSplit(double IN_ARRAY3[ANY][ANY][ANY], * double ARGOUT_ARRAY3[ANY][ANY][ANY], * double ARGOUT_ARRAY3[ANY][ANY][ANY]); */ %define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) /************************/ /* Input Array Typemaps */ /************************/ /* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE IN_ARRAY1[ANY]) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE IN_ARRAY1[ANY]) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[1] = { $1_dim0 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(freearg) (DATA_TYPE IN_ARRAY1[ANY]) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[1] = { -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); } %typemap(freearg) (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[1] = {-1}; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 1) || !require_size(array, size, 1)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE IN_ARRAY2[ANY][ANY]) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE IN_ARRAY2[ANY][ANY]) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { $1_dim0, $1_dim1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2)) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(freearg) (DATA_TYPE IN_ARRAY2[ANY][ANY]) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); } %typemap(freearg) (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); } %typemap(freearg) (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[2] = { -1, -1 }; array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 2) || !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3)) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(freearg) (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); } %typemap(freearg) (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { /* for now, only concerned with lists */ $1 = PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) { npy_intp size[2] = { -1, -1 }; PyArrayObject* temp_array; Py_ssize_t i; int is_new_object; /* length of the list */ $2 = PyList_Size($input); /* the arrays */ array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); is_new_object_array = (int *)calloc($2,sizeof(int)); if (array == NULL || object_array == NULL || is_new_object_array == NULL) { SWIG_fail; } for (i=0; i<$2; i++) { temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); /* the new array must be stored so that it can be destroyed in freearg */ object_array[i] = temp_array; is_new_object_array[i] = is_new_object; if (!temp_array || !require_dimensions(temp_array, 2)) SWIG_fail; /* store the size of the first array in the list, then use that for comparison. */ if (i == 0) { size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); } if (!require_size(temp_array, size, 2)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); } $1 = (DATA_TYPE**) array; $3 = (DIM_TYPE) size[0]; $4 = (DIM_TYPE) size[1]; } %typemap(freearg) (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { Py_ssize_t i; if (array$argnum!=NULL) free(array$argnum); /*freeing the individual arrays if needed */ if (object_array$argnum!=NULL) { if (is_new_object_array$argnum!=NULL) { for (i=0; i<$2; i++) { if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) { Py_DECREF(object_array$argnum[i]); } } free(is_new_object_array$argnum); } free(object_array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* IN_ARRAY3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); } %typemap(freearg) (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* IN_FARRAY3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[3] = { -1, -1, -1 }; array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 3) || !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3}; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4)) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(freearg) (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { -1, -1, -1, -1 }; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); $5 = (DIM_TYPE) array_size(array,3); } %typemap(freearg) (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { /* for now, only concerned with lists */ $1 = PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) { npy_intp size[3] = { -1, -1, -1 }; PyArrayObject* temp_array; Py_ssize_t i; int is_new_object; /* length of the list */ $2 = PyList_Size($input); /* the arrays */ array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); is_new_object_array = (int *)calloc($2,sizeof(int)); if (array == NULL || object_array == NULL || is_new_object_array == NULL) { SWIG_fail; } for (i=0; i<$2; i++) { temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); /* the new array must be stored so that it can be destroyed in freearg */ object_array[i] = temp_array; is_new_object_array[i] = is_new_object; if (!temp_array || !require_dimensions(temp_array, 3)) SWIG_fail; /* store the size of the first array in the list, then use that for comparison. */ if (i == 0) { size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); size[2] = array_size(temp_array,2); } if (!require_size(temp_array, size, 3)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); } $1 = (DATA_TYPE**) array; $3 = (DIM_TYPE) size[0]; $4 = (DIM_TYPE) size[1]; $5 = (DIM_TYPE) size[2]; } %typemap(freearg) (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { Py_ssize_t i; if (array$argnum!=NULL) free(array$argnum); /*freeing the individual arrays if needed */ if (object_array$argnum!=NULL) { if (is_new_object_array$argnum!=NULL) { for (i=0; i<$2; i++) { if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) { Py_DECREF(object_array$argnum[i]); } } free(is_new_object_array$argnum); } free(object_array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, * DATA_TYPE* IN_ARRAY4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { -1, -1, -1 , -1}; array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DIM_TYPE) array_size(array,3); $5 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { -1, -1, -1, -1 }; array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4) | !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); $5 = (DIM_TYPE) array_size(array,3); } %typemap(freearg) (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, * DATA_TYPE* IN_FARRAY4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) { $1 = is_array($input) || PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) (PyArrayObject* array=NULL, int is_new_object=0) { npy_intp size[4] = { -1, -1, -1 , -1 }; array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, &is_new_object); if (!array || !require_dimensions(array, 4) || !require_size(array, size, 4) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DIM_TYPE) array_size(array,3); $5 = (DATA_TYPE*) array_data(array); } %typemap(freearg) (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) { if (is_new_object$argnum && array$argnum) { Py_DECREF(array$argnum); } } /***************************/ /* In-Place Array Typemaps */ /***************************/ /* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE INPLACE_ARRAY1[ANY]) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE INPLACE_ARRAY1[ANY]) (PyArrayObject* array=NULL) { npy_intp size[1] = { $1_dim0 }; array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = ($1_ltype) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) (PyArrayObject* array=NULL, int i=1) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,1) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = 1; for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); } /* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) (PyArrayObject* array=NULL, int i=0) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,1) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = 1; for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i); $2 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) (PyArrayObject* array=NULL) { npy_intp size[2] = { $1_dim0, $1_dim1 }; array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = ($1_ltype) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,2) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) (PyArrayObject* array=NULL) { npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = ($1_ltype) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); } /* Typemap suite for (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) { npy_intp size[2] = { -1, -1 }; PyArrayObject* temp_array; Py_ssize_t i; /* length of the list */ $2 = PyList_Size($input); /* the arrays */ array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); if (array == NULL || object_array == NULL) { SWIG_fail; } for (i=0; i<$2; i++) { temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); /* the new array must be stored so that it can be destroyed in freearg */ object_array[i] = temp_array; if ( !temp_array || !require_dimensions(temp_array, 2) || !require_contiguous(temp_array) || !require_native(temp_array) || !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) ) SWIG_fail; /* store the size of the first array in the list, then use that for comparison. */ if (i == 0) { size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); } if (!require_size(temp_array, size, 2)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); } $1 = (DATA_TYPE**) array; $3 = (DIM_TYPE) size[0]; $4 = (DIM_TYPE) size[1]; } %typemap(freearg) (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { if (array$argnum!=NULL) free(array$argnum); if (object_array$argnum!=NULL) free(object_array$argnum); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* INPLACE_ARRAY3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* INPLACE_FARRAY3) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,3) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) (PyArrayObject* array=NULL) { npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3 }; array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_size(array, size, 4) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = ($1_ltype) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); $5 = (DIM_TYPE) array_size(array,3); } /* Typemap suite for (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = PySequence_Check($input); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) { npy_intp size[3] = { -1, -1, -1 }; PyArrayObject* temp_array; Py_ssize_t i; /* length of the list */ $2 = PyList_Size($input); /* the arrays */ array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); if (array == NULL || object_array == NULL) { SWIG_fail; } for (i=0; i<$2; i++) { temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); /* the new array must be stored so that it can be destroyed in freearg */ object_array[i] = temp_array; if ( !temp_array || !require_dimensions(temp_array, 3) || !require_contiguous(temp_array) || !require_native(temp_array) || !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) ) SWIG_fail; /* store the size of the first array in the list, then use that for comparison. */ if (i == 0) { size[0] = array_size(temp_array,0); size[1] = array_size(temp_array,1); size[2] = array_size(temp_array,2); } if (!require_size(temp_array, size, 3)) SWIG_fail; array[i] = (DATA_TYPE*) array_data(temp_array); } $1 = (DATA_TYPE**) array; $3 = (DIM_TYPE) size[0]; $4 = (DIM_TYPE) size[1]; $5 = (DIM_TYPE) size[2]; } %typemap(freearg) (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { if (array$argnum!=NULL) free(array$argnum); if (object_array$argnum!=NULL) free(object_array$argnum); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, * DATA_TYPE* INPLACE_ARRAY4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DIM_TYPE) array_size(array,3); $5 = (DATA_TYPE*) array_data(array); } /* Typemap suite for (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, * DIM_TYPE DIM3, DIM_TYPE DIM4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = (DIM_TYPE) array_size(array,0); $3 = (DIM_TYPE) array_size(array,1); $4 = (DIM_TYPE) array_size(array,2); $5 = (DIM_TYPE) array_size(array,3); } /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, * DATA_TYPE* INPLACE_FARRAY4) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) (PyArrayObject* array=NULL) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_dimensions(array,4) || !require_contiguous(array) || !require_native(array) || !require_fortran(array)) SWIG_fail; $1 = (DIM_TYPE) array_size(array,0); $2 = (DIM_TYPE) array_size(array,1); $3 = (DIM_TYPE) array_size(array,2); $4 = (DIM_TYPE) array_size(array,3); $5 = (DATA_TYPE*) array_data(array); } /*************************/ /* Argout Array Typemaps */ /*************************/ /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY]) */ %typemap(in,numinputs=0, fragment="NumPy_Backward_Compatibility,NumPy_Macros") (DATA_TYPE ARGOUT_ARRAY1[ANY]) (PyObject* array = NULL) { npy_intp dims[1] = { $1_dim0 }; array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(argout) (DATA_TYPE ARGOUT_ARRAY1[ANY]) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) */ %typemap(in,numinputs=1, fragment="NumPy_Fragments") (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) (PyObject* array = NULL) { npy_intp dims[1]; if (!PyInt_Check($input)) { const char* typestring = pytype_string($input); PyErr_Format(PyExc_TypeError, "Int dimension expected. '%s' given.", typestring); SWIG_fail; } $2 = (DIM_TYPE) PyInt_AsLong($input); dims[0] = (npy_intp) $2; array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); } %typemap(argout) (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) */ %typemap(in,numinputs=1, fragment="NumPy_Fragments") (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) (PyObject* array = NULL) { npy_intp dims[1]; if (!PyInt_Check($input)) { const char* typestring = pytype_string($input); PyErr_Format(PyExc_TypeError, "Int dimension expected. '%s' given.", typestring); SWIG_fail; } $1 = (DIM_TYPE) PyInt_AsLong($input); dims[0] = (npy_intp) $1; array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); if (!array) SWIG_fail; $2 = (DATA_TYPE*) array_data(array); } %typemap(argout) (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) */ %typemap(in,numinputs=0, fragment="NumPy_Backward_Compatibility,NumPy_Macros") (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) (PyObject* array = NULL) { npy_intp dims[2] = { $1_dim0, $1_dim1 }; array = PyArray_SimpleNew(2, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(argout) (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) */ %typemap(in,numinputs=0, fragment="NumPy_Backward_Compatibility,NumPy_Macros") (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) (PyObject* array = NULL) { npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 }; array = PyArray_SimpleNew(3, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(argout) (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) */ %typemap(in,numinputs=0, fragment="NumPy_Backward_Compatibility,NumPy_Macros") (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) (PyObject* array = NULL) { npy_intp dims[4] = { $1_dim0, $1_dim1, $1_dim2, $1_dim3 }; array = PyArray_SimpleNew(4, dims, DATA_TYPECODE); if (!array) SWIG_fail; $1 = ($1_ltype) array_data(array); } %typemap(argout) (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) { $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); } /*****************************/ /* Argoutview Array Typemaps */ /*****************************/ /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) { $1 = &data_temp; $2 = &dim_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) { npy_intp dims[1] = { *$2 }; PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1) (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim_temp; $2 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) { npy_intp dims[1] = { *$1 }; PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) { npy_intp dims[2] = { *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) { npy_intp dims[2] = { *$1, *$2 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) { npy_intp dims[2] = { *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) { npy_intp dims[2] = { *$1, *$2 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[3] = { *$2, *$3, *$4 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) { npy_intp dims[3] = { *$1, *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[3] = { *$2, *$3, *$4 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEW_FARRAY3) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) { npy_intp dims[3] = { *$1, *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_ARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_FARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; $result = SWIG_Python_AppendOutput($result,obj); } /*************************************/ /* Managed Argoutview Array Typemaps */ /*************************************/ /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) { $1 = &data_temp; $2 = &dim_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) { npy_intp dims[1] = { *$2 }; PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEWM_ARRAY1) (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim_temp; $2 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) { npy_intp dims[1] = { *$1 }; PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) { npy_intp dims[2] = { *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_ARRAY2) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) { npy_intp dims[2] = { *$1, *$2 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) { npy_intp dims[2] = { *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_FARRAY2) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) { npy_intp dims[2] = { *$1, *$2 }; PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[3] = { *$2, *$3, *$4 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_ARRAY3) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) { npy_intp dims[3] = { *$1, *$2, *$3 }; PyObject* obj= PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[3] = { *$2, *$3, *$4 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_FARRAY3) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) { npy_intp dims[3] = { *$1, *$2, *$3 }; PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Utilities") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) */ %typemap(in,numinputs=0) (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) { $1 = &data_temp; $2 = &dim1_temp; $3 = &dim2_temp; $4 = &dim3_temp; $5 = &dim4_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) { npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) */ %typemap(in,numinputs=0) (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) { $1 = &dim1_temp; $2 = &dim2_temp; $3 = &dim3_temp; $4 = &dim4_temp; $5 = &data_temp; } %typemap(argout, fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) { npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); PyArrayObject* array = (PyArrayObject*) obj; if (!array || !require_fortran(array)) SWIG_fail; %#ifdef SWIGPY_USE_CAPSULE PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); %#else PyObject* cap = PyCObject_FromVoidPtr((void*)(*$1), free); %#endif %#if NPY_API_VERSION < 0x00000007 PyArray_BASE(array) = cap; %#else PyArray_SetBaseObject(array,cap); %#endif $result = SWIG_Python_AppendOutput($result,obj); } /**************************************/ /* In-Place Array Typemap - flattened */ /**************************************/ /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) */ %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, fragment="NumPy_Macros") (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) { $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), DATA_TYPECODE); } %typemap(in, fragment="NumPy_Fragments") (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) (PyArrayObject* array=NULL, int i=1) { array = obj_to_array_no_conversion($input, DATA_TYPECODE); if (!array || !require_c_or_f_contiguous(array) || !require_native(array)) SWIG_fail; $1 = (DATA_TYPE*) array_data(array); $2 = 1; for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); } %enddef /* %numpy_typemaps() macro */ /* *************************************************************** */ /* Concrete instances of the %numpy_typemaps() macro: Each invocation * below applies all of the typemaps above to the specified data type. */ %numpy_typemaps(signed char , NPY_BYTE , int) %numpy_typemaps(unsigned char , NPY_UBYTE , int) %numpy_typemaps(short , NPY_SHORT , int) %numpy_typemaps(unsigned short , NPY_USHORT , int) %numpy_typemaps(int , NPY_INT , int) %numpy_typemaps(unsigned int , NPY_UINT , int) %numpy_typemaps(long , NPY_LONG , int) %numpy_typemaps(unsigned long , NPY_ULONG , int) %numpy_typemaps(long long , NPY_LONGLONG , int) %numpy_typemaps(unsigned long long, NPY_ULONGLONG, int) %numpy_typemaps(float , NPY_FLOAT , int) %numpy_typemaps(double , NPY_DOUBLE , int) %numpy_typemaps(int8_t , NPY_INT8 , int) %numpy_typemaps(int16_t , NPY_INT16 , int) %numpy_typemaps(int32_t , NPY_INT32 , int) %numpy_typemaps(int64_t , NPY_INT64 , int) %numpy_typemaps(uint8_t , NPY_UINT8 , int) %numpy_typemaps(uint16_t , NPY_UINT16 , int) %numpy_typemaps(uint32_t , NPY_UINT32 , int) %numpy_typemaps(uint64_t , NPY_UINT64 , int) /* *************************************************************** * The follow macro expansion does not work, because C++ bool is 4 * bytes and NPY_BOOL is 1 byte * * %numpy_typemaps(bool, NPY_BOOL, int) */ /* *************************************************************** * On my Mac, I get the following warning for this macro expansion: * 'swig/python detected a memory leak of type 'long double *', no destructor found.' * * %numpy_typemaps(long double, NPY_LONGDOUBLE, int) */ #ifdef __cplusplus %include %numpy_typemaps(std::complex, NPY_CFLOAT , int) %numpy_typemaps(std::complex, NPY_CDOUBLE, int) #endif #endif /* SWIGPYTHON */ diegoferigo-cmake-build-extension-7a5deb5/example/pyproject.toml000066400000000000000000000005661466752063500252540ustar00rootroot00000000000000[build-system] requires = [ "wheel", # Check the updated version pinning requirements in: # https://github.com/pypa/setuptools_scm "setuptools", "setuptools_scm[toml]", "cmake_build_extension", "numpy", "pybind11", ] build-backend = "setuptools.build_meta" [tool.black] line-length = 88 [tool.isort] profile = "black" multi_line_output = 3 diegoferigo-cmake-build-extension-7a5deb5/example/setup.cfg000066400000000000000000000026761466752063500241650ustar00rootroot00000000000000[metadata] name = mymath description = Example to show how to use cmake-build-extension with CMake, SWIG and NumPy. long_description = file: README.md long_description_content_type = text/markdown author = Diego Ferigo author_email = dgferigo@gmail.com license = MIT platforms = any url = https://github.com/diegoferigo/cmake-build-extension/tree/master/example project_urls = Source = https://github.com/diegoferigo/cmake-build-extension/tree/master/examples/swig Tracker = https://github.com/diegoferigo/cmake-build-extension/issues keywords = setuptools extension cpp cmake build package pypi bindings swig pybind11 classifiers = [options] zip_safe = False packages = find: package_dir = =src python_requires = >=3.6 install_requires = numpy # This requirement is only necessary if the build_extension_env # context manager is used in the top-level __init__.py cmake-build-extension [options.packages.find] where = src [options.extras_require] test = pytest pytest-icdiff all = %(test)s # This also requires using the "expose_binaries" option in setup.py. # It creates a generic .bin.__main__ file that is exposed # as /bin/ that relays all input arguments to # the C++ executable. [options.entry_points] console_scripts = print_answer_swig = mymath_swig.bin.__main__:main print_answer_pybind11 = mymath_pybind11.bin.__main__:main [tool:pytest] addopts = -rsxX -v testpaths = tests diegoferigo-cmake-build-extension-7a5deb5/example/setup.py000066400000000000000000000122551466752063500240500ustar00rootroot00000000000000import inspect import os import sys from pathlib import Path import cmake_build_extension import setuptools # Importing the bindings inside the build_extension_env context manager is necessary only # in Windows with Python>=3.8. # See https://github.com/diegoferigo/cmake-build-extension/issues/8. # Note that if this manager is used in the init file, cmake-build-extension becomes an # install_requires that must be added to the setup.cfg. Otherwise, cmake-build-extension # could only be listed as build-system requires in pyproject.toml since it would only # be necessary for packaging and not during runtime. init_py = inspect.cleandoc( """ import cmake_build_extension with cmake_build_extension.build_extension_env(): from . import bindings """ ) # Extra options passed to the CI/CD pipeline that uses cibuildwheel CIBW_CMAKE_OPTIONS = [] if "CIBUILDWHEEL" in os.environ and os.environ["CIBUILDWHEEL"] == "1": # The manylinux variant runs in Debian Stretch and it uses lib64 folder if sys.platform == "linux": CIBW_CMAKE_OPTIONS += ["-DCMAKE_INSTALL_LIBDIR=lib"] # Eigen is not found when installed with vcpkg because we don't pass the toolchain. # Passing directly the right folder as workaround. This is meant to work just in CI. if os.name == "nt": CIBW_CMAKE_OPTIONS += [ "-DEigen3_DIR:PATH=C:/vcpkg/packages/eigen3_x64-windows/share/eigen3", ] # This example is compliant with PEP517 and PEP518. It uses the setup.cfg file to store # most of the package metadata. However, build extensions are not supported and must be # configured in the setup.py. setuptools.setup( # The resulting "mymath" archive contains two packages: mymath_swig and mymath_pybind. # This approach separates the two bindings types, typically just one of them is used. ext_modules=[ cmake_build_extension.CMakeExtension( # This could be anything you like, it is used to create build folders name="SwigBindings", # Name of the resulting package name (import mymath_swig) install_prefix="mymath_swig", # Exposes the binary print_answer to the environment. # It requires also adding a new entry point in setup.cfg. expose_binaries=["bin/print_answer"], # Writes the content to the top-level __init__.py write_top_level_init=init_py, # Selects the folder where the main CMakeLists.txt is stored # (it could be a subfolder) source_dir=str(Path(__file__).parent.absolute()), cmake_configure_options=[ # This option points CMake to the right Python interpreter, and helps # the logic of FindPython3.cmake to find the active version f"-DPython3_ROOT_DIR={Path(sys.prefix)}", "-DCALL_FROM_SETUP_PY:BOOL=ON", "-DBUILD_SHARED_LIBS:BOOL=OFF", # Select the bindings implementation "-DEXAMPLE_WITH_SWIG:BOOL=ON", "-DEXAMPLE_WITH_PYBIND11:BOOL=OFF", ] + CIBW_CMAKE_OPTIONS, ), cmake_build_extension.CMakeExtension( name="Pybind11Bindings", # Name of the resulting package name (import mymath_pybind11) install_prefix="mymath_pybind11", # Note: pybind11 is a build-system requirement specified in pyproject.toml, # therefore pypa/pip or pypa/build will install it in the virtual # environment created in /tmp during packaging. # This cmake_depends_on option adds the pybind11 installation path # to CMAKE_PREFIX_PATH so that the example finds the pybind11 targets # even if it is not installed in the system. cmake_depends_on=["pybind11"], # Exposes the binary print_answer to the environment. # It requires also adding a new entry point in setup.cfg. expose_binaries=["bin/print_answer"], # Writes the content to the top-level __init__.py write_top_level_init=init_py, # Selects the folder where the main CMakeLists.txt is stored # (it could be a subfolder) source_dir=str(Path(__file__).parent.absolute()), cmake_configure_options=[ # This option points CMake to the right Python interpreter, and helps # the logic of FindPython3.cmake to find the active version f"-DPython3_ROOT_DIR={Path(sys.prefix)}", "-DCALL_FROM_SETUP_PY:BOOL=ON", "-DBUILD_SHARED_LIBS:BOOL=OFF", # Select the bindings implementation "-DEXAMPLE_WITH_SWIG:BOOL=OFF", "-DEXAMPLE_WITH_PYBIND11:BOOL=ON", ] + CIBW_CMAKE_OPTIONS, ), ], cmdclass=dict( # Enable the CMakeExtension entries defined above build_ext=cmake_build_extension.BuildExtension, # If the setup.py or setup.cfg are in a subfolder wrt the main CMakeLists.txt, # you can use the following custom command to create the source distribution. # sdist=cmake_build_extension.GitSdistFolder ), ) diegoferigo-cmake-build-extension-7a5deb5/example/src/000077500000000000000000000000001466752063500231205ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/example/src/mymath.cpp000066400000000000000000000020341466752063500251220ustar00rootroot00000000000000#include "mymath.h" #include #include #include #include #include double mymath::dot(const std::vector& vector1, const std::vector& vector2) { if (vector1.size() != vector2.size()) { throw std::runtime_error("Sizes of the vector do not match"); } double dot = 0; for (size_t i = 0; i < vector1.size(); ++i) { dot += vector1[i] * vector2[i]; } return dot; } std::vector mymath::normalize(const std::vector& data) { auto sumOfSquared = [](double accumulator, const double element) { return accumulator + element * element; }; const double norm = sqrt(std::accumulate(data.begin(), data.end(), 0.0, sumOfSquared)); std::vector out; out.reserve(data.size()); std::transform(data.begin(), data.end(), std::back_inserter(out), [&](const double d) -> double { return d / norm; }); return out; } diegoferigo-cmake-build-extension-7a5deb5/example/src/mymath.h000066400000000000000000000016131466752063500245710ustar00rootroot00000000000000#ifndef MYMATH_H #define MYMATH_H #include namespace mymath { /** * Perform the inner product between two 1D vectors. * * @param vector1 The first vector. * @param vector2 The second vector. * @throws If the vectors sizes do not match. * @return The double product of the input vectors. */ double dot(const std::vector& vector1, const std::vector& vector2); /** * Normalize a 1D vector. * * The normalization operation takes the input vector and divides * all its element by its norm. The resulting vector is a unit vector, * i.e. a vector with length 1. * * @param input The vector to normalize. * @return The unit vector computed by normalizing the input. */ std::vector normalize(const std::vector& data); } // namespace mymath #endif // MYMATH_H diegoferigo-cmake-build-extension-7a5deb5/example/src/print_answer.cpp000066400000000000000000000003051466752063500263350ustar00rootroot00000000000000#include #include int main() { // Answer to the Ultimate Question of Life, the Universe, and Everything std::cout << int('*') << std::endl; return EXIT_SUCCESS; } diegoferigo-cmake-build-extension-7a5deb5/example/tests/000077500000000000000000000000001466752063500234735ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/example/tests/test_pybind11.py000066400000000000000000000031341466752063500265340ustar00rootroot00000000000000import sys import mymath_pybind11.bindings as mymath import numpy as np import pytest def test_dot(): v1 = [1.0, 2, 3, -5.5, 42] v2 = [-3.2, 0, 13, 6, -3.14] result = mymath.dot(vector1=v1, vector2=v2) assert pytest.approx(result) == np.dot(v1, v2) def test_normalize(): v = [1.0, 2, 3, -5.5, 42] result = mymath.normalize(data=v) assert pytest.approx(result) == np.array(v) / np.linalg.norm(v) def test_dot_numpy(): v1 = np.array([1.0, 2, 3, -5.5, 42]) v2 = np.array([-3.2, 0, 13, 6, -3.14]) result = mymath.dot(vector1=v1, vector2=v2) assert pytest.approx(result) == np.dot(v1, v2) def test_normalize_numpy(): v = np.array([1.0, 2, 3, -5.5, 42]) result = mymath.normalize_numpy(data=v) assert isinstance(result, np.ndarray) assert pytest.approx(result) == np.array(v) / np.linalg.norm(v) @pytest.mark.skipif( sys.platform == "win32", reason="fails with the error: access violation" ) def test_assertion(): v1 = np.array([1.0, 2, 3, -5.5]) v2 = np.array([42.0]) with pytest.raises(RuntimeError): _ = mymath.dot(vector1=v1, vector2=v2) @pytest.mark.skipif( sys.version_info < (3, 7), reason="capture_output and text require Python 3.7" ) def test_executable(): import subprocess result = subprocess.run("print_answer_pybind11", capture_output=True, text=True) assert result.stdout.strip() == "42" result = subprocess.run( [sys.executable, "-m", "mymath_pybind11.bin", "print_answer_pybind11"], capture_output=True, text=True, ) assert result.stdout.strip() == "42" diegoferigo-cmake-build-extension-7a5deb5/example/tests/test_swig.py000066400000000000000000000027501466752063500260610ustar00rootroot00000000000000import sys import mymath_swig.bindings as mymath import numpy as np import pytest def test_dot(): v1 = [1.0, 2, 3, -5.5, 42] v2 = [-3.2, 0, 13, 6, -3.14] result = mymath.dot(vector1=v1, vector2=v2) assert pytest.approx(result) == np.dot(v1, v2) def test_normalize(): v = [1.0, 2, 3, -5.5, 42] result = mymath.normalize(data=v) assert pytest.approx(result) == np.array(v) / np.linalg.norm(v) def test_dot_numpy(): v1 = np.array([1.0, 2, 3, -5.5, 42]) v2 = np.array([-3.2, 0, 13, 6, -3.14]) result = mymath.dot_numpy(in_1=v1, in_2=v2) assert pytest.approx(result) == np.dot(v1, v2) def test_normalize_numpy(): v = np.array([1.0, 2, 3, -5.5, 42]) result = mymath.normalize_numpy(in_1=v) assert isinstance(result, np.ndarray) assert pytest.approx(result) == np.array(v) / np.linalg.norm(v) def test_assertion(): v1 = np.array([1.0, 2, 3, -5.5]) v2 = np.array([42.0]) with pytest.raises(RuntimeError): _ = mymath.dot_numpy(in_1=v1, in_2=v2) @pytest.mark.skipif( sys.version_info < (3, 7), reason="capture_output and text require Python 3.7" ) def test_executable(): import subprocess result = subprocess.run("print_answer_swig", capture_output=True, text=True) assert result.stdout.strip() == "42" result = subprocess.run( [sys.executable, "-m", "mymath_swig.bin", "print_answer_swig"], capture_output=True, text=True, ) assert result.stdout.strip() == "42" diegoferigo-cmake-build-extension-7a5deb5/pyproject.toml000066400000000000000000000004211466752063500236070ustar00rootroot00000000000000[build-system] requires = [ "wheel", "setuptools>=45", "setuptools_scm[toml]>=6.0", ] build-backend = "setuptools.build_meta" [tool.setuptools_scm] local_scheme = "dirty-tag" [tool.black] line-length = 88 [tool.isort] profile = "black" multi_line_output = 3 diegoferigo-cmake-build-extension-7a5deb5/setup.cfg000066400000000000000000000027701466752063500225250ustar00rootroot00000000000000[metadata] name = cmake-build-extension description = Setuptools extension to build and package CMake projects. long_description = file: README.md long_description_content_type = text/markdown author = Diego Ferigo author_email = dgferigo@gmail.com license = MIT license_file = LICENSE platforms = any url = https://github.com/diegoferigo/cmake-build-extension project_urls = Changelog = https://github.com/diegoferigo/cmake-build-extension/releases Source = https://github.com/diegoferigo/cmake-build-extension Tracker = https://github.com/diegoferigo/cmake-build-extension/issues keywords = setuptools extension cmake build package pypi classifiers = Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: MIT License Operating System :: OS Independent Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: Implementation :: CPython Topic :: Software Development :: Build Tools Topic :: Software Development :: Libraries :: Python Modules Topic :: System :: Archiving :: Packaging [options] zip_safe = False packages = find: package_dir = =src python_requires = >=3.8 install_requires = cmake ninja GitPython setuptools_scm [options.packages.find] where = src diegoferigo-cmake-build-extension-7a5deb5/setup.py000066400000000000000000000000461466752063500224100ustar00rootroot00000000000000from setuptools import setup setup() diegoferigo-cmake-build-extension-7a5deb5/src/000077500000000000000000000000001466752063500214655ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/src/cmake_build_extension/000077500000000000000000000000001466752063500260205ustar00rootroot00000000000000diegoferigo-cmake-build-extension-7a5deb5/src/cmake_build_extension/__init__.py000066400000000000000000000023251466752063500301330ustar00rootroot00000000000000import os from contextlib import contextmanager from pathlib import Path from . import build_ext_option, sdist_command from .build_extension import BuildExtension from .cmake_extension import CMakeExtension from .sdist_command import GitSdistFolder, GitSdistTree @contextmanager def build_extension_env(): """ Creates a context in which build extensions can be imported. It fixes a change of behaviour of Python >= 3.8 in Windows: https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew Other related resources: - https://stackoverflow.com/a/23805306 - https://www.mail-archive.com/dev@subversion.apache.org/msg40414.html Example: .. code-block:: python from cmake_build_extension import build_extension_env with build_extension_env(): from . import bindings """ cookies = [] # Windows and Python >= 3.8 if hasattr(os, "add_dll_directory"): for path in os.environ.get("PATH", "").split(os.pathsep): if path and Path(path).is_absolute() and Path(path).is_dir(): cookies.append(os.add_dll_directory(path)) try: yield finally: for cookie in cookies: cookie.close() diegoferigo-cmake-build-extension-7a5deb5/src/cmake_build_extension/build_ext_option.py000066400000000000000000000027771466752063500317560ustar00rootroot00000000000000from typing import NamedTuple from setuptools.command.build_ext import build_ext class BuildExtOption(NamedTuple): """ NamedTuple that stores the metadata of a custom build_ext option. Example: The following option: BuildExtOption(variable="define", short="D", help="New compiler define") is displayed as follows: $ python setup.py build_ext --help ... Options for 'BuildExtension' command: ... --define (-D) New compiler define ... """ variable: str short: str help: str = "" def add_new_build_ext_option(option: BuildExtOption, override: bool = True): """ Workaround to add an existing option shown in python setup.py build_ext -h. Args: option: The new option to add. override: Delete the option if it already exists. """ if override: # Remove from the existing build_ext.user_options the option to override build_ext.user_options = [ o for o in build_ext.user_options if o[1] is not option.short ] else: # Just check if the option already exists, and raise if it does for o in build_ext.user_options: if o[1] == option.short: raise ValueError(f"Short option '{o[1]}' already exists") # The long variable name must finish with =, here we append it option = option._replace(variable=f"{option.variable}=") # Add the new option build_ext.user_options.append(tuple(option)) diegoferigo-cmake-build-extension-7a5deb5/src/cmake_build_extension/build_extension.py000066400000000000000000000256471466752063500316030ustar00rootroot00000000000000import importlib.util import os import platform import shutil import subprocess from pathlib import Path from setuptools.command.build_ext import build_ext from .build_ext_option import BuildExtOption, add_new_build_ext_option from .cmake_extension import CMakeExtension # These options are listed in `python setup.py build_ext -h` custom_options = [ BuildExtOption( variable="define", short="D", help="Create or update CMake cache " "(example: '-DBAR=b;FOO=f')", ), BuildExtOption( variable="component", short="C", help="Install only a specific CMake component (example: '-Cbindings')", ), BuildExtOption( variable="no-cmake-extension", short="K", help="Disable a CMakeExtension module (examples: '-Kall', '-Kbar', '-Kbar;foo')", ), ] for o in custom_options: add_new_build_ext_option(option=o, override=True) class BuildExtension(build_ext): """ Setuptools build extension handler. It processes all the extensions listed in the 'ext_modules' entry. """ def initialize_options(self): # Initialize base class build_ext.initialize_options(self) # Initialize the '--define' custom option, overriding the pre-existing one. # Originally, it was aimed to pass C preprocessor definitions, but instead we # use it to pass custom configuration options to CMake. self.define = None # Initialize the '--component' custom option. # It overrides the content of the cmake_component option of CMakeExtension. self.component = None # Initialize the 'no-cmake-extension' custom option. # It allows disabling one or more CMakeExtension from the command line. self.no_cmake_extension = None def finalize_options(self): # Parse the custom CMake options and store them in a new attribute defines = [] if self.define is None else self.define.split(";") self.cmake_defines = [f"-D{define}" for define in defines] # Parse the disabled CMakeExtension modules and store them in a new attribute self.no_cmake_extensions = ( [] if self.no_cmake_extension is None else self.no_cmake_extension.split(";") ) # Call base class build_ext.finalize_options(self) def run(self) -> None: """ Process all the registered extensions executing only the CMakeExtension objects. """ # Filter the CMakeExtension objects cmake_extensions = [e for e in self.extensions if isinstance(e, CMakeExtension)] if len(cmake_extensions) == 0: raise ValueError("No CMakeExtension objects found") # Check that CMake is installed if shutil.which("cmake") is None: raise RuntimeError("Required command 'cmake' not found") for ext in cmake_extensions: # Check that Ninja is installed if (ext.cmake_generator and ext.cmake_generator.lower() == "ninja" and shutil.which("ninja") is None): raise RuntimeError("Required command 'ninja' not found") # Disable the extension if specified in the command line if ( ext.name in self.no_cmake_extensions or "all" in self.no_cmake_extensions ): continue # Disable all extensions if this env variable is present disabled_set = {"0", "false", "off", "no"} env_var_name = "CMAKE_BUILD_EXTENSION_ENABLED" if ( env_var_name in os.environ and os.environ[env_var_name].lower() in disabled_set ): continue self.build_extension(ext) def build_extension(self, ext: CMakeExtension) -> None: """ Build a CMakeExtension object. Args: ext: The CMakeExtension object to build. """ if self.inplace and ext.disable_editable: print(f"Editable install recognized. Extension '{ext.name}' disabled.") return # Export CMAKE_PREFIX_PATH of all the dependencies for pkg in ext.cmake_depends_on: try: importlib.import_module(pkg) except ImportError: raise ValueError(f"Failed to import '{pkg}'") init = importlib.util.find_spec(pkg).origin BuildExtension.extend_cmake_prefix_path(path=str(Path(init).parent)) # The ext_dir directory can be thought as a temporary site-package folder. # # Case 1: regular installation. # ext_dir is the folder that gets compressed to make the wheel archive. When # installed, the archive is extracted in the active site-package directory. # Case 2: editable installation. # ext_dir is the in-source folder containing the Python packages. In this case, # the CMake project is installed in-source. ext_dir = Path(self.get_ext_fullpath(ext.name)).parent.absolute() cmake_install_prefix = ext_dir / ext.install_prefix # Initialize the CMake configuration arguments configure_args = [] # Select the appropriate generator and accompanying settings if ext.cmake_generator is not None: configure_args += ["-G", ext.cmake_generator] if ext.cmake_generator == "Ninja": # Fix #26: https://github.com/diegoferigo/cmake-build-extension/issues/26 configure_args += [f"-DCMAKE_MAKE_PROGRAM={shutil.which('ninja')}"] # CMake configure arguments configure_args += [ f"-DCMAKE_BUILD_TYPE={ext.cmake_build_type}", f"-DCMAKE_INSTALL_PREFIX:PATH={cmake_install_prefix}", ] # Extend the configure arguments with those passed from the extension configure_args += ext.cmake_configure_options # CMake build arguments build_args = ["--config", ext.cmake_build_type] # CMake install arguments install_args = ["--config", ext.cmake_build_type] if platform.system() == "Windows": configure_args += [] elif platform.system() in {"Linux", "Darwin", "GNU"}: configure_args += [] else: raise RuntimeError(f"Unsupported '{platform.system()}' platform") # Parse the optional CMake options. They can be passed as: # # python setup.py build_ext -D"BAR=Foo;VAR=TRUE" # python setup.py bdist_wheel build_ext -D"BAR=Foo;VAR=TRUE" # python setup.py install build_ext -D"BAR=Foo;VAR=TRUE" # python setup.py install -e build_ext -D"BAR=Foo;VAR=TRUE" # pip install --global-option="build_ext" --global-option="-DBAR=Foo;VAR=TRUE" . # configure_args += self.cmake_defines # Get the absolute path to the build folder build_folder = str(Path(".").absolute() / f"{self.build_temp}_{ext.name}") # Make sure that the build folder exists Path(build_folder).mkdir(exist_ok=True, parents=True) # 1. Compose CMake configure command configure_command = [ "cmake", "-S", ext.source_dir, "-B", build_folder, ] + configure_args # 2. Compose CMake build command build_command = ["cmake", "--build", build_folder] + build_args # 3. Compose CMake install command install_command = ["cmake", "--install", build_folder] + install_args # If the cmake_component option of the CMakeExtension is used, install just # the specified component. if self.component is None and ext.cmake_component is not None: install_command.extend(["--component", ext.cmake_component]) # Instead, if the `--component` command line option is used, install just # the specified component. This has higher priority than what specified in # the CMakeExtension. if self.component is not None: install_command.extend(["--component", self.component]) print("") print("==> Configuring:") print(f"$ {' '.join(configure_command)}") print("") print("==> Building:") print(f"$ {' '.join(build_command)}") print("") print("==> Installing:") print(f"$ {' '.join(install_command)}") print("") # Call CMake subprocess.check_call(configure_command) subprocess.check_call(build_command) subprocess.check_call(install_command) # Write content to the top-level __init__.py if ext.write_top_level_init is not None: with open(file=cmake_install_prefix / "__init__.py", mode="w") as f: f.write(ext.write_top_level_init) # Write content to the bin/__main__.py magic file to expose binaries if len(ext.expose_binaries) > 0: bin_dirs = {str(Path(d).parents[0]) for d in ext.expose_binaries} import inspect main_py = inspect.cleandoc( f""" from pathlib import Path import subprocess import sys def main(): binary_name = Path(sys.argv[0]).name prefix = Path(__file__).parent.parent bin_dirs = {str(bin_dirs)} binary_path = "" for dir in bin_dirs: path = prefix / Path(dir) / binary_name if path.is_file(): binary_path = str(path) break path = Path(str(path) + ".exe") if path.is_file(): binary_path = str(path) break if not Path(binary_path).is_file(): name = binary_path if binary_path != "" else binary_name raise RuntimeError(f"Failed to find binary: {{ name }}") sys.argv[0] = binary_path result = subprocess.run(args=sys.argv, capture_output=False) exit(result.returncode) if __name__ == "__main__" and len(sys.argv) > 1: sys.argv = sys.argv[1:] main()""" ) bin_folder = cmake_install_prefix / "bin" Path(bin_folder).mkdir(exist_ok=True, parents=True) with open(file=bin_folder / "__main__.py", mode="w") as f: f.write(main_py) @staticmethod def extend_cmake_prefix_path(path: str) -> None: abs_path = Path(path).absolute() if not abs_path.exists(): raise ValueError(f"Path {abs_path} does not exist") if "CMAKE_PREFIX_PATH" in os.environ: os.environ[ "CMAKE_PREFIX_PATH" ] = f"{str(path)}:{os.environ['CMAKE_PREFIX_PATH']}" else: os.environ["CMAKE_PREFIX_PATH"] = str(path) diegoferigo-cmake-build-extension-7a5deb5/src/cmake_build_extension/cmake_extension.py000066400000000000000000000046271466752063500315570ustar00rootroot00000000000000from pathlib import Path from typing import List from setuptools import Extension class CMakeExtension(Extension): """ Custom setuptools extension that configures a CMake project. Args: name: The name of the extension. install_prefix: The path relative to the site-package directory where the CMake project is installed (typically the name of the Python package). disable_editable: Skip this extension in editable mode. write_top_level_init: Create a new top-level ``__init__.py`` file in the install prefix and write content. cmake_configure_options: List of additional CMake configure options (-DBAR=FOO). source_dir: The location of the main CMakeLists.txt. cmake_build_type: The default build type of the CMake project. cmake_component: The name of component to install. Defaults to all components. cmake_depends_on: List of dependency packages containing required CMake projects. expose_binaries: List of binary paths to expose, relative to top-level directory. cmake_generator: The generator to be used by CMake. Defaults to Ninja. """ def __init__( self, name: str, install_prefix: str = "", disable_editable: bool = False, write_top_level_init: str = None, cmake_configure_options: List[str] = (), source_dir: str = str(Path(".").absolute()), cmake_build_type: str = "Release", cmake_component: str = None, cmake_depends_on: List[str] = (), expose_binaries: List[str] = (), cmake_generator: str = "Ninja", ): super().__init__(name=name, sources=[]) if not Path(source_dir).is_absolute(): source_dir = str(Path(".").absolute() / source_dir) if not Path(source_dir).absolute().is_dir(): raise ValueError(f"Directory '{source_dir}' does not exist") self.install_prefix = install_prefix self.cmake_build_type = cmake_build_type self.disable_editable = disable_editable self.write_top_level_init = write_top_level_init self.cmake_depends_on = cmake_depends_on self.source_dir = str(Path(source_dir).absolute()) self.cmake_configure_options = cmake_configure_options self.cmake_component = cmake_component self.expose_binaries = expose_binaries self.cmake_generator = cmake_generator diegoferigo-cmake-build-extension-7a5deb5/src/cmake_build_extension/sdist_command.py000066400000000000000000000127211466752063500312210ustar00rootroot00000000000000import abc import os from pathlib import Path from shutil import copy2 from typing import Generator, List import setuptools.command.sdist class GitSdistABC(abc.ABC, setuptools.command.sdist.sdist): """ This class defines a custom command to build source distribution. It covers the case where projects store the setup.cfg file in a subfolder and are git repositories. The problem in this setup is that only the subfolder by default is packaged in the sdist, resulting in a archive that only contains part of the whole repo. """ def make_release_tree(self, base_dir, files) -> None: """ This method is the responsible of building the list of files that are included in the source distribution. These files (that could be the entire git tree) are copied in the subfolder before creating the archive, resulting in a source distribution like if the setup.cfg would be part of the top-level folder. This method prepares the egg metadata for the source distribution and allows specifying a list of files that are copied in the location of the setup.cfg. """ import setuptools_scm.integration # Build the setuptools_scm configuration, containing useful info for the sdist config: setuptools_scm.integration.Configuration = ( setuptools_scm.integration.Configuration.from_file( dist_name=self.distribution.metadata.name ) ) # Get the root of the git repository repo_root = config.absolute_root if not Path(repo_root).exists() or not Path(repo_root).is_dir(): raise RuntimeError(f"Failed to find a git repo in {repo_root}") # Prepare the release tree by calling the original method super(GitSdistABC, self).make_release_tree(base_dir=base_dir, files=files) # Collect all the files and copy them in the subfolder containing setup.cfg for file in self.get_sdist_files(repo_root=repo_root): src = Path(file) dst = Path(base_dir) / Path(file).relative_to(repo_root) # Make sure that the parent directory of the destination exists dst.absolute().parent.mkdir(parents=True, exist_ok=True) print(f"{Path(file).relative_to(repo_root)} -> {dst}") copy2(src=src, dst=dst) # Create the updated list of files included in the sdist all_files_gen = Path(base_dir).glob(pattern="**/*") all_files = [str(f.relative_to(base_dir)) for f in all_files_gen] # Find the SOURCES.txt file sources_txt_list = list(Path(base_dir).glob(pattern=f"*.egg-info/SOURCES.txt")) assert len(sources_txt_list) == 1 # Update the SOURCES.txt files with the real content of the sdist os.unlink(sources_txt_list[0]) with open(file=sources_txt_list[0], mode="w") as f: f.write("\n".join([str(f) for f in all_files])) @staticmethod @abc.abstractmethod def get_sdist_files(repo_root: str) -> List[Path]: """ Return all files that will be included in the source distribution. Note: the egg metadata are included by default, there's not need to specify them. Args: repo_root: The path to the root of the git repository. Returns: The list of files to include in the source distribution. """ class GitSdistTree(GitSdistABC): """ This class defines a custom command to build source distribution. It covers the case where projects store the setup.cfg file in a subfolder and are git repositories. The problem in this setup is that only the subfolder by default is packaged in the sdist, resulting in a archive that only contains part of the whole repo. In particular, this class copies all the files that are part of the last git commit. Any uncommitted or staged files are ignored and are not part of the sdist. """ @staticmethod def get_sdist_files(repo_root: str) -> List[Path]: import git # Create the git Repo object git_repo = git.Repo(path=repo_root) # Get all the files of the git repo recursively def list_paths( tree: git.Tree, path: Path = Path(".") ) -> Generator[Path, None, None]: for blob in tree.blobs: yield path / blob.name for tree in tree.trees: yield from list_paths(tree=tree, path=path / tree.name) # Return the list of absolute paths to all the git repo files return list(list_paths(tree=git_repo.commit().tree, path=Path(repo_root))) class GitSdistFolder(GitSdistABC): """ This class defines a custom command to build source distribution. It covers the case where projects store the setup.cfg file in a subfolder and are git repositories. The problem in this setup is that only the subfolder by default is packaged in the sdist, resulting in a archive that only contains part of the whole repo. In particular, this class copies all the files that are part of the git folder. It includes also all uncommitted and staged files. """ @staticmethod def get_sdist_files(repo_root: str) -> List[Path]: # Create the list of files of the git folder all_files_gen = Path(repo_root).glob(pattern="**/*") # Return the list of absolute paths to all the git folder files (also uncommited) return [f for f in all_files_gen if not f.is_dir() and ".git" not in f.parts]