├── .github └── workflows │ └── python.yml ├── .gitignore ├── LICENSE ├── README.md ├── example ├── .clang-format ├── CMakeLists.txt ├── README.md ├── bindings_pybind11 │ ├── CMakeLists.txt │ └── bindings.cpp ├── bindings_swig │ ├── CMakeLists.txt │ ├── bindings.i │ └── numpy.i ├── pyproject.toml ├── setup.cfg ├── setup.py ├── src │ ├── mymath.cpp │ ├── mymath.h │ └── print_answer.cpp └── tests │ ├── test_pybind11.py │ └── test_swig.py ├── pyproject.toml ├── setup.cfg ├── setup.py └── src └── cmake_build_extension ├── __init__.py ├── build_ext_option.py ├── build_extension.py ├── cmake_extension.py └── sdist_command.py /.github/workflows/python.yml: -------------------------------------------------------------------------------- 1 | name: Python CI/CD 2 | 3 | on: 4 | push: 5 | pull_request: 6 | release: 7 | types: 8 | - published 9 | 10 | jobs: 11 | 12 | build-and-test: 13 | name: 'Python${{ matrix.python-version }}@${{ matrix.os }}' 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | python-version: 19 | - 3.8 20 | - 3.9 21 | - "3.10" 22 | - "3.11" 23 | - "3.12" 24 | - "3.13" 25 | os: 26 | - ubuntu-22.04 27 | - macos-latest 28 | - windows-latest 29 | include: 30 | - optional: false 31 | 32 | steps: 33 | 34 | - uses: actions/checkout@v4 35 | - run: git fetch --prune --unshallow 36 | 37 | - name: Set up Python 38 | uses: actions/setup-python@v5 39 | with: 40 | python-version: ${{ matrix.python-version }} 41 | 42 | - name: Install cmake-build-extensions 43 | run: pip install wheel && pip install -v .[all] 44 | 45 | - name: Example dependencies [Windows] 46 | if: contains(matrix.os, 'windows') 47 | shell: bash 48 | run: | 49 | choco install -y swig 50 | vcpkg install --triplet x64-windows eigen3 51 | 52 | - name: Example dependencies [macOS] 53 | if: contains(matrix.os, 'macOS') 54 | run: | 55 | brew install swig eigen 56 | # https://cibuildwheel.readthedocs.io/en/stable/cpp_standards 57 | echo "MACOSX_DEPLOYMENT_TARGET=10.14" >> $GITHUB_ENV 58 | 59 | - name: Example dependencies [Ubuntu] 60 | if: contains(matrix.os, 'ubuntu') 61 | run: | 62 | sudo apt update 63 | sudo apt install build-essential swig libeigen3-dev 64 | 65 | - name: Build and install example 66 | continue-on-error: ${{ matrix.optional }} 67 | working-directory: example 68 | run: pip install -v .[all] 69 | env: 70 | # Pretend to be using cibuildwheel 71 | CIBUILDWHEEL: 1 72 | 73 | - name: Test example 74 | continue-on-error: ${{ matrix.optional }} 75 | working-directory: example 76 | run: pytest 77 | 78 | publish: 79 | name: Publish to PyPI 80 | needs: build-and-test 81 | runs-on: ubuntu-22.04 82 | permissions: 83 | id-token: write 84 | 85 | steps: 86 | 87 | - uses: actions/checkout@master 88 | - run: git fetch --prune --unshallow 89 | 90 | - name: Set up Python 91 | uses: actions/setup-python@v5 92 | with: 93 | python-version: "3.10" 94 | 95 | - name: Install Python tools 96 | run: pip install build 97 | 98 | - name: Create distributions 99 | run: python -m build -o dist/ 100 | 101 | - name: Inspect dist folder 102 | run: ls -lah dist/ 103 | 104 | - name: Check wheel 105 | run: test $(find dist/ -name *-none-any.whl | wc -l) -gt 0 106 | 107 | - name: Upload artifacts 108 | uses: actions/upload-artifact@v4 109 | with: 110 | path: dist/* 111 | name: dist 112 | 113 | - name: Publish to PyPI 114 | if: | 115 | github.repository == 'diegoferigo/cmake-build-extension' && 116 | ((github.event_name == 'push' && github.ref == 'refs/heads/master') || 117 | (github.event_name == 'release')) 118 | uses: pypa/gh-action-pypi-publish@release/v1 119 | with: 120 | skip_existing: true 121 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.swp 3 | *.old 4 | *.bak 5 | CMakeLists.txt.user* 6 | 7 | # Byte-compiled / optimized / DLL files 8 | __pycache__/ 9 | *.py[cod] 10 | *$py.class 11 | 12 | # C extensions 13 | *.so 14 | 15 | # Distribution / packaging 16 | .Python 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | .eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | wheels/ 29 | pip-wheel-metadata/ 30 | share/python-wheels/ 31 | *.egg-info/ 32 | .installed.cfg 33 | *.egg 34 | MANIFEST 35 | 36 | # PyInstaller 37 | # Usually these files are written by a python script from a template 38 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 39 | *.manifest 40 | *.spec 41 | 42 | # Installer logs 43 | pip-log.txt 44 | pip-delete-this-directory.txt 45 | 46 | # Unit test / coverage reports 47 | htmlcov/ 48 | .tox/ 49 | .nox/ 50 | .coverage 51 | .coverage.* 52 | .cache 53 | nosetests.xml 54 | coverage.xml 55 | *.cover 56 | *.py,cover 57 | .hypothesis/ 58 | .pytest_cache/ 59 | 60 | # Translations 61 | *.mo 62 | *.pot 63 | 64 | # Django stuff: 65 | *.log 66 | local_settings.py 67 | db.sqlite3 68 | db.sqlite3-journal 69 | 70 | # Flask stuff: 71 | instance/ 72 | .webassets-cache 73 | 74 | # Scrapy stuff: 75 | .scrapy 76 | 77 | # Sphinx documentation 78 | docs/_build/ 79 | 80 | # PyBuilder 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # IPython 87 | profile_default/ 88 | ipython_config.py 89 | 90 | # pyenv 91 | .python-version 92 | 93 | # pipenv 94 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 95 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 96 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 97 | # install all needed dependencies. 98 | #Pipfile.lock 99 | 100 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 101 | __pypackages__/ 102 | 103 | # Celery stuff 104 | celerybeat-schedule 105 | celerybeat.pid 106 | 107 | # SageMath parsed files 108 | *.sage.py 109 | 110 | # Environments 111 | .env 112 | .venv 113 | env/ 114 | venv/ 115 | ENV/ 116 | env.bak/ 117 | venv.bak/ 118 | 119 | # Spyder project settings 120 | .spyderproject 121 | .spyproject 122 | 123 | # Rope project settings 124 | .ropeproject 125 | 126 | # mkdocs documentation 127 | /site 128 | 129 | # mypy 130 | .mypy_cache/ 131 | .dmypy.json 132 | dmypy.json 133 | 134 | # Pyre type checker 135 | .pyre/ 136 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Diego Ferigo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cmake-build-extension 2 | 3 | [![Version](https://img.shields.io/pypi/v/cmake-build-extension.svg)][pypi] 4 | [![Python versions](https://img.shields.io/pypi/pyversions/cmake-build-extension.svg)][pypi] 5 | [![Status](https://img.shields.io/pypi/status/cmake-build-extension.svg)][pypi] 6 | [![Format](https://img.shields.io/pypi/format/cmake-build-extension.svg)][pypi] 7 | [![License](https://img.shields.io/pypi/l/cmake-build-extension.svg)][pypi] 8 | [![Python CI/CD](https://github.com/diegoferigo/cmake-build-extension/workflows/Python%20CI/CD/badge.svg)][ci_cd] 9 | 10 | [pypi]: https://pypi.org/project/cmake-build-extension/ 11 | [ci_cd]: https://github.com/diegoferigo/cmake-build-extension/actions/workflows/python.yml 12 | 13 | **Setuptools extension to build and package CMake projects.** 14 | 15 | This project aims to simplify the integration of C++ projects based on CMake with Python packaging tools. 16 | CMake provides out-of-the-box support to either [SWIG][swig] and [pybind11][pybind11], 17 | that are two among the most used projects to create Python bindings from C++ sources. 18 | 19 | [swig]: https://github.com/swig/swig 20 | [pybind11]: https://github.com/pybind/pybind11 21 | 22 | If you have any experience with these hybrid projects, you know the challenges to make packaging right! 23 | This project takes inspiration from pre-existing examples 24 | ([`pybind/cmake_example`][pybind11_example], among many others) 25 | and provides a simple, flexible, and reusable setuptools extension with the following features: 26 | 27 | - Bridge between CMake projects and Python packaging. 28 | - Configure and build the CMake project from `setup.py`. 29 | - Install the CMake project in the resulting Python package. 30 | - Allow passing custom CMake options. 31 | - Allow creating a top-level `__init__.py`. 32 | - Expose C++ executables to the Python environment. 33 | - Provide a context manager to import reliably CPython modules on all major OSs. 34 | - Disable the C++ extension in editable installations (requiring to manually call CMake to install the C++ project). 35 | 36 | [pybind11_example]: https://github.com/pybind/cmake_example 37 | 38 | Have a look to the [example](example/) for an overview of what can be done with this extension. 39 | It shows how to create SWIG and pybind11 bindings for a project composed by a small C++ library with NumPy support 40 | and an executable. 41 | 42 | ### Advanced features 43 | 44 | 1. This extension supports creating packages [PEP517] and [PEP518] compliant ([more details][pyproject]). 45 | 2. If the CMake project [exports the targets][export_targets], downstream projects can: 46 | 1. Extend their `CMAKE_MODULE_PATH` with the root of your installed Python package, 47 | that could be obtained with: 48 | ```bash 49 | python -c "import , pathlib; print(pathlib.Path(.__file__).parent)" 50 | ``` 51 | and consume the exported CMake targets. 52 | 1. Use `cmake-build-extension` with the `cmake_depends_on` option and link against the exported CMake targets 53 | during the downstream packaging. 54 | 55 | Note that the second feature allows distributing C++ dependencies through PyPI. 56 | The resulting package structure is similar to other projects like [pybind11][pybind11_pypi] and [CasADi][casadi_pypi]. 57 | Be aware that ensuring ABI compatibility could be problematic in edge cases, 58 | and the usage of a proper [compatible release pattern][pep440] (`~=`) could be necessary. 59 | 60 | [pep440]: https://www.python.org/dev/peps/pep-0440/#compatible-release 61 | [pep517]: https://www.python.org/dev/peps/pep-0517/ 62 | [pep518]: https://www.python.org/dev/peps/pep-0518/ 63 | 64 | [pyproject]: https://snarky.ca/what-the-heck-is-pyproject-toml/ 65 | [export_targets]: https://cmake.org/cmake/help/git-stage/guide/importing-exporting/index.html 66 | 67 | [pybind11_pypi]: https://pypi.org/project/pybind11/ 68 | [casadi_pypi]: https://pypi.org/project/casadi/ 69 | 70 | ## Installation 71 | 72 | From PyPI: 73 | 74 | ```bash 75 | pip install cmake-build-extension 76 | ``` 77 | 78 | From the repository: 79 | 80 | ```bash 81 | pip install git+https://github.com/diegoferigo/cmake-build-extension 82 | ``` 83 | 84 | ## Usage 85 | 86 | Once both CMake project and `setup.py|setup.cfg|pyproject.toml` of your hybrid package are correctly configured 87 | to use the resources provided by cmake-build-extension, the following commands can be used: 88 | 89 | ```bash 90 | # ============ 91 | # Create sdist 92 | # ============ 93 | 94 | # Calling setup.py 95 | python setup.py sdist 96 | 97 | # Using pypa/build 98 | python -m build --sdist 99 | 100 | # ============ 101 | # Create wheel 102 | # ============ 103 | 104 | # Calling setup.py 105 | python setup.py bdist_wheel 106 | 107 | # Using pip 108 | pip wheel -w dist/ . 109 | 110 | # Using pypa/build 111 | python -m build --wheel 112 | 113 | # ========================================================== 114 | # Create wheel or install package passing additional options 115 | # ========================================================== 116 | 117 | # Calling setup.py 118 | python setup.py {bdist_wheel|install} build_ext -D"BAR=Foo;VAR=TRUE" 119 | 120 | # Using pip 121 | pip {wheel|install} --global-option="build_ext" --global-option="-DBAR=Foo;VAR=TRUE" . 122 | 123 | # Using pypa/build (only wheel creation) 124 | python -m build --wheel "-C--global-option=build_ext" "-C--global-option=-DBAR=Foo;VAR=TRUE" 125 | ``` 126 | 127 | ## Caveats 128 | 129 | ### `manylinux*` support 130 | 131 | This extension, beyond packaging the hybrid C++ / Python project, 132 | also allows the inclusion of the exported CMake targets in the resulting wheel. 133 | This result depends on how the CMake project is configured, 134 | and whether the [exported targets][exp_imp_wiki] are installed together with the other files. 135 | 136 | [exp_imp_wiki]: https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/Exporting-and-Importing-Targets 137 | 138 | Such hybrid packages can then be uploaded to PyPI. 139 | Though, on GNU/Linux, the generated wheel is not compliant by default with any [`manylinux*`][manylinux] standard. 140 | Tools such [auditwheel][auditwheel] exist to fix these wheels, but they require running on selected distributions. 141 | Luckily, other projects like [cibuildwheel][cibuildwheel] greatly simplify the process in CI. 142 | 143 | [manylinux]: https://github.com/pypa/manylinux 144 | [auditwheel]: https://github.com/pypa/auditwheel 145 | [cibuildwheel]: https://github.com/joerick/cibuildwheel 146 | 147 | This being said, `manylinux*` guidelines could still work against you. 148 | In fact, wheels supporting `manylinux2010|manylinux2014` are built [with gcc4][pep599_manylinux2014] 149 | that does not support the new C++11 ABIs. 150 | In few words, this means that the exported libraries bundled in the wheel cannot 151 | be imported in a downstream project using relatively new C++ standards! 152 | For more details visit [robotology/idyntree#776](https://github.com/robotology/idyntree/issues/776). 153 | 154 | [pep599_manylinux2014]: https://www.python.org/dev/peps/pep-0599/#the-manylinux2014-policy 155 | 156 | Luckily, the situation changed thanks to the finalization of [PEP600][pep600], i.e. `manylinuxX_YY` :tada: 157 | If you build a PEP600 compliant wheel (nowadays compatible with most of the commonly used distributions), 158 | your exported CMake project bundled in the wheel can be successfully imported downstream. 159 | If you want to support this use case, make sure to produce and distribute wheels compliant with PEP600. 160 | 161 | [pep600]: https://www.python.org/dev/peps/pep-0600/ 162 | 163 | ### Loading CPython modules in Windows 164 | 165 | Python 3.8 [changed][changelog_3_8] how DLL are resolved. 166 | By default, modules that could be imported in Python 3.7 stopped working, and using the new 167 | [`os.add_dll_directory`][add_dll_directory] is now necessary. 168 | 169 | In order to streamline the process, `cmake-build-extension` implements a context manager that can be used 170 | to import reliably the bindings module: 171 | 172 | ```python 173 | import cmake_build_extension 174 | 175 | with cmake_build_extension.build_extension_env(): 176 | from . import bindings 177 | ``` 178 | 179 | It will take care to temporarily fix the search path. 180 | 181 | For more details, refer to [#8][windows_import_issue] and [#12][windows_import_pr]. 182 | 183 | [changelog_3_8]: https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew 184 | [add_dll_directory]: https://docs.python.org/3/library/os.html#os.add_dll_directory 185 | [windows_import_issue]: https://github.com/diegoferigo/cmake-build-extension/issues/8 186 | [windows_import_pr]: https://github.com/diegoferigo/cmake-build-extension/pull/12 187 | 188 | ### `setup.py|setup.cfg|pyproject.toml` files in subfolder 189 | 190 | Sometimes hybrid projects are C++ centric, and keeping these files in the top-level folder is not desirable. 191 | In this setup, however, problems occur if the main `CMakeLists.txt` is kept in the top-level folder 192 | (see [pypa/build#322][sdist_issue]). 193 | To solve this problem, `cmake-build-extension` provides custom commands to create source distribution. 194 | You can use one of the following custom `sdist` options in `setup.py`: 195 | 196 | ```python 197 | setuptools.setup( 198 | cmdclass=dict( 199 | # [...] 200 | # Pack the whole git folder: 201 | sdist=cmake_build_extension.GitSdistFolder, 202 | # Pack only the git tree: 203 | sdist=cmake_build_extension.GitSdistTree, 204 | # Or, inherit from cmake_build_extension.sdist_command.GitSdistABC and 205 | # make your own custom sdist including only the files you are interested 206 | ), 207 | ) 208 | ``` 209 | 210 | [sdist_issue]: https://github.com/pypa/build/issues/322 211 | 212 | ## Downstream projects 213 | 214 | If the provided example is not enough complex, find here below a list of projects using `cmake-build-extension`: 215 | 216 | - [`robotology/idyntree`](https://github.com/robotology/idyntree/) 217 | - [`robotology/yarp`](https://github.com/robotology/yarp/) 218 | - [`robotology/ycm`](https://github.com/robotology/ycm/) 219 | - [`diegoferigo/gazebo-yarp-synchronizer`](https://github.com/diegoferigo/gazebo-yarp-synchronizer) 220 | - [`robotology/gym-ignition@scenario`](https://github.com/robotology/gym-ignition/tree/devel/scenario) 221 | - [`dic-iit/gazebo-scenario-plugins`](https://github.com/dic-iit/gazebo-scenario-plugins/) 222 | - [`dic-iit/bipedal-locomotion-framework`](https://github.com/dic-iit/bipedal-locomotion-framework) 223 | - [`artivis/manif`](https://github.com/artivis/manif) 224 | 225 | ## Contributing 226 | 227 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 228 | 229 | ## License 230 | 231 | [MIT](https://choosealicense.com/licenses/mit/) 232 | -------------------------------------------------------------------------------- /example/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: WebKit 4 | AccessModifierOffset: -4 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Left 9 | AlignOperands: true 10 | AlignTrailingComments: false 11 | AllowAllParametersOfDeclarationOnNextLine: false 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: Inline 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: true 21 | BinPackArguments: false 22 | BinPackParameters: false 23 | BraceWrapping: 24 | AfterClass: true 25 | AfterControlStatement: false 26 | AfterEnum: true 27 | AfterFunction: true 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: true 31 | AfterUnion: false 32 | BeforeCatch: true 33 | BeforeElse: true 34 | IndentBraces: false 35 | SplitEmptyFunction: false 36 | SplitEmptyRecord: false 37 | SplitEmptyNamespace: false 38 | BreakBeforeBinaryOperators: NonAssignment 39 | BreakBeforeBraces: Custom 40 | BreakBeforeInheritanceComma: true 41 | BreakBeforeTernaryOperators: true 42 | BreakConstructorInitializersBeforeComma: true 43 | BreakConstructorInitializers: BeforeComma 44 | BreakAfterJavaFieldAnnotations: false 45 | BreakStringLiterals: true 46 | ColumnLimit: 80 47 | CommentPragmas: '^ IWYU pragma:' 48 | CompactNamespaces: false 49 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 50 | ConstructorInitializerIndentWidth: 4 51 | ContinuationIndentWidth: 4 52 | Cpp11BracedListStyle: true 53 | DerivePointerAlignment: false 54 | DisableFormat: false 55 | ExperimentalAutoDetectBinPacking: false 56 | FixNamespaceComments: true 57 | ForEachMacros: 58 | - foreach 59 | - Q_FOREACH 60 | - BOOST_FOREACH 61 | IncludeBlocks: Preserve 62 | IncludeCategories: 63 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 64 | Priority: 2 65 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 66 | Priority: 3 67 | - Regex: '.*' 68 | Priority: 1 69 | IncludeIsMainRegex: '(Test)?$' 70 | IndentCaseLabels: true 71 | IndentWidth: 4 72 | IndentWrappedFunctionNames: false 73 | JavaScriptQuotes: Leave 74 | JavaScriptWrapImports: true 75 | KeepEmptyLinesAtTheStartOfBlocks: true 76 | MacroBlockBegin: '' 77 | MacroBlockEnd: '' 78 | MaxEmptyLinesToKeep: 1 79 | NamespaceIndentation: All 80 | ObjCBlockIndentWidth: 4 81 | ObjCSpaceAfterProperty: true 82 | ObjCSpaceBeforeProtocolList: true 83 | PenaltyBreakAssignment: 2 84 | PenaltyBreakBeforeFirstCallParameter: 19 85 | PenaltyBreakComment: 300 86 | PenaltyBreakFirstLessLess: 120 87 | PenaltyBreakString: 1000 88 | PenaltyExcessCharacter: 1000000 89 | PenaltyReturnTypeOnItsOwnLine: 60 90 | PointerAlignment: Left 91 | ReflowComments: true 92 | SortIncludes: true 93 | SortUsingDeclarations: true 94 | SpaceAfterCStyleCast: true 95 | SpaceAfterTemplateKeyword: true 96 | SpaceBeforeAssignmentOperators: true 97 | SpaceBeforeParens: ControlStatements 98 | SpaceInEmptyParentheses: false 99 | SpacesBeforeTrailingComments: 1 100 | SpacesInAngles: false 101 | SpacesInContainerLiterals: true 102 | SpacesInCStyleCastParentheses: false 103 | SpacesInParentheses: false 104 | SpacesInSquareBrackets: false 105 | Standard: Cpp11 106 | TabWidth: 4 107 | UseTab: Never 108 | ... 109 | -------------------------------------------------------------------------------- /example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18.2) 2 | project(MyMath VERSION 1.0) 3 | 4 | # C++ standard 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_C_EXTENSIONS OFF) 7 | set(CMAKE_CXX_EXTENSIONS OFF) 8 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 9 | 10 | # Common installation directories 11 | include(GNUInstallDirs) 12 | 13 | # Use -fPIC even if statically compiled 14 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 15 | 16 | # ============ 17 | # math library 18 | # ============ 19 | 20 | # Create the mymath library 21 | add_library(mymath 22 | src/mymath.h 23 | src/mymath.cpp) 24 | add_library(MyMath::mymath ALIAS mymath) 25 | 26 | set_target_properties(mymath PROPERTIES 27 | PUBLIC_HEADER src/mymath.h) 28 | 29 | target_include_directories(mymath PUBLIC 30 | $ 31 | $) 32 | 33 | # ======================= 34 | # print_answer executable 35 | # ======================= 36 | 37 | # Create the print_answer executable 38 | add_executable(print_answer src/print_answer.cpp) 39 | 40 | # ======= 41 | # Install 42 | # ======= 43 | 44 | # See official documentation on exporting targets: 45 | # https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html#exporting-targets 46 | 47 | # Install the target with C++ code 48 | install( 49 | TARGETS mymath print_answer 50 | EXPORT MyMathTargets 51 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 52 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 53 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 54 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) 55 | 56 | # Install the exported targets 57 | install( 58 | EXPORT MyMathTargets 59 | FILE MyMathTargets.cmake 60 | NAMESPACE MyMath:: 61 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyMath) 62 | 63 | # Create a CMake package 64 | include(CMakePackageConfigHelpers) 65 | 66 | # Prepare the Config.cmake.in content 67 | set(PACKAGE_INIT_MACRO "@PACKAGE_INIT@") 68 | set(CONFIG_CMAKE_IN "\ 69 | @PACKAGE_INIT_MACRO@\n\ 70 | include(\"\${CMAKE_CURRENT_LIST_DIR}/MyMathTargets.cmake\")\n\ 71 | check_required_components(MyMath)\n" 72 | ) 73 | 74 | # Create Config.cmake.in 75 | file(CONFIGURE 76 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Config.cmake.in 77 | CONTENT ${CONFIG_CMAKE_IN} 78 | @ONLY) 79 | 80 | # Create MyMathConfig.cmake 81 | configure_package_config_file( 82 | ${CMAKE_CURRENT_BINARY_DIR}/Config.cmake.in 83 | ${CMAKE_CURRENT_BINARY_DIR}/MyMathConfig.cmake 84 | INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyMath) 85 | 86 | # Create MyMathConfigVersion.cmake 87 | write_basic_package_version_file( 88 | "${CMAKE_CURRENT_BINARY_DIR}/MyMathConfigVersion.cmake" 89 | VERSION "${version}" 90 | COMPATIBILITY AnyNewerVersion 91 | ) 92 | 93 | # Install CMake package files 94 | install(FILES 95 | "${CMAKE_CURRENT_BINARY_DIR}/MyMathConfig.cmake" 96 | "${CMAKE_CURRENT_BINARY_DIR}/MyMathConfigVersion.cmake" 97 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyMath 98 | ) 99 | 100 | # =============== 101 | # Python bindings 102 | # =============== 103 | 104 | # Find Python3 and NumPy 105 | find_package(Python3 COMPONENTS Interpreter Development.Module NumPy REQUIRED) 106 | 107 | # Handle where to install the resulting Python package 108 | if(CALL_FROM_SETUP_PY) 109 | # The CMakeExtension will set CMAKE_INSTALL_PREFIX to the root 110 | # of the resulting wheel archive 111 | set(MYMATH_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) 112 | else() 113 | # The Python package is installed directly in the folder of the 114 | # detected interpreter (system, user, or virtualenv) 115 | set(MYMATH_INSTALL_PREFIX ${Python3_SITELIB}) 116 | endif() 117 | 118 | # ============= 119 | # SWIG bindings 120 | # ============= 121 | 122 | if(EXAMPLE_WITH_SWIG) 123 | # Rename the executable 124 | set_target_properties(print_answer PROPERTIES OUTPUT_NAME print_answer_swig) 125 | 126 | # Add the bindings 127 | add_subdirectory(bindings_swig) 128 | endif() 129 | 130 | # ================= 131 | # Pybind11 bindings 132 | # ================= 133 | 134 | if(EXAMPLE_WITH_PYBIND11) 135 | # Rename the executable 136 | set_target_properties(print_answer PROPERTIES OUTPUT_NAME print_answer_pybind11) 137 | 138 | # Add the bindings 139 | add_subdirectory(bindings_pybind11) 140 | endif() 141 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diegoferigo/cmake-build-extension/4bd5dab5c2e3eeaf5ed1b40d7aa159b83a1fb7c9/example/README.md -------------------------------------------------------------------------------- /example/bindings_pybind11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(pybind11 REQUIRED) 2 | find_package(Eigen3 REQUIRED NO_MODULE) 3 | 4 | # ======= 5 | # Library 6 | # ======= 7 | 8 | # Create the pybind11 library 9 | pybind11_add_module(pybind11_bindings MODULE bindings.cpp) 10 | 11 | target_link_libraries(pybind11_bindings 12 | PRIVATE MyMath::mymath Eigen3::Eigen) 13 | 14 | # The name of the shared library must match the module name 15 | set_target_properties(pybind11_bindings PROPERTIES 16 | LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mymath 17 | OUTPUT_NAME "bindings") 18 | 19 | # ======= 20 | # Install 21 | # ======= 22 | 23 | # Install the pybind11 library 24 | install( 25 | TARGETS pybind11_bindings 26 | COMPONENT bindings 27 | LIBRARY DESTINATION ${MYMATH_INSTALL_PREFIX} 28 | ARCHIVE DESTINATION ${MYMATH_INSTALL_PREFIX} 29 | RUNTIME DESTINATION ${MYMATH_INSTALL_PREFIX}) 30 | -------------------------------------------------------------------------------- /example/bindings_pybind11/bindings.cpp: -------------------------------------------------------------------------------- 1 | #include "mymath.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | // Create the Python module 11 | PYBIND11_MODULE(bindings, module) 12 | { 13 | namespace py = ::pybind11; 14 | module.doc() = "mymath bindings"; 15 | 16 | // These methods accept numpy array but return float / list 17 | module.def("dot", &mymath::dot, py::arg("vector1"), py::arg("vector2")); 18 | module.def("normalize", &mymath::normalize, py::arg("data")); 19 | 20 | // In order to return directly a numpy object, we can pass through Eigen 21 | module.def( 22 | "normalize_numpy", 23 | [](const std::vector& data) -> Eigen::VectorXd { 24 | const auto output = mymath::normalize(data); 25 | return Eigen::Map( 26 | const_cast(output.data()), output.size()); 27 | }, 28 | py::arg("data")); 29 | } 30 | -------------------------------------------------------------------------------- /example/bindings_swig/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Set SWIG policies 2 | cmake_policy(SET CMP0078 NEW) 3 | cmake_policy(SET CMP0086 NEW) 4 | 5 | find_package(SWIG 4.0 REQUIRED) 6 | set(UseSWIG_MODULE_VERSION 2) 7 | include(${SWIG_USE_FILE}) 8 | 9 | # ======= 10 | # Library 11 | # ======= 12 | 13 | # The name of the shared library must match the module name 14 | set_source_files_properties(bindings.i PROPERTIES 15 | CPLUSPLUS ON 16 | SWIG_MODULE_NAME "bindings") 17 | 18 | # Create the SWIG library 19 | swig_add_library(swig_bindings 20 | TYPE MODULE 21 | LANGUAGE python 22 | OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/mymath 23 | OUTFILE_DIR ${CMAKE_CURRENT_BINARY_DIR} 24 | SOURCES bindings.i) 25 | 26 | target_link_libraries(swig_bindings 27 | PRIVATE MyMath::mymath Python3::NumPy) 28 | 29 | set_target_properties(swig_bindings PROPERTIES 30 | LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mymath) 31 | 32 | set_property(TARGET swig_bindings PROPERTY 33 | SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE) 34 | 35 | # Enable parsing the doxygen comments 36 | set_property(TARGET swig_bindings 37 | PROPERTY SWIG_COMPILE_OPTIONS -doxygen) 38 | 39 | # Add dependency to numpy.i 40 | set_property( 41 | TARGET swig_bindings 42 | PROPERTY SWIG_DEPENDS numpy.i) 43 | 44 | # ======= 45 | # Install 46 | # ======= 47 | 48 | # Get the autogenerated Python file 49 | get_property(WRAPPER_PY_FILE 50 | TARGET swig_bindings 51 | PROPERTY SWIG_SUPPORT_FILES) 52 | 53 | # Install the autogenerated Python file 54 | install( 55 | FILES ${WRAPPER_PY_FILE} 56 | DESTINATION ${MYMATH_INSTALL_PREFIX} 57 | COMPONENT bindings) 58 | 59 | # Install the SWIG library 60 | install( 61 | TARGETS swig_bindings 62 | COMPONENT bindings 63 | LIBRARY DESTINATION ${MYMATH_INSTALL_PREFIX} 64 | ARCHIVE DESTINATION ${MYMATH_INSTALL_PREFIX} 65 | RUNTIME DESTINATION ${MYMATH_INSTALL_PREFIX}) 66 | -------------------------------------------------------------------------------- /example/bindings_swig/bindings.i: -------------------------------------------------------------------------------- 1 | // Documentation: https://numpy.org/doc/stable/reference/swig.interface-file.html 2 | 3 | %module(package="mathlib") mymath 4 | 5 | %{ 6 | #define SWIG_FILE_WITH_INIT 7 | #include "mymath.h" 8 | %} 9 | 10 | %naturalvar; 11 | 12 | // Convert all exceptions to RuntimeError 13 | %include "exception.i" 14 | %exception { 15 | try { 16 | $action 17 | } catch (const std::exception& e) { 18 | SWIG_exception(SWIG_RuntimeError, e.what()); 19 | } 20 | } 21 | 22 | // Convert std::vector <-> python containers 23 | %include 24 | %template(VectorD) std::vector; 25 | 26 | // Doxygen typemaps 27 | %typemap(doctype) std::vector "Iterable[float]"; 28 | 29 | // Necessary for type hinting 30 | %pythonbegin %{ 31 | from typing import Iterable 32 | %} 33 | 34 | // Include numpy.i typemaps 35 | %include "numpy.i" 36 | 37 | // Initialize NumPy 38 | %init %{ 39 | import_array(); 40 | %} 41 | 42 | // Apply the NumPy typemaps to the following signatures 43 | %apply (double* IN_ARRAY1, int DIM1) {(double* in_1, unsigned size_in_1)}; 44 | %apply (double* IN_ARRAY1, int DIM1) {(double* in_2, unsigned size_in_2)}; 45 | %apply (double** ARGOUTVIEWM_ARRAY1, int* DIM1) {(double** out_1, int* size_out_1)}; 46 | 47 | // Create manually additional functions to allow using directly NumPy types 48 | // without the need to alter the original C++ library 49 | %inline %{ 50 | namespace numpy { 51 | double dot_numpy(double* in_1, unsigned size_in_1, 52 | double* in_2, unsigned size_in_2) 53 | { 54 | const std::vector vector1(in_1, in_1 + size_in_1); 55 | const std::vector vector2(in_2, in_2 + size_in_2); 56 | 57 | return mymath::dot(vector1, vector2); 58 | } 59 | 60 | void normalize_numpy(double* in_1, unsigned size_in_1, 61 | double** out_1, int* size_out_1) 62 | { 63 | const std::vector vector(in_1, in_1 + size_in_1); 64 | 65 | auto result = mymath::normalize(vector); 66 | 67 | *out_1 = static_cast(malloc(result.size() * sizeof(double))); 68 | std::copy(result.begin(), result.end(), *out_1); 69 | 70 | *size_out_1 = result.size(); 71 | } 72 | } 73 | %} 74 | 75 | // Include the header with the symbols to wrap 76 | %include "mymath.h" 77 | -------------------------------------------------------------------------------- /example/bindings_swig/numpy.i: -------------------------------------------------------------------------------- 1 | /* -*- C -*- (not really, but good for syntax highlighting) */ 2 | 3 | /* 4 | * Copyright (c) 2005-2015, NumPy Developers. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 14 | * * Redistributions in binary form must reproduce the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer in the documentation and/or other materials provided 17 | * with the distribution. 18 | * 19 | * * Neither the name of the NumPy Developers nor the names of any 20 | * contributors may be used to endorse or promote products derived 21 | * from this software without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | 36 | #ifdef SWIGPYTHON 37 | 38 | %{ 39 | #ifndef SWIG_FILE_WITH_INIT 40 | #define NO_IMPORT_ARRAY 41 | #endif 42 | #include "stdio.h" 43 | #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 44 | #include 45 | %} 46 | 47 | /**********************************************************************/ 48 | 49 | %fragment("NumPy_Backward_Compatibility", "header") 50 | { 51 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 52 | %#define NPY_ARRAY_DEFAULT NPY_DEFAULT 53 | %#define NPY_ARRAY_FARRAY NPY_FARRAY 54 | %#define NPY_FORTRANORDER NPY_FORTRAN 55 | %#endif 56 | } 57 | 58 | /**********************************************************************/ 59 | 60 | /* The following code originally appeared in 61 | * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was 62 | * translated from C++ to C by John Hunter. Bill Spotz has modified 63 | * it to fix some minor bugs, upgrade from Numeric to numpy (all 64 | * versions), add some comments and functionality, and convert from 65 | * direct code insertion to SWIG fragments. 66 | */ 67 | 68 | %fragment("NumPy_Macros", "header") 69 | { 70 | /* Macros to extract array attributes. 71 | */ 72 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 73 | %#define is_array(a) ((a) && PyArray_Check((PyArrayObject*)a)) 74 | %#define array_type(a) (int)(PyArray_TYPE((PyArrayObject*)a)) 75 | %#define array_numdims(a) (((PyArrayObject*)a)->nd) 76 | %#define array_dimensions(a) (((PyArrayObject*)a)->dimensions) 77 | %#define array_size(a,i) (((PyArrayObject*)a)->dimensions[i]) 78 | %#define array_strides(a) (((PyArrayObject*)a)->strides) 79 | %#define array_stride(a,i) (((PyArrayObject*)a)->strides[i]) 80 | %#define array_data(a) (((PyArrayObject*)a)->data) 81 | %#define array_descr(a) (((PyArrayObject*)a)->descr) 82 | %#define array_flags(a) (((PyArrayObject*)a)->flags) 83 | %#define array_clearflags(a,f) (((PyArrayObject*)a)->flags) &= ~f 84 | %#define array_enableflags(a,f) (((PyArrayObject*)a)->flags) = f 85 | %#define array_is_fortran(a) (PyArray_ISFORTRAN((PyArrayObject*)a)) 86 | %#else 87 | %#define is_array(a) ((a) && PyArray_Check(a)) 88 | %#define array_type(a) PyArray_TYPE((PyArrayObject*)a) 89 | %#define array_numdims(a) PyArray_NDIM((PyArrayObject*)a) 90 | %#define array_dimensions(a) PyArray_DIMS((PyArrayObject*)a) 91 | %#define array_strides(a) PyArray_STRIDES((PyArrayObject*)a) 92 | %#define array_stride(a,i) PyArray_STRIDE((PyArrayObject*)a,i) 93 | %#define array_size(a,i) PyArray_DIM((PyArrayObject*)a,i) 94 | %#define array_data(a) PyArray_DATA((PyArrayObject*)a) 95 | %#define array_descr(a) PyArray_DESCR((PyArrayObject*)a) 96 | %#define array_flags(a) PyArray_FLAGS((PyArrayObject*)a) 97 | %#define array_enableflags(a,f) PyArray_ENABLEFLAGS((PyArrayObject*)a,f) 98 | %#define array_clearflags(a,f) PyArray_CLEARFLAGS((PyArrayObject*)a,f) 99 | %#define array_is_fortran(a) (PyArray_IS_F_CONTIGUOUS((PyArrayObject*)a)) 100 | %#endif 101 | %#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS((PyArrayObject*)a)) 102 | %#define array_is_native(a) (PyArray_ISNOTSWAPPED((PyArrayObject*)a)) 103 | } 104 | 105 | /**********************************************************************/ 106 | 107 | %fragment("NumPy_Utilities", 108 | "header") 109 | { 110 | /* Given a PyObject, return a string describing its type. 111 | */ 112 | const char* pytype_string(PyObject* py_obj) 113 | { 114 | if (py_obj == NULL ) return "C NULL value"; 115 | if (py_obj == Py_None ) return "Python None" ; 116 | if (PyCallable_Check(py_obj)) return "callable" ; 117 | if (PyBytes_Check( py_obj)) return "string" ; 118 | if (PyLong_Check( py_obj)) return "int" ; 119 | if (PyFloat_Check( py_obj)) return "float" ; 120 | if (PyDict_Check( py_obj)) return "dict" ; 121 | if (PyList_Check( py_obj)) return "list" ; 122 | if (PyTuple_Check( py_obj)) return "tuple" ; 123 | 124 | return "unknown type"; 125 | } 126 | 127 | /* Given a NumPy typecode, return a string describing the type. 128 | */ 129 | const char* typecode_string(int typecode) 130 | { 131 | static const char* type_names[25] = {"bool", 132 | "byte", 133 | "unsigned byte", 134 | "short", 135 | "unsigned short", 136 | "int", 137 | "unsigned int", 138 | "long", 139 | "unsigned long", 140 | "long long", 141 | "unsigned long long", 142 | "float", 143 | "double", 144 | "long double", 145 | "complex float", 146 | "complex double", 147 | "complex long double", 148 | "object", 149 | "string", 150 | "unicode", 151 | "void", 152 | "ntypes", 153 | "notype", 154 | "char", 155 | "unknown"}; 156 | return typecode < 24 ? type_names[typecode] : type_names[24]; 157 | } 158 | 159 | /* Make sure input has correct numpy type. This now just calls 160 | PyArray_EquivTypenums(). 161 | */ 162 | int type_match(int actual_type, 163 | int desired_type) 164 | { 165 | return PyArray_EquivTypenums(actual_type, desired_type); 166 | } 167 | 168 | void free_cap(PyObject * cap) 169 | { 170 | void* array = (void*) PyCapsule_GetPointer(cap,SWIGPY_CAPSULE_NAME); 171 | if (array != NULL) free(array); 172 | } 173 | 174 | 175 | } 176 | 177 | /**********************************************************************/ 178 | 179 | %fragment("NumPy_Object_to_Array", 180 | "header", 181 | fragment="NumPy_Backward_Compatibility", 182 | fragment="NumPy_Macros", 183 | fragment="NumPy_Utilities") 184 | { 185 | /* Given a PyObject pointer, cast it to a PyArrayObject pointer if 186 | * legal. If not, set the python error string appropriately and 187 | * return NULL. 188 | */ 189 | PyArrayObject* obj_to_array_no_conversion(PyObject* input, 190 | int typecode) 191 | { 192 | PyArrayObject* ary = NULL; 193 | if (is_array(input) && (typecode == NPY_NOTYPE || 194 | PyArray_EquivTypenums(array_type(input), typecode))) 195 | { 196 | ary = (PyArrayObject*) input; 197 | } 198 | else if is_array(input) 199 | { 200 | const char* desired_type = typecode_string(typecode); 201 | const char* actual_type = typecode_string(array_type(input)); 202 | PyErr_Format(PyExc_TypeError, 203 | "Array of type '%s' required. Array of type '%s' given", 204 | desired_type, actual_type); 205 | ary = NULL; 206 | } 207 | else 208 | { 209 | const char* desired_type = typecode_string(typecode); 210 | const char* actual_type = pytype_string(input); 211 | PyErr_Format(PyExc_TypeError, 212 | "Array of type '%s' required. A '%s' was given", 213 | desired_type, 214 | actual_type); 215 | ary = NULL; 216 | } 217 | return ary; 218 | } 219 | 220 | /* Convert the given PyObject to a NumPy array with the given 221 | * typecode. On success, return a valid PyArrayObject* with the 222 | * correct type. On failure, the python error string will be set and 223 | * the routine returns NULL. 224 | */ 225 | PyArrayObject* obj_to_array_allow_conversion(PyObject* input, 226 | int typecode, 227 | int* is_new_object) 228 | { 229 | PyArrayObject* ary = NULL; 230 | PyObject* py_obj; 231 | if (is_array(input) && (typecode == NPY_NOTYPE || 232 | PyArray_EquivTypenums(array_type(input),typecode))) 233 | { 234 | ary = (PyArrayObject*) input; 235 | *is_new_object = 0; 236 | } 237 | else 238 | { 239 | py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_ARRAY_DEFAULT); 240 | /* If NULL, PyArray_FromObject will have set python error value.*/ 241 | ary = (PyArrayObject*) py_obj; 242 | *is_new_object = 1; 243 | } 244 | return ary; 245 | } 246 | 247 | /* Given a PyArrayObject, check to see if it is contiguous. If so, 248 | * return the input pointer and flag it as not a new object. If it is 249 | * not contiguous, create a new PyArrayObject using the original data, 250 | * flag it as a new object and return the pointer. 251 | */ 252 | PyArrayObject* make_contiguous(PyArrayObject* ary, 253 | int* is_new_object, 254 | int min_dims, 255 | int max_dims) 256 | { 257 | PyArrayObject* result; 258 | if (array_is_contiguous(ary)) 259 | { 260 | result = ary; 261 | *is_new_object = 0; 262 | } 263 | else 264 | { 265 | result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, 266 | array_type(ary), 267 | min_dims, 268 | max_dims); 269 | *is_new_object = 1; 270 | } 271 | return result; 272 | } 273 | 274 | /* Given a PyArrayObject, check to see if it is Fortran-contiguous. 275 | * If so, return the input pointer, but do not flag it as not a new 276 | * object. If it is not Fortran-contiguous, create a new 277 | * PyArrayObject using the original data, flag it as a new object 278 | * and return the pointer. 279 | */ 280 | PyArrayObject* make_fortran(PyArrayObject* ary, 281 | int* is_new_object) 282 | { 283 | PyArrayObject* result; 284 | if (array_is_fortran(ary)) 285 | { 286 | result = ary; 287 | *is_new_object = 0; 288 | } 289 | else 290 | { 291 | Py_INCREF(array_descr(ary)); 292 | result = (PyArrayObject*) PyArray_FromArray(ary, 293 | array_descr(ary), 294 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 295 | NPY_FORTRANORDER); 296 | %#else 297 | NPY_ARRAY_F_CONTIGUOUS); 298 | %#endif 299 | *is_new_object = 1; 300 | } 301 | return result; 302 | } 303 | 304 | /* Convert a given PyObject to a contiguous PyArrayObject of the 305 | * specified type. If the input object is not a contiguous 306 | * PyArrayObject, a new one will be created and the new object flag 307 | * will be set. 308 | */ 309 | PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, 310 | int typecode, 311 | int* is_new_object) 312 | { 313 | int is_new1 = 0; 314 | int is_new2 = 0; 315 | PyArrayObject* ary2; 316 | PyArrayObject* ary1 = obj_to_array_allow_conversion(input, 317 | typecode, 318 | &is_new1); 319 | if (ary1) 320 | { 321 | ary2 = make_contiguous(ary1, &is_new2, 0, 0); 322 | if ( is_new1 && is_new2) 323 | { 324 | Py_DECREF(ary1); 325 | } 326 | ary1 = ary2; 327 | } 328 | *is_new_object = is_new1 || is_new2; 329 | return ary1; 330 | } 331 | 332 | /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the 333 | * specified type. If the input object is not a Fortran-ordered 334 | * PyArrayObject, a new one will be created and the new object flag 335 | * will be set. 336 | */ 337 | PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input, 338 | int typecode, 339 | int* is_new_object) 340 | { 341 | int is_new1 = 0; 342 | int is_new2 = 0; 343 | PyArrayObject* ary2; 344 | PyArrayObject* ary1 = obj_to_array_allow_conversion(input, 345 | typecode, 346 | &is_new1); 347 | if (ary1) 348 | { 349 | ary2 = make_fortran(ary1, &is_new2); 350 | if (is_new1 && is_new2) 351 | { 352 | Py_DECREF(ary1); 353 | } 354 | ary1 = ary2; 355 | } 356 | *is_new_object = is_new1 || is_new2; 357 | return ary1; 358 | } 359 | } /* end fragment */ 360 | 361 | /**********************************************************************/ 362 | 363 | %fragment("NumPy_Array_Requirements", 364 | "header", 365 | fragment="NumPy_Backward_Compatibility", 366 | fragment="NumPy_Macros") 367 | { 368 | /* Test whether a python object is contiguous. If array is 369 | * contiguous, return 1. Otherwise, set the python error string and 370 | * return 0. 371 | */ 372 | int require_contiguous(PyArrayObject* ary) 373 | { 374 | int contiguous = 1; 375 | if (!array_is_contiguous(ary)) 376 | { 377 | PyErr_SetString(PyExc_TypeError, 378 | "Array must be contiguous. A non-contiguous array was given"); 379 | contiguous = 0; 380 | } 381 | return contiguous; 382 | } 383 | 384 | /* Test whether a python object is (C_ or F_) contiguous. If array is 385 | * contiguous, return 1. Otherwise, set the python error string and 386 | * return 0. 387 | */ 388 | int require_c_or_f_contiguous(PyArrayObject* ary) 389 | { 390 | int contiguous = 1; 391 | if (!(array_is_contiguous(ary) || array_is_fortran(ary))) 392 | { 393 | PyErr_SetString(PyExc_TypeError, 394 | "Array must be contiguous (C_ or F_). A non-contiguous array was given"); 395 | contiguous = 0; 396 | } 397 | return contiguous; 398 | } 399 | 400 | /* Require that a numpy array is not byte-swapped. If the array is 401 | * not byte-swapped, return 1. Otherwise, set the python error string 402 | * and return 0. 403 | */ 404 | int require_native(PyArrayObject* ary) 405 | { 406 | int native = 1; 407 | if (!array_is_native(ary)) 408 | { 409 | PyErr_SetString(PyExc_TypeError, 410 | "Array must have native byteorder. " 411 | "A byte-swapped array was given"); 412 | native = 0; 413 | } 414 | return native; 415 | } 416 | 417 | /* Require the given PyArrayObject to have a specified number of 418 | * dimensions. If the array has the specified number of dimensions, 419 | * return 1. Otherwise, set the python error string and return 0. 420 | */ 421 | int require_dimensions(PyArrayObject* ary, 422 | int exact_dimensions) 423 | { 424 | int success = 1; 425 | if (array_numdims(ary) != exact_dimensions) 426 | { 427 | PyErr_Format(PyExc_TypeError, 428 | "Array must have %d dimensions. Given array has %d dimensions", 429 | exact_dimensions, 430 | array_numdims(ary)); 431 | success = 0; 432 | } 433 | return success; 434 | } 435 | 436 | /* Require the given PyArrayObject to have one of a list of specified 437 | * number of dimensions. If the array has one of the specified number 438 | * of dimensions, return 1. Otherwise, set the python error string 439 | * and return 0. 440 | */ 441 | int require_dimensions_n(PyArrayObject* ary, 442 | int* exact_dimensions, 443 | int n) 444 | { 445 | int success = 0; 446 | int i; 447 | char dims_str[255] = ""; 448 | char s[255]; 449 | for (i = 0; i < n && !success; i++) 450 | { 451 | if (array_numdims(ary) == exact_dimensions[i]) 452 | { 453 | success = 1; 454 | } 455 | } 456 | if (!success) 457 | { 458 | for (i = 0; i < n-1; i++) 459 | { 460 | sprintf(s, "%d, ", exact_dimensions[i]); 461 | strcat(dims_str,s); 462 | } 463 | sprintf(s, " or %d", exact_dimensions[n-1]); 464 | strcat(dims_str,s); 465 | PyErr_Format(PyExc_TypeError, 466 | "Array must have %s dimensions. Given array has %d dimensions", 467 | dims_str, 468 | array_numdims(ary)); 469 | } 470 | return success; 471 | } 472 | 473 | /* Require the given PyArrayObject to have a specified shape. If the 474 | * array has the specified shape, return 1. Otherwise, set the python 475 | * error string and return 0. 476 | */ 477 | int require_size(PyArrayObject* ary, 478 | npy_intp* size, 479 | int n) 480 | { 481 | int i; 482 | int success = 1; 483 | size_t len; 484 | char desired_dims[255] = "["; 485 | char s[255]; 486 | char actual_dims[255] = "["; 487 | for(i=0; i < n;i++) 488 | { 489 | if (size[i] != -1 && size[i] != array_size(ary,i)) 490 | { 491 | success = 0; 492 | } 493 | } 494 | if (!success) 495 | { 496 | for (i = 0; i < n; i++) 497 | { 498 | if (size[i] == -1) 499 | { 500 | sprintf(s, "*,"); 501 | } 502 | else 503 | { 504 | sprintf(s, "%ld,", (long int)size[i]); 505 | } 506 | strcat(desired_dims,s); 507 | } 508 | len = strlen(desired_dims); 509 | desired_dims[len-1] = ']'; 510 | for (i = 0; i < n; i++) 511 | { 512 | sprintf(s, "%ld,", (long int)array_size(ary,i)); 513 | strcat(actual_dims,s); 514 | } 515 | len = strlen(actual_dims); 516 | actual_dims[len-1] = ']'; 517 | PyErr_Format(PyExc_TypeError, 518 | "Array must have shape of %s. Given array has shape of %s", 519 | desired_dims, 520 | actual_dims); 521 | } 522 | return success; 523 | } 524 | 525 | /* Require the given PyArrayObject to be Fortran ordered. If the 526 | * the PyArrayObject is already Fortran ordered, do nothing. Else, 527 | * set the Fortran ordering flag and recompute the strides. 528 | */ 529 | int require_fortran(PyArrayObject* ary) 530 | { 531 | int success = 1; 532 | int nd = array_numdims(ary); 533 | int i; 534 | npy_intp * strides = array_strides(ary); 535 | if (array_is_fortran(ary)) return success; 536 | int n_non_one = 0; 537 | /* Set the Fortran ordered flag */ 538 | const npy_intp *dims = array_dimensions(ary); 539 | for (i=0; i < nd; ++i) 540 | n_non_one += (dims[i] != 1) ? 1 : 0; 541 | if (n_non_one > 1) 542 | array_clearflags(ary,NPY_ARRAY_CARRAY); 543 | array_enableflags(ary,NPY_ARRAY_FARRAY); 544 | /* Recompute the strides */ 545 | strides[0] = strides[nd-1]; 546 | for (i=1; i < nd; ++i) 547 | strides[i] = strides[i-1] * array_size(ary,i-1); 548 | return success; 549 | } 550 | } 551 | 552 | /* Combine all NumPy fragments into one for convenience */ 553 | %fragment("NumPy_Fragments", 554 | "header", 555 | fragment="NumPy_Backward_Compatibility", 556 | fragment="NumPy_Macros", 557 | fragment="NumPy_Utilities", 558 | fragment="NumPy_Object_to_Array", 559 | fragment="NumPy_Array_Requirements") 560 | { 561 | } 562 | 563 | /* End John Hunter translation (with modifications by Bill Spotz) 564 | */ 565 | 566 | /* %numpy_typemaps() macro 567 | * 568 | * This macro defines a family of 75 typemaps that allow C arguments 569 | * of the form 570 | * 571 | * 1. (DATA_TYPE IN_ARRAY1[ANY]) 572 | * 2. (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) 573 | * 3. (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) 574 | * 575 | * 4. (DATA_TYPE IN_ARRAY2[ANY][ANY]) 576 | * 5. (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 577 | * 6. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) 578 | * 7. (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 579 | * 8. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) 580 | * 581 | * 9. (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) 582 | * 10. (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 583 | * 11. (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 584 | * 12. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) 585 | * 13. (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 586 | * 14. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) 587 | * 588 | * 15. (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) 589 | * 16. (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 590 | * 17. (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 591 | * 18. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) 592 | * 19. (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 593 | * 20. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) 594 | * 595 | * 21. (DATA_TYPE INPLACE_ARRAY1[ANY]) 596 | * 22. (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) 597 | * 23. (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) 598 | * 599 | * 24. (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) 600 | * 25. (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 601 | * 26. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) 602 | * 27. (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 603 | * 28. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) 604 | * 605 | * 29. (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) 606 | * 30. (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 607 | * 31. (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 608 | * 32. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) 609 | * 33. (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 610 | * 34. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) 611 | * 612 | * 35. (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) 613 | * 36. (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 614 | * 37. (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 615 | * 38. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) 616 | * 39. (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 617 | * 40. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) 618 | * 619 | * 41. (DATA_TYPE ARGOUT_ARRAY1[ANY]) 620 | * 42. (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) 621 | * 43. (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) 622 | * 623 | * 44. (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) 624 | * 625 | * 45. (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) 626 | * 627 | * 46. (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) 628 | * 629 | * 47. (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) 630 | * 48. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) 631 | * 632 | * 49. (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 633 | * 50. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) 634 | * 51. (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 635 | * 52. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) 636 | * 637 | * 53. (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) 638 | * 54. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) 639 | * 55. (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) 640 | * 56. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) 641 | * 642 | * 57. (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) 643 | * 58. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) 644 | * 59. (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) 645 | * 60. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) 646 | * 647 | * 61. (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) 648 | * 62. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) 649 | * 650 | * 63. (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 651 | * 64. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) 652 | * 65. (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 653 | * 66. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) 654 | * 655 | * 67. (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) 656 | * 68. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) 657 | * 69. (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) 658 | * 70. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) 659 | * 660 | * 71. (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) 661 | * 72. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) 662 | * 73. (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) 663 | * 74. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) 664 | * 665 | * 75. (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) 666 | * 667 | * where "DATA_TYPE" is any type supported by the NumPy module, and 668 | * "DIM_TYPE" is any int-like type suitable for specifying dimensions. 669 | * The difference between "ARRAY" typemaps and "FARRAY" typemaps is 670 | * that the "FARRAY" typemaps expect Fortran ordering of 671 | * multidimensional arrays. In python, the dimensions will not need 672 | * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1" 673 | * typemaps). The IN_ARRAYs can be a numpy array or any sequence that 674 | * can be converted to a numpy array of the specified type. The 675 | * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The 676 | * ARGOUT_ARRAYs will be returned as new numpy arrays of the 677 | * appropriate type. 678 | * 679 | * These typemaps can be applied to existing functions using the 680 | * %apply directive. For example: 681 | * 682 | * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)}; 683 | * double prod(double* series, int length); 684 | * 685 | * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) 686 | * {(int rows, int cols, double* matrix )}; 687 | * void floor(int rows, int cols, double* matrix, double f); 688 | * 689 | * %apply (double IN_ARRAY3[ANY][ANY][ANY]) 690 | * {(double tensor[2][2][2] )}; 691 | * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) 692 | * {(double low[2][2][2] )}; 693 | * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) 694 | * {(double upp[2][2][2] )}; 695 | * void luSplit(double tensor[2][2][2], 696 | * double low[2][2][2], 697 | * double upp[2][2][2] ); 698 | * 699 | * or directly with 700 | * 701 | * double prod(double* IN_ARRAY1, int DIM1); 702 | * 703 | * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f); 704 | * 705 | * void luSplit(double IN_ARRAY3[ANY][ANY][ANY], 706 | * double ARGOUT_ARRAY3[ANY][ANY][ANY], 707 | * double ARGOUT_ARRAY3[ANY][ANY][ANY]); 708 | */ 709 | 710 | %define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) 711 | 712 | /************************/ 713 | /* Input Array Typemaps */ 714 | /************************/ 715 | 716 | /* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY]) 717 | */ 718 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 719 | fragment="NumPy_Macros") 720 | (DATA_TYPE IN_ARRAY1[ANY]) 721 | { 722 | $1 = is_array($input) || PySequence_Check($input); 723 | } 724 | %typemap(in, 725 | fragment="NumPy_Fragments") 726 | (DATA_TYPE IN_ARRAY1[ANY]) 727 | (PyArrayObject* array=NULL, int is_new_object=0) 728 | { 729 | npy_intp size[1] = { $1_dim0 }; 730 | array = obj_to_array_contiguous_allow_conversion($input, 731 | DATA_TYPECODE, 732 | &is_new_object); 733 | if (!array || !require_dimensions(array, 1) || 734 | !require_size(array, size, 1)) SWIG_fail; 735 | $1 = ($1_ltype) array_data(array); 736 | } 737 | %typemap(freearg) 738 | (DATA_TYPE IN_ARRAY1[ANY]) 739 | { 740 | if (is_new_object$argnum && array$argnum) 741 | { Py_DECREF(array$argnum); } 742 | } 743 | 744 | /* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) 745 | */ 746 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 747 | fragment="NumPy_Macros") 748 | (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) 749 | { 750 | $1 = is_array($input) || PySequence_Check($input); 751 | } 752 | %typemap(in, 753 | fragment="NumPy_Fragments") 754 | (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) 755 | (PyArrayObject* array=NULL, int is_new_object=0) 756 | { 757 | npy_intp size[1] = { -1 }; 758 | array = obj_to_array_contiguous_allow_conversion($input, 759 | DATA_TYPECODE, 760 | &is_new_object); 761 | if (!array || !require_dimensions(array, 1) || 762 | !require_size(array, size, 1)) SWIG_fail; 763 | $1 = (DATA_TYPE*) array_data(array); 764 | $2 = (DIM_TYPE) array_size(array,0); 765 | } 766 | %typemap(freearg) 767 | (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) 768 | { 769 | if (is_new_object$argnum && array$argnum) 770 | { Py_DECREF(array$argnum); } 771 | } 772 | 773 | /* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) 774 | */ 775 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 776 | fragment="NumPy_Macros") 777 | (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) 778 | { 779 | $1 = is_array($input) || PySequence_Check($input); 780 | } 781 | %typemap(in, 782 | fragment="NumPy_Fragments") 783 | (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) 784 | (PyArrayObject* array=NULL, int is_new_object=0) 785 | { 786 | npy_intp size[1] = {-1}; 787 | array = obj_to_array_contiguous_allow_conversion($input, 788 | DATA_TYPECODE, 789 | &is_new_object); 790 | if (!array || !require_dimensions(array, 1) || 791 | !require_size(array, size, 1)) SWIG_fail; 792 | $1 = (DIM_TYPE) array_size(array,0); 793 | $2 = (DATA_TYPE*) array_data(array); 794 | } 795 | %typemap(freearg) 796 | (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) 797 | { 798 | if (is_new_object$argnum && array$argnum) 799 | { Py_DECREF(array$argnum); } 800 | } 801 | 802 | /* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY]) 803 | */ 804 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 805 | fragment="NumPy_Macros") 806 | (DATA_TYPE IN_ARRAY2[ANY][ANY]) 807 | { 808 | $1 = is_array($input) || PySequence_Check($input); 809 | } 810 | %typemap(in, 811 | fragment="NumPy_Fragments") 812 | (DATA_TYPE IN_ARRAY2[ANY][ANY]) 813 | (PyArrayObject* array=NULL, int is_new_object=0) 814 | { 815 | npy_intp size[2] = { $1_dim0, $1_dim1 }; 816 | array = obj_to_array_contiguous_allow_conversion($input, 817 | DATA_TYPECODE, 818 | &is_new_object); 819 | if (!array || !require_dimensions(array, 2) || 820 | !require_size(array, size, 2)) SWIG_fail; 821 | $1 = ($1_ltype) array_data(array); 822 | } 823 | %typemap(freearg) 824 | (DATA_TYPE IN_ARRAY2[ANY][ANY]) 825 | { 826 | if (is_new_object$argnum && array$argnum) 827 | { Py_DECREF(array$argnum); } 828 | } 829 | 830 | /* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 831 | */ 832 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 833 | fragment="NumPy_Macros") 834 | (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 835 | { 836 | $1 = is_array($input) || PySequence_Check($input); 837 | } 838 | %typemap(in, 839 | fragment="NumPy_Fragments") 840 | (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 841 | (PyArrayObject* array=NULL, int is_new_object=0) 842 | { 843 | npy_intp size[2] = { -1, -1 }; 844 | array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, 845 | &is_new_object); 846 | if (!array || !require_dimensions(array, 2) || 847 | !require_size(array, size, 2)) SWIG_fail; 848 | $1 = (DATA_TYPE*) array_data(array); 849 | $2 = (DIM_TYPE) array_size(array,0); 850 | $3 = (DIM_TYPE) array_size(array,1); 851 | } 852 | %typemap(freearg) 853 | (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 854 | { 855 | if (is_new_object$argnum && array$argnum) 856 | { Py_DECREF(array$argnum); } 857 | } 858 | 859 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) 860 | */ 861 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 862 | fragment="NumPy_Macros") 863 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) 864 | { 865 | $1 = is_array($input) || PySequence_Check($input); 866 | } 867 | %typemap(in, 868 | fragment="NumPy_Fragments") 869 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) 870 | (PyArrayObject* array=NULL, int is_new_object=0) 871 | { 872 | npy_intp size[2] = { -1, -1 }; 873 | array = obj_to_array_contiguous_allow_conversion($input, 874 | DATA_TYPECODE, 875 | &is_new_object); 876 | if (!array || !require_dimensions(array, 2) || 877 | !require_size(array, size, 2)) SWIG_fail; 878 | $1 = (DIM_TYPE) array_size(array,0); 879 | $2 = (DIM_TYPE) array_size(array,1); 880 | $3 = (DATA_TYPE*) array_data(array); 881 | } 882 | %typemap(freearg) 883 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) 884 | { 885 | if (is_new_object$argnum && array$argnum) 886 | { Py_DECREF(array$argnum); } 887 | } 888 | 889 | /* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 890 | */ 891 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 892 | fragment="NumPy_Macros") 893 | (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 894 | { 895 | $1 = is_array($input) || PySequence_Check($input); 896 | } 897 | %typemap(in, 898 | fragment="NumPy_Fragments") 899 | (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 900 | (PyArrayObject* array=NULL, int is_new_object=0) 901 | { 902 | npy_intp size[2] = { -1, -1 }; 903 | array = obj_to_array_fortran_allow_conversion($input, 904 | DATA_TYPECODE, 905 | &is_new_object); 906 | if (!array || !require_dimensions(array, 2) || 907 | !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; 908 | $1 = (DATA_TYPE*) array_data(array); 909 | $2 = (DIM_TYPE) array_size(array,0); 910 | $3 = (DIM_TYPE) array_size(array,1); 911 | } 912 | %typemap(freearg) 913 | (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 914 | { 915 | if (is_new_object$argnum && array$argnum) 916 | { Py_DECREF(array$argnum); } 917 | } 918 | 919 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) 920 | */ 921 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 922 | fragment="NumPy_Macros") 923 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) 924 | { 925 | $1 = is_array($input) || PySequence_Check($input); 926 | } 927 | %typemap(in, 928 | fragment="NumPy_Fragments") 929 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) 930 | (PyArrayObject* array=NULL, int is_new_object=0) 931 | { 932 | npy_intp size[2] = { -1, -1 }; 933 | array = obj_to_array_fortran_allow_conversion($input, 934 | DATA_TYPECODE, 935 | &is_new_object); 936 | if (!array || !require_dimensions(array, 2) || 937 | !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; 938 | $1 = (DIM_TYPE) array_size(array,0); 939 | $2 = (DIM_TYPE) array_size(array,1); 940 | $3 = (DATA_TYPE*) array_data(array); 941 | } 942 | %typemap(freearg) 943 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) 944 | { 945 | if (is_new_object$argnum && array$argnum) 946 | { Py_DECREF(array$argnum); } 947 | } 948 | 949 | /* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) 950 | */ 951 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 952 | fragment="NumPy_Macros") 953 | (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) 954 | { 955 | $1 = is_array($input) || PySequence_Check($input); 956 | } 957 | %typemap(in, 958 | fragment="NumPy_Fragments") 959 | (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) 960 | (PyArrayObject* array=NULL, int is_new_object=0) 961 | { 962 | npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; 963 | array = obj_to_array_contiguous_allow_conversion($input, 964 | DATA_TYPECODE, 965 | &is_new_object); 966 | if (!array || !require_dimensions(array, 3) || 967 | !require_size(array, size, 3)) SWIG_fail; 968 | $1 = ($1_ltype) array_data(array); 969 | } 970 | %typemap(freearg) 971 | (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) 972 | { 973 | if (is_new_object$argnum && array$argnum) 974 | { Py_DECREF(array$argnum); } 975 | } 976 | 977 | /* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, 978 | * DIM_TYPE DIM3) 979 | */ 980 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 981 | fragment="NumPy_Macros") 982 | (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 983 | { 984 | $1 = is_array($input) || PySequence_Check($input); 985 | } 986 | %typemap(in, 987 | fragment="NumPy_Fragments") 988 | (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 989 | (PyArrayObject* array=NULL, int is_new_object=0) 990 | { 991 | npy_intp size[3] = { -1, -1, -1 }; 992 | array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, 993 | &is_new_object); 994 | if (!array || !require_dimensions(array, 3) || 995 | !require_size(array, size, 3)) SWIG_fail; 996 | $1 = (DATA_TYPE*) array_data(array); 997 | $2 = (DIM_TYPE) array_size(array,0); 998 | $3 = (DIM_TYPE) array_size(array,1); 999 | $4 = (DIM_TYPE) array_size(array,2); 1000 | } 1001 | %typemap(freearg) 1002 | (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1003 | { 1004 | if (is_new_object$argnum && array$argnum) 1005 | { Py_DECREF(array$argnum); } 1006 | } 1007 | 1008 | /* Typemap suite for (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, 1009 | * DIM_TYPE DIM3) 1010 | */ 1011 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1012 | fragment="NumPy_Macros") 1013 | (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1014 | { 1015 | /* for now, only concerned with lists */ 1016 | $1 = PySequence_Check($input); 1017 | } 1018 | %typemap(in, 1019 | fragment="NumPy_Fragments") 1020 | (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1021 | (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) 1022 | { 1023 | npy_intp size[2] = { -1, -1 }; 1024 | PyArrayObject* temp_array; 1025 | Py_ssize_t i; 1026 | int is_new_object; 1027 | 1028 | /* length of the list */ 1029 | $2 = PyList_Size($input); 1030 | 1031 | /* the arrays */ 1032 | array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); 1033 | object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); 1034 | is_new_object_array = (int *)calloc($2,sizeof(int)); 1035 | 1036 | if (array == NULL || object_array == NULL || is_new_object_array == NULL) 1037 | { 1038 | SWIG_fail; 1039 | } 1040 | 1041 | for (i=0; i<$2; i++) 1042 | { 1043 | temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); 1044 | 1045 | /* the new array must be stored so that it can be destroyed in freearg */ 1046 | object_array[i] = temp_array; 1047 | is_new_object_array[i] = is_new_object; 1048 | 1049 | if (!temp_array || !require_dimensions(temp_array, 2)) SWIG_fail; 1050 | 1051 | /* store the size of the first array in the list, then use that for comparison. */ 1052 | if (i == 0) 1053 | { 1054 | size[0] = array_size(temp_array,0); 1055 | size[1] = array_size(temp_array,1); 1056 | } 1057 | 1058 | if (!require_size(temp_array, size, 2)) SWIG_fail; 1059 | 1060 | array[i] = (DATA_TYPE*) array_data(temp_array); 1061 | } 1062 | 1063 | $1 = (DATA_TYPE**) array; 1064 | $3 = (DIM_TYPE) size[0]; 1065 | $4 = (DIM_TYPE) size[1]; 1066 | } 1067 | %typemap(freearg) 1068 | (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1069 | { 1070 | Py_ssize_t i; 1071 | 1072 | if (array$argnum!=NULL) free(array$argnum); 1073 | 1074 | /*freeing the individual arrays if needed */ 1075 | if (object_array$argnum!=NULL) 1076 | { 1077 | if (is_new_object_array$argnum!=NULL) 1078 | { 1079 | for (i=0; i<$2; i++) 1080 | { 1081 | if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) 1082 | { Py_DECREF(object_array$argnum[i]); } 1083 | } 1084 | free(is_new_object_array$argnum); 1085 | } 1086 | free(object_array$argnum); 1087 | } 1088 | } 1089 | 1090 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, 1091 | * DATA_TYPE* IN_ARRAY3) 1092 | */ 1093 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1094 | fragment="NumPy_Macros") 1095 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) 1096 | { 1097 | $1 = is_array($input) || PySequence_Check($input); 1098 | } 1099 | %typemap(in, 1100 | fragment="NumPy_Fragments") 1101 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) 1102 | (PyArrayObject* array=NULL, int is_new_object=0) 1103 | { 1104 | npy_intp size[3] = { -1, -1, -1 }; 1105 | array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, 1106 | &is_new_object); 1107 | if (!array || !require_dimensions(array, 3) || 1108 | !require_size(array, size, 3)) SWIG_fail; 1109 | $1 = (DIM_TYPE) array_size(array,0); 1110 | $2 = (DIM_TYPE) array_size(array,1); 1111 | $3 = (DIM_TYPE) array_size(array,2); 1112 | $4 = (DATA_TYPE*) array_data(array); 1113 | } 1114 | %typemap(freearg) 1115 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) 1116 | { 1117 | if (is_new_object$argnum && array$argnum) 1118 | { Py_DECREF(array$argnum); } 1119 | } 1120 | 1121 | /* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, 1122 | * DIM_TYPE DIM3) 1123 | */ 1124 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1125 | fragment="NumPy_Macros") 1126 | (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1127 | { 1128 | $1 = is_array($input) || PySequence_Check($input); 1129 | } 1130 | %typemap(in, 1131 | fragment="NumPy_Fragments") 1132 | (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1133 | (PyArrayObject* array=NULL, int is_new_object=0) 1134 | { 1135 | npy_intp size[3] = { -1, -1, -1 }; 1136 | array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, 1137 | &is_new_object); 1138 | if (!array || !require_dimensions(array, 3) || 1139 | !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; 1140 | $1 = (DATA_TYPE*) array_data(array); 1141 | $2 = (DIM_TYPE) array_size(array,0); 1142 | $3 = (DIM_TYPE) array_size(array,1); 1143 | $4 = (DIM_TYPE) array_size(array,2); 1144 | } 1145 | %typemap(freearg) 1146 | (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1147 | { 1148 | if (is_new_object$argnum && array$argnum) 1149 | { Py_DECREF(array$argnum); } 1150 | } 1151 | 1152 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, 1153 | * DATA_TYPE* IN_FARRAY3) 1154 | */ 1155 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1156 | fragment="NumPy_Macros") 1157 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) 1158 | { 1159 | $1 = is_array($input) || PySequence_Check($input); 1160 | } 1161 | %typemap(in, 1162 | fragment="NumPy_Fragments") 1163 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) 1164 | (PyArrayObject* array=NULL, int is_new_object=0) 1165 | { 1166 | npy_intp size[3] = { -1, -1, -1 }; 1167 | array = obj_to_array_fortran_allow_conversion($input, 1168 | DATA_TYPECODE, 1169 | &is_new_object); 1170 | if (!array || !require_dimensions(array, 3) || 1171 | !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; 1172 | $1 = (DIM_TYPE) array_size(array,0); 1173 | $2 = (DIM_TYPE) array_size(array,1); 1174 | $3 = (DIM_TYPE) array_size(array,2); 1175 | $4 = (DATA_TYPE*) array_data(array); 1176 | } 1177 | %typemap(freearg) 1178 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) 1179 | { 1180 | if (is_new_object$argnum && array$argnum) 1181 | { Py_DECREF(array$argnum); } 1182 | } 1183 | 1184 | /* Typemap suite for (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) 1185 | */ 1186 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1187 | fragment="NumPy_Macros") 1188 | (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) 1189 | { 1190 | $1 = is_array($input) || PySequence_Check($input); 1191 | } 1192 | %typemap(in, 1193 | fragment="NumPy_Fragments") 1194 | (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) 1195 | (PyArrayObject* array=NULL, int is_new_object=0) 1196 | { 1197 | npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3}; 1198 | array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, 1199 | &is_new_object); 1200 | if (!array || !require_dimensions(array, 4) || 1201 | !require_size(array, size, 4)) SWIG_fail; 1202 | $1 = ($1_ltype) array_data(array); 1203 | } 1204 | %typemap(freearg) 1205 | (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) 1206 | { 1207 | if (is_new_object$argnum && array$argnum) 1208 | { Py_DECREF(array$argnum); } 1209 | } 1210 | 1211 | /* Typemap suite for (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, 1212 | * DIM_TYPE DIM3, DIM_TYPE DIM4) 1213 | */ 1214 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1215 | fragment="NumPy_Macros") 1216 | (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1217 | { 1218 | $1 = is_array($input) || PySequence_Check($input); 1219 | } 1220 | %typemap(in, 1221 | fragment="NumPy_Fragments") 1222 | (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1223 | (PyArrayObject* array=NULL, int is_new_object=0) 1224 | { 1225 | npy_intp size[4] = { -1, -1, -1, -1 }; 1226 | array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, 1227 | &is_new_object); 1228 | if (!array || !require_dimensions(array, 4) || 1229 | !require_size(array, size, 4)) SWIG_fail; 1230 | $1 = (DATA_TYPE*) array_data(array); 1231 | $2 = (DIM_TYPE) array_size(array,0); 1232 | $3 = (DIM_TYPE) array_size(array,1); 1233 | $4 = (DIM_TYPE) array_size(array,2); 1234 | $5 = (DIM_TYPE) array_size(array,3); 1235 | } 1236 | %typemap(freearg) 1237 | (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1238 | { 1239 | if (is_new_object$argnum && array$argnum) 1240 | { Py_DECREF(array$argnum); } 1241 | } 1242 | 1243 | /* Typemap suite for (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, 1244 | * DIM_TYPE DIM3, DIM_TYPE DIM4) 1245 | */ 1246 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1247 | fragment="NumPy_Macros") 1248 | (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1249 | { 1250 | /* for now, only concerned with lists */ 1251 | $1 = PySequence_Check($input); 1252 | } 1253 | %typemap(in, 1254 | fragment="NumPy_Fragments") 1255 | (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1256 | (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) 1257 | { 1258 | npy_intp size[3] = { -1, -1, -1 }; 1259 | PyArrayObject* temp_array; 1260 | Py_ssize_t i; 1261 | int is_new_object; 1262 | 1263 | /* length of the list */ 1264 | $2 = PyList_Size($input); 1265 | 1266 | /* the arrays */ 1267 | array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); 1268 | object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); 1269 | is_new_object_array = (int *)calloc($2,sizeof(int)); 1270 | 1271 | if (array == NULL || object_array == NULL || is_new_object_array == NULL) 1272 | { 1273 | SWIG_fail; 1274 | } 1275 | 1276 | for (i=0; i<$2; i++) 1277 | { 1278 | temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); 1279 | 1280 | /* the new array must be stored so that it can be destroyed in freearg */ 1281 | object_array[i] = temp_array; 1282 | is_new_object_array[i] = is_new_object; 1283 | 1284 | if (!temp_array || !require_dimensions(temp_array, 3)) SWIG_fail; 1285 | 1286 | /* store the size of the first array in the list, then use that for comparison. */ 1287 | if (i == 0) 1288 | { 1289 | size[0] = array_size(temp_array,0); 1290 | size[1] = array_size(temp_array,1); 1291 | size[2] = array_size(temp_array,2); 1292 | } 1293 | 1294 | if (!require_size(temp_array, size, 3)) SWIG_fail; 1295 | 1296 | array[i] = (DATA_TYPE*) array_data(temp_array); 1297 | } 1298 | 1299 | $1 = (DATA_TYPE**) array; 1300 | $3 = (DIM_TYPE) size[0]; 1301 | $4 = (DIM_TYPE) size[1]; 1302 | $5 = (DIM_TYPE) size[2]; 1303 | } 1304 | %typemap(freearg) 1305 | (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1306 | { 1307 | Py_ssize_t i; 1308 | 1309 | if (array$argnum!=NULL) free(array$argnum); 1310 | 1311 | /*freeing the individual arrays if needed */ 1312 | if (object_array$argnum!=NULL) 1313 | { 1314 | if (is_new_object_array$argnum!=NULL) 1315 | { 1316 | for (i=0; i<$2; i++) 1317 | { 1318 | if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) 1319 | { Py_DECREF(object_array$argnum[i]); } 1320 | } 1321 | free(is_new_object_array$argnum); 1322 | } 1323 | free(object_array$argnum); 1324 | } 1325 | } 1326 | 1327 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, 1328 | * DATA_TYPE* IN_ARRAY4) 1329 | */ 1330 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1331 | fragment="NumPy_Macros") 1332 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) 1333 | { 1334 | $1 = is_array($input) || PySequence_Check($input); 1335 | } 1336 | %typemap(in, 1337 | fragment="NumPy_Fragments") 1338 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) 1339 | (PyArrayObject* array=NULL, int is_new_object=0) 1340 | { 1341 | npy_intp size[4] = { -1, -1, -1 , -1}; 1342 | array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, 1343 | &is_new_object); 1344 | if (!array || !require_dimensions(array, 4) || 1345 | !require_size(array, size, 4)) SWIG_fail; 1346 | $1 = (DIM_TYPE) array_size(array,0); 1347 | $2 = (DIM_TYPE) array_size(array,1); 1348 | $3 = (DIM_TYPE) array_size(array,2); 1349 | $4 = (DIM_TYPE) array_size(array,3); 1350 | $5 = (DATA_TYPE*) array_data(array); 1351 | } 1352 | %typemap(freearg) 1353 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) 1354 | { 1355 | if (is_new_object$argnum && array$argnum) 1356 | { Py_DECREF(array$argnum); } 1357 | } 1358 | 1359 | /* Typemap suite for (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, 1360 | * DIM_TYPE DIM3, DIM_TYPE DIM4) 1361 | */ 1362 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1363 | fragment="NumPy_Macros") 1364 | (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1365 | { 1366 | $1 = is_array($input) || PySequence_Check($input); 1367 | } 1368 | %typemap(in, 1369 | fragment="NumPy_Fragments") 1370 | (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1371 | (PyArrayObject* array=NULL, int is_new_object=0) 1372 | { 1373 | npy_intp size[4] = { -1, -1, -1, -1 }; 1374 | array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, 1375 | &is_new_object); 1376 | if (!array || !require_dimensions(array, 4) || 1377 | !require_size(array, size, 4) | !require_fortran(array)) SWIG_fail; 1378 | $1 = (DATA_TYPE*) array_data(array); 1379 | $2 = (DIM_TYPE) array_size(array,0); 1380 | $3 = (DIM_TYPE) array_size(array,1); 1381 | $4 = (DIM_TYPE) array_size(array,2); 1382 | $5 = (DIM_TYPE) array_size(array,3); 1383 | } 1384 | %typemap(freearg) 1385 | (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1386 | { 1387 | if (is_new_object$argnum && array$argnum) 1388 | { Py_DECREF(array$argnum); } 1389 | } 1390 | 1391 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, 1392 | * DATA_TYPE* IN_FARRAY4) 1393 | */ 1394 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1395 | fragment="NumPy_Macros") 1396 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) 1397 | { 1398 | $1 = is_array($input) || PySequence_Check($input); 1399 | } 1400 | %typemap(in, 1401 | fragment="NumPy_Fragments") 1402 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) 1403 | (PyArrayObject* array=NULL, int is_new_object=0) 1404 | { 1405 | npy_intp size[4] = { -1, -1, -1 , -1 }; 1406 | array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, 1407 | &is_new_object); 1408 | if (!array || !require_dimensions(array, 4) || 1409 | !require_size(array, size, 4) || !require_fortran(array)) SWIG_fail; 1410 | $1 = (DIM_TYPE) array_size(array,0); 1411 | $2 = (DIM_TYPE) array_size(array,1); 1412 | $3 = (DIM_TYPE) array_size(array,2); 1413 | $4 = (DIM_TYPE) array_size(array,3); 1414 | $5 = (DATA_TYPE*) array_data(array); 1415 | } 1416 | %typemap(freearg) 1417 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) 1418 | { 1419 | if (is_new_object$argnum && array$argnum) 1420 | { Py_DECREF(array$argnum); } 1421 | } 1422 | 1423 | /***************************/ 1424 | /* In-Place Array Typemaps */ 1425 | /***************************/ 1426 | 1427 | /* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY]) 1428 | */ 1429 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1430 | fragment="NumPy_Macros") 1431 | (DATA_TYPE INPLACE_ARRAY1[ANY]) 1432 | { 1433 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1434 | DATA_TYPECODE); 1435 | } 1436 | %typemap(in, 1437 | fragment="NumPy_Fragments") 1438 | (DATA_TYPE INPLACE_ARRAY1[ANY]) 1439 | (PyArrayObject* array=NULL) 1440 | { 1441 | npy_intp size[1] = { $1_dim0 }; 1442 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1443 | if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) || 1444 | !require_contiguous(array) || !require_native(array)) SWIG_fail; 1445 | $1 = ($1_ltype) array_data(array); 1446 | } 1447 | 1448 | /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) 1449 | */ 1450 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1451 | fragment="NumPy_Macros") 1452 | (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) 1453 | { 1454 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1455 | DATA_TYPECODE); 1456 | } 1457 | %typemap(in, 1458 | fragment="NumPy_Fragments") 1459 | (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) 1460 | (PyArrayObject* array=NULL, int i=1) 1461 | { 1462 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1463 | if (!array || !require_dimensions(array,1) || !require_contiguous(array) 1464 | || !require_native(array)) SWIG_fail; 1465 | $1 = (DATA_TYPE*) array_data(array); 1466 | $2 = 1; 1467 | for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); 1468 | } 1469 | 1470 | /* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) 1471 | */ 1472 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1473 | fragment="NumPy_Macros") 1474 | (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) 1475 | { 1476 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1477 | DATA_TYPECODE); 1478 | } 1479 | %typemap(in, 1480 | fragment="NumPy_Fragments") 1481 | (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) 1482 | (PyArrayObject* array=NULL, int i=0) 1483 | { 1484 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1485 | if (!array || !require_dimensions(array,1) || !require_contiguous(array) 1486 | || !require_native(array)) SWIG_fail; 1487 | $1 = 1; 1488 | for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i); 1489 | $2 = (DATA_TYPE*) array_data(array); 1490 | } 1491 | 1492 | /* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) 1493 | */ 1494 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1495 | fragment="NumPy_Macros") 1496 | (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) 1497 | { 1498 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1499 | DATA_TYPECODE); 1500 | } 1501 | %typemap(in, 1502 | fragment="NumPy_Fragments") 1503 | (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) 1504 | (PyArrayObject* array=NULL) 1505 | { 1506 | npy_intp size[2] = { $1_dim0, $1_dim1 }; 1507 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1508 | if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) || 1509 | !require_contiguous(array) || !require_native(array)) SWIG_fail; 1510 | $1 = ($1_ltype) array_data(array); 1511 | } 1512 | 1513 | /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 1514 | */ 1515 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1516 | fragment="NumPy_Macros") 1517 | (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 1518 | { 1519 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1520 | DATA_TYPECODE); 1521 | } 1522 | %typemap(in, 1523 | fragment="NumPy_Fragments") 1524 | (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 1525 | (PyArrayObject* array=NULL) 1526 | { 1527 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1528 | if (!array || !require_dimensions(array,2) || !require_contiguous(array) 1529 | || !require_native(array)) SWIG_fail; 1530 | $1 = (DATA_TYPE*) array_data(array); 1531 | $2 = (DIM_TYPE) array_size(array,0); 1532 | $3 = (DIM_TYPE) array_size(array,1); 1533 | } 1534 | 1535 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) 1536 | */ 1537 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1538 | fragment="NumPy_Macros") 1539 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) 1540 | { 1541 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1542 | DATA_TYPECODE); 1543 | } 1544 | %typemap(in, 1545 | fragment="NumPy_Fragments") 1546 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) 1547 | (PyArrayObject* array=NULL) 1548 | { 1549 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1550 | if (!array || !require_dimensions(array,2) || !require_contiguous(array) || 1551 | !require_native(array)) SWIG_fail; 1552 | $1 = (DIM_TYPE) array_size(array,0); 1553 | $2 = (DIM_TYPE) array_size(array,1); 1554 | $3 = (DATA_TYPE*) array_data(array); 1555 | } 1556 | 1557 | /* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 1558 | */ 1559 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1560 | fragment="NumPy_Macros") 1561 | (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 1562 | { 1563 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1564 | DATA_TYPECODE); 1565 | } 1566 | %typemap(in, 1567 | fragment="NumPy_Fragments") 1568 | (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) 1569 | (PyArrayObject* array=NULL) 1570 | { 1571 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1572 | if (!array || !require_dimensions(array,2) || !require_contiguous(array) 1573 | || !require_native(array) || !require_fortran(array)) SWIG_fail; 1574 | $1 = (DATA_TYPE*) array_data(array); 1575 | $2 = (DIM_TYPE) array_size(array,0); 1576 | $3 = (DIM_TYPE) array_size(array,1); 1577 | } 1578 | 1579 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) 1580 | */ 1581 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1582 | fragment="NumPy_Macros") 1583 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) 1584 | { 1585 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1586 | DATA_TYPECODE); 1587 | } 1588 | %typemap(in, 1589 | fragment="NumPy_Fragments") 1590 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) 1591 | (PyArrayObject* array=NULL) 1592 | { 1593 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1594 | if (!array || !require_dimensions(array,2) || !require_contiguous(array) || 1595 | !require_native(array) || !require_fortran(array)) SWIG_fail; 1596 | $1 = (DIM_TYPE) array_size(array,0); 1597 | $2 = (DIM_TYPE) array_size(array,1); 1598 | $3 = (DATA_TYPE*) array_data(array); 1599 | } 1600 | 1601 | /* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) 1602 | */ 1603 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1604 | fragment="NumPy_Macros") 1605 | (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) 1606 | { 1607 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1608 | DATA_TYPECODE); 1609 | } 1610 | %typemap(in, 1611 | fragment="NumPy_Fragments") 1612 | (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) 1613 | (PyArrayObject* array=NULL) 1614 | { 1615 | npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; 1616 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1617 | if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) || 1618 | !require_contiguous(array) || !require_native(array)) SWIG_fail; 1619 | $1 = ($1_ltype) array_data(array); 1620 | } 1621 | 1622 | /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, 1623 | * DIM_TYPE DIM3) 1624 | */ 1625 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1626 | fragment="NumPy_Macros") 1627 | (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1628 | { 1629 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1630 | DATA_TYPECODE); 1631 | } 1632 | %typemap(in, 1633 | fragment="NumPy_Fragments") 1634 | (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1635 | (PyArrayObject* array=NULL) 1636 | { 1637 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1638 | if (!array || !require_dimensions(array,3) || !require_contiguous(array) || 1639 | !require_native(array)) SWIG_fail; 1640 | $1 = (DATA_TYPE*) array_data(array); 1641 | $2 = (DIM_TYPE) array_size(array,0); 1642 | $3 = (DIM_TYPE) array_size(array,1); 1643 | $4 = (DIM_TYPE) array_size(array,2); 1644 | } 1645 | 1646 | /* Typemap suite for (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, 1647 | * DIM_TYPE DIM3) 1648 | */ 1649 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1650 | fragment="NumPy_Macros") 1651 | (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1652 | { 1653 | $1 = PySequence_Check($input); 1654 | } 1655 | %typemap(in, 1656 | fragment="NumPy_Fragments") 1657 | (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1658 | (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) 1659 | { 1660 | npy_intp size[2] = { -1, -1 }; 1661 | PyArrayObject* temp_array; 1662 | Py_ssize_t i; 1663 | 1664 | /* length of the list */ 1665 | $2 = PyList_Size($input); 1666 | 1667 | /* the arrays */ 1668 | array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); 1669 | object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); 1670 | 1671 | if (array == NULL || object_array == NULL) 1672 | { 1673 | SWIG_fail; 1674 | } 1675 | 1676 | for (i=0; i<$2; i++) 1677 | { 1678 | temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); 1679 | 1680 | /* the new array must be stored so that it can be destroyed in freearg */ 1681 | object_array[i] = temp_array; 1682 | 1683 | if ( !temp_array || !require_dimensions(temp_array, 2) || 1684 | !require_contiguous(temp_array) || 1685 | !require_native(temp_array) || 1686 | !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) 1687 | ) SWIG_fail; 1688 | 1689 | /* store the size of the first array in the list, then use that for comparison. */ 1690 | if (i == 0) 1691 | { 1692 | size[0] = array_size(temp_array,0); 1693 | size[1] = array_size(temp_array,1); 1694 | } 1695 | 1696 | if (!require_size(temp_array, size, 2)) SWIG_fail; 1697 | 1698 | array[i] = (DATA_TYPE*) array_data(temp_array); 1699 | } 1700 | 1701 | $1 = (DATA_TYPE**) array; 1702 | $3 = (DIM_TYPE) size[0]; 1703 | $4 = (DIM_TYPE) size[1]; 1704 | } 1705 | %typemap(freearg) 1706 | (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1707 | { 1708 | if (array$argnum!=NULL) free(array$argnum); 1709 | if (object_array$argnum!=NULL) free(object_array$argnum); 1710 | } 1711 | 1712 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, 1713 | * DATA_TYPE* INPLACE_ARRAY3) 1714 | */ 1715 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1716 | fragment="NumPy_Macros") 1717 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) 1718 | { 1719 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1720 | DATA_TYPECODE); 1721 | } 1722 | %typemap(in, 1723 | fragment="NumPy_Fragments") 1724 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) 1725 | (PyArrayObject* array=NULL) 1726 | { 1727 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1728 | if (!array || !require_dimensions(array,3) || !require_contiguous(array) 1729 | || !require_native(array)) SWIG_fail; 1730 | $1 = (DIM_TYPE) array_size(array,0); 1731 | $2 = (DIM_TYPE) array_size(array,1); 1732 | $3 = (DIM_TYPE) array_size(array,2); 1733 | $4 = (DATA_TYPE*) array_data(array); 1734 | } 1735 | 1736 | /* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, 1737 | * DIM_TYPE DIM3) 1738 | */ 1739 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1740 | fragment="NumPy_Macros") 1741 | (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1742 | { 1743 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1744 | DATA_TYPECODE); 1745 | } 1746 | %typemap(in, 1747 | fragment="NumPy_Fragments") 1748 | (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) 1749 | (PyArrayObject* array=NULL) 1750 | { 1751 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1752 | if (!array || !require_dimensions(array,3) || !require_contiguous(array) || 1753 | !require_native(array) || !require_fortran(array)) SWIG_fail; 1754 | $1 = (DATA_TYPE*) array_data(array); 1755 | $2 = (DIM_TYPE) array_size(array,0); 1756 | $3 = (DIM_TYPE) array_size(array,1); 1757 | $4 = (DIM_TYPE) array_size(array,2); 1758 | } 1759 | 1760 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, 1761 | * DATA_TYPE* INPLACE_FARRAY3) 1762 | */ 1763 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1764 | fragment="NumPy_Macros") 1765 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) 1766 | { 1767 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1768 | DATA_TYPECODE); 1769 | } 1770 | %typemap(in, 1771 | fragment="NumPy_Fragments") 1772 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) 1773 | (PyArrayObject* array=NULL) 1774 | { 1775 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1776 | if (!array || !require_dimensions(array,3) || !require_contiguous(array) 1777 | || !require_native(array) || !require_fortran(array)) SWIG_fail; 1778 | $1 = (DIM_TYPE) array_size(array,0); 1779 | $2 = (DIM_TYPE) array_size(array,1); 1780 | $3 = (DIM_TYPE) array_size(array,2); 1781 | $4 = (DATA_TYPE*) array_data(array); 1782 | } 1783 | 1784 | /* Typemap suite for (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) 1785 | */ 1786 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1787 | fragment="NumPy_Macros") 1788 | (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) 1789 | { 1790 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1791 | DATA_TYPECODE); 1792 | } 1793 | %typemap(in, 1794 | fragment="NumPy_Fragments") 1795 | (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) 1796 | (PyArrayObject* array=NULL) 1797 | { 1798 | npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3 }; 1799 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1800 | if (!array || !require_dimensions(array,4) || !require_size(array, size, 4) || 1801 | !require_contiguous(array) || !require_native(array)) SWIG_fail; 1802 | $1 = ($1_ltype) array_data(array); 1803 | } 1804 | 1805 | /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, 1806 | * DIM_TYPE DIM3, DIM_TYPE DIM4) 1807 | */ 1808 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1809 | fragment="NumPy_Macros") 1810 | (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1811 | { 1812 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1813 | DATA_TYPECODE); 1814 | } 1815 | %typemap(in, 1816 | fragment="NumPy_Fragments") 1817 | (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1818 | (PyArrayObject* array=NULL) 1819 | { 1820 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1821 | if (!array || !require_dimensions(array,4) || !require_contiguous(array) || 1822 | !require_native(array)) SWIG_fail; 1823 | $1 = (DATA_TYPE*) array_data(array); 1824 | $2 = (DIM_TYPE) array_size(array,0); 1825 | $3 = (DIM_TYPE) array_size(array,1); 1826 | $4 = (DIM_TYPE) array_size(array,2); 1827 | $5 = (DIM_TYPE) array_size(array,3); 1828 | } 1829 | 1830 | /* Typemap suite for (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, 1831 | * DIM_TYPE DIM3, DIM_TYPE DIM4) 1832 | */ 1833 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1834 | fragment="NumPy_Macros") 1835 | (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1836 | { 1837 | $1 = PySequence_Check($input); 1838 | } 1839 | %typemap(in, 1840 | fragment="NumPy_Fragments") 1841 | (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1842 | (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) 1843 | { 1844 | npy_intp size[3] = { -1, -1, -1 }; 1845 | PyArrayObject* temp_array; 1846 | Py_ssize_t i; 1847 | 1848 | /* length of the list */ 1849 | $2 = PyList_Size($input); 1850 | 1851 | /* the arrays */ 1852 | array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); 1853 | object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); 1854 | 1855 | if (array == NULL || object_array == NULL) 1856 | { 1857 | SWIG_fail; 1858 | } 1859 | 1860 | for (i=0; i<$2; i++) 1861 | { 1862 | temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); 1863 | 1864 | /* the new array must be stored so that it can be destroyed in freearg */ 1865 | object_array[i] = temp_array; 1866 | 1867 | if ( !temp_array || !require_dimensions(temp_array, 3) || 1868 | !require_contiguous(temp_array) || 1869 | !require_native(temp_array) || 1870 | !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) 1871 | ) SWIG_fail; 1872 | 1873 | /* store the size of the first array in the list, then use that for comparison. */ 1874 | if (i == 0) 1875 | { 1876 | size[0] = array_size(temp_array,0); 1877 | size[1] = array_size(temp_array,1); 1878 | size[2] = array_size(temp_array,2); 1879 | } 1880 | 1881 | if (!require_size(temp_array, size, 3)) SWIG_fail; 1882 | 1883 | array[i] = (DATA_TYPE*) array_data(temp_array); 1884 | } 1885 | 1886 | $1 = (DATA_TYPE**) array; 1887 | $3 = (DIM_TYPE) size[0]; 1888 | $4 = (DIM_TYPE) size[1]; 1889 | $5 = (DIM_TYPE) size[2]; 1890 | } 1891 | %typemap(freearg) 1892 | (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1893 | { 1894 | if (array$argnum!=NULL) free(array$argnum); 1895 | if (object_array$argnum!=NULL) free(object_array$argnum); 1896 | } 1897 | 1898 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, 1899 | * DATA_TYPE* INPLACE_ARRAY4) 1900 | */ 1901 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1902 | fragment="NumPy_Macros") 1903 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) 1904 | { 1905 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1906 | DATA_TYPECODE); 1907 | } 1908 | %typemap(in, 1909 | fragment="NumPy_Fragments") 1910 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) 1911 | (PyArrayObject* array=NULL) 1912 | { 1913 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1914 | if (!array || !require_dimensions(array,4) || !require_contiguous(array) 1915 | || !require_native(array)) SWIG_fail; 1916 | $1 = (DIM_TYPE) array_size(array,0); 1917 | $2 = (DIM_TYPE) array_size(array,1); 1918 | $3 = (DIM_TYPE) array_size(array,2); 1919 | $4 = (DIM_TYPE) array_size(array,3); 1920 | $5 = (DATA_TYPE*) array_data(array); 1921 | } 1922 | 1923 | /* Typemap suite for (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, 1924 | * DIM_TYPE DIM3, DIM_TYPE DIM4) 1925 | */ 1926 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1927 | fragment="NumPy_Macros") 1928 | (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1929 | { 1930 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1931 | DATA_TYPECODE); 1932 | } 1933 | %typemap(in, 1934 | fragment="NumPy_Fragments") 1935 | (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) 1936 | (PyArrayObject* array=NULL) 1937 | { 1938 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1939 | if (!array || !require_dimensions(array,4) || !require_contiguous(array) || 1940 | !require_native(array) || !require_fortran(array)) SWIG_fail; 1941 | $1 = (DATA_TYPE*) array_data(array); 1942 | $2 = (DIM_TYPE) array_size(array,0); 1943 | $3 = (DIM_TYPE) array_size(array,1); 1944 | $4 = (DIM_TYPE) array_size(array,2); 1945 | $5 = (DIM_TYPE) array_size(array,3); 1946 | } 1947 | 1948 | /* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, 1949 | * DATA_TYPE* INPLACE_FARRAY4) 1950 | */ 1951 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 1952 | fragment="NumPy_Macros") 1953 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) 1954 | { 1955 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 1956 | DATA_TYPECODE); 1957 | } 1958 | %typemap(in, 1959 | fragment="NumPy_Fragments") 1960 | (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) 1961 | (PyArrayObject* array=NULL) 1962 | { 1963 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 1964 | if (!array || !require_dimensions(array,4) || !require_contiguous(array) 1965 | || !require_native(array) || !require_fortran(array)) SWIG_fail; 1966 | $1 = (DIM_TYPE) array_size(array,0); 1967 | $2 = (DIM_TYPE) array_size(array,1); 1968 | $3 = (DIM_TYPE) array_size(array,2); 1969 | $4 = (DIM_TYPE) array_size(array,3); 1970 | $5 = (DATA_TYPE*) array_data(array); 1971 | } 1972 | 1973 | /*************************/ 1974 | /* Argout Array Typemaps */ 1975 | /*************************/ 1976 | 1977 | /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY]) 1978 | */ 1979 | %typemap(in,numinputs=0, 1980 | fragment="NumPy_Backward_Compatibility,NumPy_Macros") 1981 | (DATA_TYPE ARGOUT_ARRAY1[ANY]) 1982 | (PyObject* array = NULL) 1983 | { 1984 | npy_intp dims[1] = { $1_dim0 }; 1985 | array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); 1986 | if (!array) SWIG_fail; 1987 | $1 = ($1_ltype) array_data(array); 1988 | } 1989 | %typemap(argout) 1990 | (DATA_TYPE ARGOUT_ARRAY1[ANY]) 1991 | { 1992 | $result = SWIG_AppendOutput($result,(PyObject*)array$argnum); 1993 | } 1994 | 1995 | /* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) 1996 | */ 1997 | %typemap(in,numinputs=1, 1998 | fragment="NumPy_Fragments") 1999 | (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) 2000 | (PyObject* array = NULL) 2001 | { 2002 | npy_intp dims[1]; 2003 | if (!PyLong_Check($input)) 2004 | { 2005 | const char* typestring = pytype_string($input); 2006 | PyErr_Format(PyExc_TypeError, 2007 | "Int dimension expected. '%s' given.", 2008 | typestring); 2009 | SWIG_fail; 2010 | } 2011 | $2 = (DIM_TYPE) PyLong_AsSsize_t($input); 2012 | if ($2 == -1 && PyErr_Occurred()) SWIG_fail; 2013 | dims[0] = (npy_intp) $2; 2014 | array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); 2015 | if (!array) SWIG_fail; 2016 | $1 = (DATA_TYPE*) array_data(array); 2017 | } 2018 | %typemap(argout) 2019 | (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) 2020 | { 2021 | $result = SWIG_AppendOutput($result,(PyObject*)array$argnum); 2022 | } 2023 | 2024 | /* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) 2025 | */ 2026 | %typemap(in,numinputs=1, 2027 | fragment="NumPy_Fragments") 2028 | (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) 2029 | (PyObject* array = NULL) 2030 | { 2031 | npy_intp dims[1]; 2032 | if (!PyLong_Check($input)) 2033 | { 2034 | const char* typestring = pytype_string($input); 2035 | PyErr_Format(PyExc_TypeError, 2036 | "Int dimension expected. '%s' given.", 2037 | typestring); 2038 | SWIG_fail; 2039 | } 2040 | $1 = (DIM_TYPE) PyLong_AsSsize_t($input); 2041 | if ($1 == -1 && PyErr_Occurred()) SWIG_fail; 2042 | dims[0] = (npy_intp) $1; 2043 | array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); 2044 | if (!array) SWIG_fail; 2045 | $2 = (DATA_TYPE*) array_data(array); 2046 | } 2047 | %typemap(argout) 2048 | (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) 2049 | { 2050 | $result = SWIG_AppendOutput($result,(PyObject*)array$argnum); 2051 | } 2052 | 2053 | /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) 2054 | */ 2055 | %typemap(in,numinputs=0, 2056 | fragment="NumPy_Backward_Compatibility,NumPy_Macros") 2057 | (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) 2058 | (PyObject* array = NULL) 2059 | { 2060 | npy_intp dims[2] = { $1_dim0, $1_dim1 }; 2061 | array = PyArray_SimpleNew(2, dims, DATA_TYPECODE); 2062 | if (!array) SWIG_fail; 2063 | $1 = ($1_ltype) array_data(array); 2064 | } 2065 | %typemap(argout) 2066 | (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) 2067 | { 2068 | $result = SWIG_AppendOutput($result,(PyObject*)array$argnum); 2069 | } 2070 | 2071 | /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) 2072 | */ 2073 | %typemap(in,numinputs=0, 2074 | fragment="NumPy_Backward_Compatibility,NumPy_Macros") 2075 | (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) 2076 | (PyObject* array = NULL) 2077 | { 2078 | npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 }; 2079 | array = PyArray_SimpleNew(3, dims, DATA_TYPECODE); 2080 | if (!array) SWIG_fail; 2081 | $1 = ($1_ltype) array_data(array); 2082 | } 2083 | %typemap(argout) 2084 | (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) 2085 | { 2086 | $result = SWIG_AppendOutput($result,(PyObject*)array$argnum); 2087 | } 2088 | 2089 | /* Typemap suite for (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) 2090 | */ 2091 | %typemap(in,numinputs=0, 2092 | fragment="NumPy_Backward_Compatibility,NumPy_Macros") 2093 | (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) 2094 | (PyObject* array = NULL) 2095 | { 2096 | npy_intp dims[4] = { $1_dim0, $1_dim1, $1_dim2, $1_dim3 }; 2097 | array = PyArray_SimpleNew(4, dims, DATA_TYPECODE); 2098 | if (!array) SWIG_fail; 2099 | $1 = ($1_ltype) array_data(array); 2100 | } 2101 | %typemap(argout) 2102 | (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) 2103 | { 2104 | $result = SWIG_AppendOutput($result,(PyObject*)array$argnum); 2105 | } 2106 | 2107 | /*****************************/ 2108 | /* Argoutview Array Typemaps */ 2109 | /*****************************/ 2110 | 2111 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) 2112 | */ 2113 | %typemap(in,numinputs=0) 2114 | (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 ) 2115 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) 2116 | { 2117 | $1 = &data_temp; 2118 | $2 = &dim_temp; 2119 | } 2120 | %typemap(argout, 2121 | fragment="NumPy_Backward_Compatibility") 2122 | (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) 2123 | { 2124 | npy_intp dims[1] = { *$2 }; 2125 | PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); 2126 | PyArrayObject* array = (PyArrayObject*) obj; 2127 | 2128 | if (!array) SWIG_fail; 2129 | $result = SWIG_AppendOutput($result,obj); 2130 | } 2131 | 2132 | /* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) 2133 | */ 2134 | %typemap(in,numinputs=0) 2135 | (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1) 2136 | (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) 2137 | { 2138 | $1 = &dim_temp; 2139 | $2 = &data_temp; 2140 | } 2141 | %typemap(argout, 2142 | fragment="NumPy_Backward_Compatibility") 2143 | (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) 2144 | { 2145 | npy_intp dims[1] = { *$1 }; 2146 | PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); 2147 | PyArrayObject* array = (PyArrayObject*) obj; 2148 | 2149 | if (!array) SWIG_fail; 2150 | $result = SWIG_AppendOutput($result,obj); 2151 | } 2152 | 2153 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 2154 | */ 2155 | %typemap(in,numinputs=0) 2156 | (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) 2157 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) 2158 | { 2159 | $1 = &data_temp; 2160 | $2 = &dim1_temp; 2161 | $3 = &dim2_temp; 2162 | } 2163 | %typemap(argout, 2164 | fragment="NumPy_Backward_Compatibility") 2165 | (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 2166 | { 2167 | npy_intp dims[2] = { *$2, *$3 }; 2168 | PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); 2169 | PyArrayObject* array = (PyArrayObject*) obj; 2170 | 2171 | if (!array) SWIG_fail; 2172 | $result = SWIG_AppendOutput($result,obj); 2173 | } 2174 | 2175 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) 2176 | */ 2177 | %typemap(in,numinputs=0) 2178 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2) 2179 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) 2180 | { 2181 | $1 = &dim1_temp; 2182 | $2 = &dim2_temp; 2183 | $3 = &data_temp; 2184 | } 2185 | %typemap(argout, 2186 | fragment="NumPy_Backward_Compatibility") 2187 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) 2188 | { 2189 | npy_intp dims[2] = { *$1, *$2 }; 2190 | PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); 2191 | PyArrayObject* array = (PyArrayObject*) obj; 2192 | 2193 | if (!array) SWIG_fail; 2194 | $result = SWIG_AppendOutput($result,obj); 2195 | } 2196 | 2197 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 2198 | */ 2199 | %typemap(in,numinputs=0) 2200 | (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) 2201 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) 2202 | { 2203 | $1 = &data_temp; 2204 | $2 = &dim1_temp; 2205 | $3 = &dim2_temp; 2206 | } 2207 | %typemap(argout, 2208 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") 2209 | (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 2210 | { 2211 | npy_intp dims[2] = { *$2, *$3 }; 2212 | PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); 2213 | PyArrayObject* array = (PyArrayObject*) obj; 2214 | 2215 | if (!array || !require_fortran(array)) SWIG_fail; 2216 | $result = SWIG_AppendOutput($result,obj); 2217 | } 2218 | 2219 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) 2220 | */ 2221 | %typemap(in,numinputs=0) 2222 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2) 2223 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) 2224 | { 2225 | $1 = &dim1_temp; 2226 | $2 = &dim2_temp; 2227 | $3 = &data_temp; 2228 | } 2229 | %typemap(argout, 2230 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") 2231 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) 2232 | { 2233 | npy_intp dims[2] = { *$1, *$2 }; 2234 | PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); 2235 | PyArrayObject* array = (PyArrayObject*) obj; 2236 | 2237 | if (!array || !require_fortran(array)) SWIG_fail; 2238 | $result = SWIG_AppendOutput($result,obj); 2239 | } 2240 | 2241 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, 2242 | DIM_TYPE* DIM3) 2243 | */ 2244 | %typemap(in,numinputs=0) 2245 | (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) 2246 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) 2247 | { 2248 | $1 = &data_temp; 2249 | $2 = &dim1_temp; 2250 | $3 = &dim2_temp; 2251 | $4 = &dim3_temp; 2252 | } 2253 | %typemap(argout, 2254 | fragment="NumPy_Backward_Compatibility") 2255 | (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) 2256 | { 2257 | npy_intp dims[3] = { *$2, *$3, *$4 }; 2258 | PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); 2259 | PyArrayObject* array = (PyArrayObject*) obj; 2260 | 2261 | if (!array) SWIG_fail; 2262 | $result = SWIG_AppendOutput($result,obj); 2263 | } 2264 | 2265 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, 2266 | DATA_TYPE** ARGOUTVIEW_ARRAY3) 2267 | */ 2268 | %typemap(in,numinputs=0) 2269 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) 2270 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL) 2271 | { 2272 | $1 = &dim1_temp; 2273 | $2 = &dim2_temp; 2274 | $3 = &dim3_temp; 2275 | $4 = &data_temp; 2276 | } 2277 | %typemap(argout, 2278 | fragment="NumPy_Backward_Compatibility") 2279 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) 2280 | { 2281 | npy_intp dims[3] = { *$1, *$2, *$3 }; 2282 | PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); 2283 | PyArrayObject* array = (PyArrayObject*) obj; 2284 | 2285 | if (!array) SWIG_fail; 2286 | $result = SWIG_AppendOutput($result,obj); 2287 | } 2288 | 2289 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, 2290 | DIM_TYPE* DIM3) 2291 | */ 2292 | %typemap(in,numinputs=0) 2293 | (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) 2294 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) 2295 | { 2296 | $1 = &data_temp; 2297 | $2 = &dim1_temp; 2298 | $3 = &dim2_temp; 2299 | $4 = &dim3_temp; 2300 | } 2301 | %typemap(argout, 2302 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") 2303 | (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) 2304 | { 2305 | npy_intp dims[3] = { *$2, *$3, *$4 }; 2306 | PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); 2307 | PyArrayObject* array = (PyArrayObject*) obj; 2308 | 2309 | if (!array || !require_fortran(array)) SWIG_fail; 2310 | $result = SWIG_AppendOutput($result,obj); 2311 | } 2312 | 2313 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, 2314 | DATA_TYPE** ARGOUTVIEW_FARRAY3) 2315 | */ 2316 | %typemap(in,numinputs=0) 2317 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEW_FARRAY3) 2318 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) 2319 | { 2320 | $1 = &dim1_temp; 2321 | $2 = &dim2_temp; 2322 | $3 = &dim3_temp; 2323 | $4 = &data_temp; 2324 | } 2325 | %typemap(argout, 2326 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") 2327 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) 2328 | { 2329 | npy_intp dims[3] = { *$1, *$2, *$3 }; 2330 | PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); 2331 | PyArrayObject* array = (PyArrayObject*) obj; 2332 | 2333 | if (!array || !require_fortran(array)) SWIG_fail; 2334 | $result = SWIG_AppendOutput($result,obj); 2335 | } 2336 | 2337 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, 2338 | DIM_TYPE* DIM3, DIM_TYPE* DIM4) 2339 | */ 2340 | %typemap(in,numinputs=0) 2341 | (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) 2342 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) 2343 | { 2344 | $1 = &data_temp; 2345 | $2 = &dim1_temp; 2346 | $3 = &dim2_temp; 2347 | $4 = &dim3_temp; 2348 | $5 = &dim4_temp; 2349 | } 2350 | %typemap(argout, 2351 | fragment="NumPy_Backward_Compatibility") 2352 | (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) 2353 | { 2354 | npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; 2355 | PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); 2356 | PyArrayObject* array = (PyArrayObject*) obj; 2357 | 2358 | if (!array) SWIG_fail; 2359 | $result = SWIG_AppendOutput($result,obj); 2360 | } 2361 | 2362 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, 2363 | DATA_TYPE** ARGOUTVIEW_ARRAY4) 2364 | */ 2365 | %typemap(in,numinputs=0) 2366 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_ARRAY4) 2367 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) 2368 | { 2369 | $1 = &dim1_temp; 2370 | $2 = &dim2_temp; 2371 | $3 = &dim3_temp; 2372 | $4 = &dim4_temp; 2373 | $5 = &data_temp; 2374 | } 2375 | %typemap(argout, 2376 | fragment="NumPy_Backward_Compatibility") 2377 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) 2378 | { 2379 | npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; 2380 | PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); 2381 | PyArrayObject* array = (PyArrayObject*) obj; 2382 | 2383 | if (!array) SWIG_fail; 2384 | $result = SWIG_AppendOutput($result,obj); 2385 | } 2386 | 2387 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, 2388 | DIM_TYPE* DIM3, DIM_TYPE* DIM4) 2389 | */ 2390 | %typemap(in,numinputs=0) 2391 | (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) 2392 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) 2393 | { 2394 | $1 = &data_temp; 2395 | $2 = &dim1_temp; 2396 | $3 = &dim2_temp; 2397 | $4 = &dim3_temp; 2398 | $5 = &dim4_temp; 2399 | } 2400 | %typemap(argout, 2401 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") 2402 | (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) 2403 | { 2404 | npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; 2405 | PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); 2406 | PyArrayObject* array = (PyArrayObject*) obj; 2407 | 2408 | if (!array || !require_fortran(array)) SWIG_fail; 2409 | $result = SWIG_AppendOutput($result,obj); 2410 | } 2411 | 2412 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, 2413 | DATA_TYPE** ARGOUTVIEW_FARRAY4) 2414 | */ 2415 | %typemap(in,numinputs=0) 2416 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_FARRAY4) 2417 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) 2418 | { 2419 | $1 = &dim1_temp; 2420 | $2 = &dim2_temp; 2421 | $3 = &dim3_temp; 2422 | $4 = &dim4_temp; 2423 | $5 = &data_temp; 2424 | } 2425 | %typemap(argout, 2426 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") 2427 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) 2428 | { 2429 | npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; 2430 | PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); 2431 | PyArrayObject* array = (PyArrayObject*) obj; 2432 | 2433 | if (!array || !require_fortran(array)) SWIG_fail; 2434 | $result = SWIG_AppendOutput($result,obj); 2435 | } 2436 | 2437 | /*************************************/ 2438 | /* Managed Argoutview Array Typemaps */ 2439 | /*************************************/ 2440 | 2441 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) 2442 | */ 2443 | %typemap(in,numinputs=0) 2444 | (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1 ) 2445 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) 2446 | { 2447 | $1 = &data_temp; 2448 | $2 = &dim_temp; 2449 | } 2450 | %typemap(argout, 2451 | fragment="NumPy_Backward_Compatibility,NumPy_Utilities") 2452 | (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) 2453 | { 2454 | npy_intp dims[1] = { *$2 }; 2455 | PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); 2456 | PyArrayObject* array = (PyArrayObject*) obj; 2457 | 2458 | if (!array) SWIG_fail; 2459 | 2460 | PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); 2461 | 2462 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2463 | PyArray_BASE(array) = cap; 2464 | %#else 2465 | PyArray_SetBaseObject(array,cap); 2466 | %#endif 2467 | 2468 | $result = SWIG_AppendOutput($result,obj); 2469 | } 2470 | 2471 | /* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) 2472 | */ 2473 | %typemap(in,numinputs=0) 2474 | (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEWM_ARRAY1) 2475 | (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) 2476 | { 2477 | $1 = &dim_temp; 2478 | $2 = &data_temp; 2479 | } 2480 | %typemap(argout, 2481 | fragment="NumPy_Backward_Compatibility,NumPy_Utilities") 2482 | (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) 2483 | { 2484 | npy_intp dims[1] = { *$1 }; 2485 | PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); 2486 | PyArrayObject* array = (PyArrayObject*) obj; 2487 | 2488 | if (!array) SWIG_fail; 2489 | 2490 | PyObject* cap = PyCapsule_New((void*)(*$2), SWIGPY_CAPSULE_NAME, free_cap); 2491 | 2492 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2493 | PyArray_BASE(array) = cap; 2494 | %#else 2495 | PyArray_SetBaseObject(array,cap); 2496 | %#endif 2497 | 2498 | $result = SWIG_AppendOutput($result,obj); 2499 | } 2500 | 2501 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 2502 | */ 2503 | %typemap(in,numinputs=0) 2504 | (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) 2505 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) 2506 | { 2507 | $1 = &data_temp; 2508 | $2 = &dim1_temp; 2509 | $3 = &dim2_temp; 2510 | } 2511 | %typemap(argout, 2512 | fragment="NumPy_Backward_Compatibility,NumPy_Utilities") 2513 | (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 2514 | { 2515 | npy_intp dims[2] = { *$2, *$3 }; 2516 | PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); 2517 | PyArrayObject* array = (PyArrayObject*) obj; 2518 | 2519 | if (!array) SWIG_fail; 2520 | 2521 | PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); 2522 | 2523 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2524 | PyArray_BASE(array) = cap; 2525 | %#else 2526 | PyArray_SetBaseObject(array,cap); 2527 | %#endif 2528 | 2529 | $result = SWIG_AppendOutput($result,obj); 2530 | } 2531 | 2532 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) 2533 | */ 2534 | %typemap(in,numinputs=0) 2535 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_ARRAY2) 2536 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) 2537 | { 2538 | $1 = &dim1_temp; 2539 | $2 = &dim2_temp; 2540 | $3 = &data_temp; 2541 | } 2542 | %typemap(argout, 2543 | fragment="NumPy_Backward_Compatibility,NumPy_Utilities") 2544 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) 2545 | { 2546 | npy_intp dims[2] = { *$1, *$2 }; 2547 | PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); 2548 | PyArrayObject* array = (PyArrayObject*) obj; 2549 | 2550 | if (!array) SWIG_fail; 2551 | 2552 | PyObject* cap = PyCapsule_New((void*)(*$3), SWIGPY_CAPSULE_NAME, free_cap); 2553 | 2554 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2555 | PyArray_BASE(array) = cap; 2556 | %#else 2557 | PyArray_SetBaseObject(array,cap); 2558 | %#endif 2559 | 2560 | $result = SWIG_AppendOutput($result,obj); 2561 | } 2562 | 2563 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 2564 | */ 2565 | %typemap(in,numinputs=0) 2566 | (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) 2567 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) 2568 | { 2569 | $1 = &data_temp; 2570 | $2 = &dim1_temp; 2571 | $3 = &dim2_temp; 2572 | } 2573 | %typemap(argout, 2574 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") 2575 | (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) 2576 | { 2577 | npy_intp dims[2] = { *$2, *$3 }; 2578 | PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); 2579 | PyArrayObject* array = (PyArrayObject*) obj; 2580 | 2581 | if (!array || !require_fortran(array)) SWIG_fail; 2582 | 2583 | PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); 2584 | 2585 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2586 | PyArray_BASE(array) = cap; 2587 | %#else 2588 | PyArray_SetBaseObject(array,cap); 2589 | %#endif 2590 | 2591 | $result = SWIG_AppendOutput($result,obj); 2592 | } 2593 | 2594 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) 2595 | */ 2596 | %typemap(in,numinputs=0) 2597 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_FARRAY2) 2598 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) 2599 | { 2600 | $1 = &dim1_temp; 2601 | $2 = &dim2_temp; 2602 | $3 = &data_temp; 2603 | } 2604 | %typemap(argout, 2605 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") 2606 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) 2607 | { 2608 | npy_intp dims[2] = { *$1, *$2 }; 2609 | PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); 2610 | PyArrayObject* array = (PyArrayObject*) obj; 2611 | 2612 | if (!array || !require_fortran(array)) SWIG_fail; 2613 | 2614 | PyObject* cap = PyCapsule_New((void*)(*$3), SWIGPY_CAPSULE_NAME, free_cap); 2615 | 2616 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2617 | PyArray_BASE(array) = cap; 2618 | %#else 2619 | PyArray_SetBaseObject(array,cap); 2620 | %#endif 2621 | 2622 | $result = SWIG_AppendOutput($result,obj); 2623 | } 2624 | 2625 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, 2626 | DIM_TYPE* DIM3) 2627 | */ 2628 | %typemap(in,numinputs=0) 2629 | (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) 2630 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) 2631 | { 2632 | $1 = &data_temp; 2633 | $2 = &dim1_temp; 2634 | $3 = &dim2_temp; 2635 | $4 = &dim3_temp; 2636 | } 2637 | %typemap(argout, 2638 | fragment="NumPy_Backward_Compatibility,NumPy_Utilities") 2639 | (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) 2640 | { 2641 | npy_intp dims[3] = { *$2, *$3, *$4 }; 2642 | PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); 2643 | PyArrayObject* array = (PyArrayObject*) obj; 2644 | 2645 | if (!array) SWIG_fail; 2646 | 2647 | PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); 2648 | 2649 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2650 | PyArray_BASE(array) = cap; 2651 | %#else 2652 | PyArray_SetBaseObject(array,cap); 2653 | %#endif 2654 | 2655 | $result = SWIG_AppendOutput($result,obj); 2656 | } 2657 | 2658 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, 2659 | DATA_TYPE** ARGOUTVIEWM_ARRAY3) 2660 | */ 2661 | %typemap(in,numinputs=0) 2662 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_ARRAY3) 2663 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) 2664 | { 2665 | $1 = &dim1_temp; 2666 | $2 = &dim2_temp; 2667 | $3 = &dim3_temp; 2668 | $4 = &data_temp; 2669 | } 2670 | %typemap(argout, 2671 | fragment="NumPy_Backward_Compatibility,NumPy_Utilities") 2672 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) 2673 | { 2674 | npy_intp dims[3] = { *$1, *$2, *$3 }; 2675 | PyObject* obj= PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); 2676 | PyArrayObject* array = (PyArrayObject*) obj; 2677 | 2678 | if (!array) SWIG_fail; 2679 | 2680 | PyObject* cap = PyCapsule_New((void*)(*$4), SWIGPY_CAPSULE_NAME, free_cap); 2681 | 2682 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2683 | PyArray_BASE(array) = cap; 2684 | %#else 2685 | PyArray_SetBaseObject(array,cap); 2686 | %#endif 2687 | 2688 | $result = SWIG_AppendOutput($result,obj); 2689 | } 2690 | 2691 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, 2692 | DIM_TYPE* DIM3) 2693 | */ 2694 | %typemap(in,numinputs=0) 2695 | (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) 2696 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) 2697 | { 2698 | $1 = &data_temp; 2699 | $2 = &dim1_temp; 2700 | $3 = &dim2_temp; 2701 | $4 = &dim3_temp; 2702 | } 2703 | %typemap(argout, 2704 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") 2705 | (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) 2706 | { 2707 | npy_intp dims[3] = { *$2, *$3, *$4 }; 2708 | PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); 2709 | PyArrayObject* array = (PyArrayObject*) obj; 2710 | 2711 | if (!array || !require_fortran(array)) SWIG_fail; 2712 | 2713 | PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); 2714 | 2715 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2716 | PyArray_BASE(array) = cap; 2717 | %#else 2718 | PyArray_SetBaseObject(array,cap); 2719 | %#endif 2720 | 2721 | $result = SWIG_AppendOutput($result,obj); 2722 | } 2723 | 2724 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, 2725 | DATA_TYPE** ARGOUTVIEWM_FARRAY3) 2726 | */ 2727 | %typemap(in,numinputs=0) 2728 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_FARRAY3) 2729 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) 2730 | { 2731 | $1 = &dim1_temp; 2732 | $2 = &dim2_temp; 2733 | $3 = &dim3_temp; 2734 | $4 = &data_temp; 2735 | } 2736 | %typemap(argout, 2737 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") 2738 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) 2739 | { 2740 | npy_intp dims[3] = { *$1, *$2, *$3 }; 2741 | PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); 2742 | PyArrayObject* array = (PyArrayObject*) obj; 2743 | 2744 | if (!array || !require_fortran(array)) SWIG_fail; 2745 | 2746 | PyObject* cap = PyCapsule_New((void*)(*$4), SWIGPY_CAPSULE_NAME, free_cap); 2747 | 2748 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2749 | PyArray_BASE(array) = cap; 2750 | %#else 2751 | PyArray_SetBaseObject(array,cap); 2752 | %#endif 2753 | 2754 | $result = SWIG_AppendOutput($result,obj); 2755 | } 2756 | 2757 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, 2758 | DIM_TYPE* DIM3, DIM_TYPE* DIM4) 2759 | */ 2760 | %typemap(in,numinputs=0) 2761 | (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) 2762 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) 2763 | { 2764 | $1 = &data_temp; 2765 | $2 = &dim1_temp; 2766 | $3 = &dim2_temp; 2767 | $4 = &dim3_temp; 2768 | $5 = &dim4_temp; 2769 | } 2770 | %typemap(argout, 2771 | fragment="NumPy_Backward_Compatibility,NumPy_Utilities") 2772 | (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) 2773 | { 2774 | npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; 2775 | PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); 2776 | PyArrayObject* array = (PyArrayObject*) obj; 2777 | 2778 | if (!array) SWIG_fail; 2779 | 2780 | PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); 2781 | 2782 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2783 | PyArray_BASE(array) = cap; 2784 | %#else 2785 | PyArray_SetBaseObject(array,cap); 2786 | %#endif 2787 | 2788 | $result = SWIG_AppendOutput($result,obj); 2789 | } 2790 | 2791 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, 2792 | DATA_TYPE** ARGOUTVIEWM_ARRAY4) 2793 | */ 2794 | %typemap(in,numinputs=0) 2795 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) 2796 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) 2797 | { 2798 | $1 = &dim1_temp; 2799 | $2 = &dim2_temp; 2800 | $3 = &dim3_temp; 2801 | $4 = &dim4_temp; 2802 | $5 = &data_temp; 2803 | } 2804 | %typemap(argout, 2805 | fragment="NumPy_Backward_Compatibility,NumPy_Utilities") 2806 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) 2807 | { 2808 | npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; 2809 | PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); 2810 | PyArrayObject* array = (PyArrayObject*) obj; 2811 | 2812 | if (!array) SWIG_fail; 2813 | 2814 | PyObject* cap = PyCapsule_New((void*)(*$5), SWIGPY_CAPSULE_NAME, free_cap); 2815 | 2816 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2817 | PyArray_BASE(array) = cap; 2818 | %#else 2819 | PyArray_SetBaseObject(array,cap); 2820 | %#endif 2821 | 2822 | $result = SWIG_AppendOutput($result,obj); 2823 | } 2824 | 2825 | /* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, 2826 | DIM_TYPE* DIM3, DIM_TYPE* DIM4) 2827 | */ 2828 | %typemap(in,numinputs=0) 2829 | (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) 2830 | (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) 2831 | { 2832 | $1 = &data_temp; 2833 | $2 = &dim1_temp; 2834 | $3 = &dim2_temp; 2835 | $4 = &dim3_temp; 2836 | $5 = &dim4_temp; 2837 | } 2838 | %typemap(argout, 2839 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") 2840 | (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) 2841 | { 2842 | npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; 2843 | PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); 2844 | PyArrayObject* array = (PyArrayObject*) obj; 2845 | 2846 | if (!array || !require_fortran(array)) SWIG_fail; 2847 | 2848 | PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); 2849 | 2850 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2851 | PyArray_BASE(array) = cap; 2852 | %#else 2853 | PyArray_SetBaseObject(array,cap); 2854 | %#endif 2855 | 2856 | $result = SWIG_AppendOutput($result,obj); 2857 | } 2858 | 2859 | /* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, 2860 | DATA_TYPE** ARGOUTVIEWM_FARRAY4) 2861 | */ 2862 | %typemap(in,numinputs=0) 2863 | (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) 2864 | (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) 2865 | { 2866 | $1 = &dim1_temp; 2867 | $2 = &dim2_temp; 2868 | $3 = &dim3_temp; 2869 | $4 = &dim4_temp; 2870 | $5 = &data_temp; 2871 | } 2872 | %typemap(argout, 2873 | fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") 2874 | (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) 2875 | { 2876 | npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; 2877 | PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); 2878 | PyArrayObject* array = (PyArrayObject*) obj; 2879 | 2880 | if (!array || !require_fortran(array)) SWIG_fail; 2881 | 2882 | PyObject* cap = PyCapsule_New((void*)(*$5), SWIGPY_CAPSULE_NAME, free_cap); 2883 | 2884 | %#if NPY_API_VERSION < NPY_1_7_API_VERSION 2885 | PyArray_BASE(array) = cap; 2886 | %#else 2887 | PyArray_SetBaseObject(array,cap); 2888 | %#endif 2889 | 2890 | $result = SWIG_AppendOutput($result,obj); 2891 | } 2892 | 2893 | /**************************************/ 2894 | /* In-Place Array Typemap - flattened */ 2895 | /**************************************/ 2896 | 2897 | /* Typemap suite for (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) 2898 | */ 2899 | %typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, 2900 | fragment="NumPy_Macros") 2901 | (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) 2902 | { 2903 | $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), 2904 | DATA_TYPECODE); 2905 | } 2906 | %typemap(in, 2907 | fragment="NumPy_Fragments") 2908 | (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) 2909 | (PyArrayObject* array=NULL, int i=1) 2910 | { 2911 | array = obj_to_array_no_conversion($input, DATA_TYPECODE); 2912 | if (!array || !require_c_or_f_contiguous(array) 2913 | || !require_native(array)) SWIG_fail; 2914 | $1 = (DATA_TYPE*) array_data(array); 2915 | $2 = 1; 2916 | for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); 2917 | } 2918 | 2919 | %enddef /* %numpy_typemaps() macro */ 2920 | /* *************************************************************** */ 2921 | 2922 | /* Concrete instances of the %numpy_typemaps() macro: Each invocation 2923 | * below applies all of the typemaps above to the specified data type. 2924 | */ 2925 | %numpy_typemaps(signed char , NPY_BYTE , int) 2926 | %numpy_typemaps(unsigned char , NPY_UBYTE , int) 2927 | %numpy_typemaps(short , NPY_SHORT , int) 2928 | %numpy_typemaps(unsigned short , NPY_USHORT , int) 2929 | %numpy_typemaps(int , NPY_INT , int) 2930 | %numpy_typemaps(unsigned int , NPY_UINT , int) 2931 | %numpy_typemaps(long , NPY_LONG , int) 2932 | %numpy_typemaps(unsigned long , NPY_ULONG , int) 2933 | %numpy_typemaps(long long , NPY_LONGLONG , int) 2934 | %numpy_typemaps(unsigned long long, NPY_ULONGLONG, int) 2935 | %numpy_typemaps(float , NPY_FLOAT , int) 2936 | %numpy_typemaps(double , NPY_DOUBLE , int) 2937 | %numpy_typemaps(int8_t , NPY_INT8 , int) 2938 | %numpy_typemaps(int16_t , NPY_INT16 , int) 2939 | %numpy_typemaps(int32_t , NPY_INT32 , int) 2940 | %numpy_typemaps(int64_t , NPY_INT64 , int) 2941 | %numpy_typemaps(uint8_t , NPY_UINT8 , int) 2942 | %numpy_typemaps(uint16_t , NPY_UINT16 , int) 2943 | %numpy_typemaps(uint32_t , NPY_UINT32 , int) 2944 | %numpy_typemaps(uint64_t , NPY_UINT64 , int) 2945 | 2946 | 2947 | /* *************************************************************** 2948 | * The follow macro expansion does not work, because C++ bool is 4 2949 | * bytes and NPY_BOOL is 1 byte 2950 | * 2951 | * %numpy_typemaps(bool, NPY_BOOL, int) 2952 | */ 2953 | 2954 | /* *************************************************************** 2955 | * On my Mac, I get the following warning for this macro expansion: 2956 | * 'swig/python detected a memory leak of type 'long double *', no destructor found.' 2957 | * 2958 | * %numpy_typemaps(long double, NPY_LONGDOUBLE, int) 2959 | */ 2960 | 2961 | #ifdef __cplusplus 2962 | 2963 | %include 2964 | 2965 | %numpy_typemaps(std::complex, NPY_CFLOAT , int) 2966 | %numpy_typemaps(std::complex, NPY_CDOUBLE, int) 2967 | 2968 | #endif 2969 | 2970 | #endif /* SWIGPYTHON */ 2971 | -------------------------------------------------------------------------------- /example/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "wheel", 4 | # Check the updated version pinning requirements in: 5 | # https://github.com/pypa/setuptools_scm 6 | "setuptools", 7 | "setuptools_scm[toml]", 8 | "cmake_build_extension", 9 | "numpy", 10 | "pybind11", 11 | ] 12 | build-backend = "setuptools.build_meta" 13 | 14 | [tool.black] 15 | line-length = 88 16 | 17 | [tool.isort] 18 | profile = "black" 19 | multi_line_output = 3 20 | -------------------------------------------------------------------------------- /example/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = mymath 3 | description = Example to show how to use cmake-build-extension with CMake, SWIG and NumPy. 4 | long_description = file: README.md 5 | long_description_content_type = text/markdown 6 | author = Diego Ferigo 7 | author_email = dgferigo@gmail.com 8 | license = MIT 9 | platforms = any 10 | url = https://github.com/diegoferigo/cmake-build-extension/tree/master/example 11 | project_urls = 12 | Source = https://github.com/diegoferigo/cmake-build-extension/tree/master/examples/swig 13 | Tracker = https://github.com/diegoferigo/cmake-build-extension/issues 14 | keywords = setuptools extension cpp cmake build package pypi bindings swig pybind11 15 | classifiers = 16 | 17 | [options] 18 | zip_safe = False 19 | packages = find: 20 | package_dir = 21 | =src 22 | python_requires = >=3.6 23 | install_requires = 24 | numpy 25 | # This requirement is only necessary if the build_extension_env 26 | # context manager is used in the top-level __init__.py 27 | cmake-build-extension 28 | 29 | [options.packages.find] 30 | where = src 31 | 32 | [options.extras_require] 33 | test = 34 | pytest 35 | pytest-icdiff 36 | all = 37 | %(test)s 38 | 39 | # This also requires using the "expose_binaries" option in setup.py. 40 | # It creates a generic .bin.__main__ file that is exposed 41 | # as /bin/ that relays all input arguments to 42 | # the C++ executable. 43 | [options.entry_points] 44 | console_scripts = 45 | print_answer_swig = mymath_swig.bin.__main__:main 46 | print_answer_pybind11 = mymath_pybind11.bin.__main__:main 47 | 48 | [tool:pytest] 49 | addopts = -rsxX -v 50 | testpaths = tests 51 | -------------------------------------------------------------------------------- /example/setup.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | import os 3 | import sys 4 | from pathlib import Path 5 | 6 | import cmake_build_extension 7 | import setuptools 8 | 9 | # Importing the bindings inside the build_extension_env context manager is necessary only 10 | # in Windows with Python>=3.8. 11 | # See https://github.com/diegoferigo/cmake-build-extension/issues/8. 12 | # Note that if this manager is used in the init file, cmake-build-extension becomes an 13 | # install_requires that must be added to the setup.cfg. Otherwise, cmake-build-extension 14 | # could only be listed as build-system requires in pyproject.toml since it would only 15 | # be necessary for packaging and not during runtime. 16 | init_py = inspect.cleandoc( 17 | """ 18 | import cmake_build_extension 19 | 20 | with cmake_build_extension.build_extension_env(): 21 | from . import bindings 22 | """ 23 | ) 24 | 25 | # Extra options passed to the CI/CD pipeline that uses cibuildwheel 26 | CIBW_CMAKE_OPTIONS = [] 27 | if "CIBUILDWHEEL" in os.environ and os.environ["CIBUILDWHEEL"] == "1": 28 | 29 | # The manylinux variant runs in Debian Stretch and it uses lib64 folder 30 | if sys.platform == "linux": 31 | CIBW_CMAKE_OPTIONS += ["-DCMAKE_INSTALL_LIBDIR=lib"] 32 | 33 | # Eigen is not found when installed with vcpkg because we don't pass the toolchain. 34 | # Passing directly the right folder as workaround. This is meant to work just in CI. 35 | if os.name == "nt": 36 | CIBW_CMAKE_OPTIONS += [ 37 | "-DEigen3_DIR:PATH=C:/vcpkg/packages/eigen3_x64-windows/share/eigen3", 38 | ] 39 | 40 | # This example is compliant with PEP517 and PEP518. It uses the setup.cfg file to store 41 | # most of the package metadata. However, build extensions are not supported and must be 42 | # configured in the setup.py. 43 | setuptools.setup( 44 | # The resulting "mymath" archive contains two packages: mymath_swig and mymath_pybind. 45 | # This approach separates the two bindings types, typically just one of them is used. 46 | ext_modules=[ 47 | cmake_build_extension.CMakeExtension( 48 | # This could be anything you like, it is used to create build folders 49 | name="SwigBindings", 50 | # Name of the resulting package name (import mymath_swig) 51 | install_prefix="mymath_swig", 52 | # Exposes the binary print_answer to the environment. 53 | # It requires also adding a new entry point in setup.cfg. 54 | expose_binaries=["bin/print_answer"], 55 | # Writes the content to the top-level __init__.py 56 | write_top_level_init=init_py, 57 | # Selects the folder where the main CMakeLists.txt is stored 58 | # (it could be a subfolder) 59 | source_dir=str(Path(__file__).parent.absolute()), 60 | cmake_configure_options=[ 61 | # This option points CMake to the right Python interpreter, and helps 62 | # the logic of FindPython3.cmake to find the active version 63 | f"-DPython3_ROOT_DIR={Path(sys.prefix)}", 64 | "-DCALL_FROM_SETUP_PY:BOOL=ON", 65 | "-DBUILD_SHARED_LIBS:BOOL=OFF", 66 | # Select the bindings implementation 67 | "-DEXAMPLE_WITH_SWIG:BOOL=ON", 68 | "-DEXAMPLE_WITH_PYBIND11:BOOL=OFF", 69 | ] 70 | + CIBW_CMAKE_OPTIONS, 71 | ), 72 | cmake_build_extension.CMakeExtension( 73 | name="Pybind11Bindings", 74 | # Name of the resulting package name (import mymath_pybind11) 75 | install_prefix="mymath_pybind11", 76 | # Note: pybind11 is a build-system requirement specified in pyproject.toml, 77 | # therefore pypa/pip or pypa/build will install it in the virtual 78 | # environment created in /tmp during packaging. 79 | # This cmake_depends_on option adds the pybind11 installation path 80 | # to CMAKE_PREFIX_PATH so that the example finds the pybind11 targets 81 | # even if it is not installed in the system. 82 | cmake_depends_on=["pybind11"], 83 | # Exposes the binary print_answer to the environment. 84 | # It requires also adding a new entry point in setup.cfg. 85 | expose_binaries=["bin/print_answer"], 86 | # Writes the content to the top-level __init__.py 87 | write_top_level_init=init_py, 88 | # Selects the folder where the main CMakeLists.txt is stored 89 | # (it could be a subfolder) 90 | source_dir=str(Path(__file__).parent.absolute()), 91 | cmake_configure_options=[ 92 | # This option points CMake to the right Python interpreter, and helps 93 | # the logic of FindPython3.cmake to find the active version 94 | f"-DPython3_ROOT_DIR={Path(sys.prefix)}", 95 | "-DCALL_FROM_SETUP_PY:BOOL=ON", 96 | "-DBUILD_SHARED_LIBS:BOOL=OFF", 97 | # Select the bindings implementation 98 | "-DEXAMPLE_WITH_SWIG:BOOL=OFF", 99 | "-DEXAMPLE_WITH_PYBIND11:BOOL=ON", 100 | ] 101 | + CIBW_CMAKE_OPTIONS, 102 | ), 103 | ], 104 | cmdclass=dict( 105 | # Enable the CMakeExtension entries defined above 106 | build_ext=cmake_build_extension.BuildExtension, 107 | # If the setup.py or setup.cfg are in a subfolder wrt the main CMakeLists.txt, 108 | # you can use the following custom command to create the source distribution. 109 | # sdist=cmake_build_extension.GitSdistFolder 110 | ), 111 | ) 112 | -------------------------------------------------------------------------------- /example/src/mymath.cpp: -------------------------------------------------------------------------------- 1 | #include "mymath.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | double mymath::dot(const std::vector& vector1, 10 | const std::vector& vector2) 11 | { 12 | if (vector1.size() != vector2.size()) { 13 | throw std::runtime_error("Sizes of the vector do not match"); 14 | } 15 | 16 | double dot = 0; 17 | 18 | for (size_t i = 0; i < vector1.size(); ++i) { 19 | dot += vector1[i] * vector2[i]; 20 | } 21 | 22 | return dot; 23 | } 24 | 25 | std::vector mymath::normalize(const std::vector& data) 26 | { 27 | auto sumOfSquared = [](double accumulator, const double element) { 28 | return accumulator + element * element; 29 | }; 30 | 31 | const double norm = 32 | sqrt(std::accumulate(data.begin(), data.end(), 0.0, sumOfSquared)); 33 | 34 | std::vector out; 35 | out.reserve(data.size()); 36 | 37 | std::transform(data.begin(), 38 | data.end(), 39 | std::back_inserter(out), 40 | [&](const double d) -> double { return d / norm; }); 41 | 42 | return out; 43 | } 44 | -------------------------------------------------------------------------------- /example/src/mymath.h: -------------------------------------------------------------------------------- 1 | #ifndef MYMATH_H 2 | #define MYMATH_H 3 | 4 | #include 5 | 6 | namespace mymath { 7 | 8 | /** 9 | * Perform the inner product between two 1D vectors. 10 | * 11 | * @param vector1 The first vector. 12 | * @param vector2 The second vector. 13 | * @throws If the vectors sizes do not match. 14 | * @return The double product of the input vectors. 15 | */ 16 | double dot(const std::vector& vector1, 17 | const std::vector& vector2); 18 | 19 | /** 20 | * Normalize a 1D vector. 21 | * 22 | * The normalization operation takes the input vector and divides 23 | * all its element by its norm. The resulting vector is a unit vector, 24 | * i.e. a vector with length 1. 25 | * 26 | * @param input The vector to normalize. 27 | * @return The unit vector computed by normalizing the input. 28 | */ 29 | std::vector normalize(const std::vector& data); 30 | } // namespace mymath 31 | 32 | #endif // MYMATH_H 33 | -------------------------------------------------------------------------------- /example/src/print_answer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | // Answer to the Ultimate Question of Life, the Universe, and Everything 7 | std::cout << int('*') << std::endl; 8 | return EXIT_SUCCESS; 9 | } 10 | -------------------------------------------------------------------------------- /example/tests/test_pybind11.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import mymath_pybind11.bindings as mymath 4 | import numpy as np 5 | import pytest 6 | 7 | 8 | def test_dot(): 9 | 10 | v1 = [1.0, 2, 3, -5.5, 42] 11 | v2 = [-3.2, 0, 13, 6, -3.14] 12 | 13 | result = mymath.dot(vector1=v1, vector2=v2) 14 | assert pytest.approx(result) == np.dot(v1, v2) 15 | 16 | 17 | def test_normalize(): 18 | 19 | v = [1.0, 2, 3, -5.5, 42] 20 | 21 | result = mymath.normalize(data=v) 22 | assert pytest.approx(result) == np.array(v) / np.linalg.norm(v) 23 | 24 | 25 | def test_dot_numpy(): 26 | 27 | v1 = np.array([1.0, 2, 3, -5.5, 42]) 28 | v2 = np.array([-3.2, 0, 13, 6, -3.14]) 29 | 30 | result = mymath.dot(vector1=v1, vector2=v2) 31 | assert pytest.approx(result) == np.dot(v1, v2) 32 | 33 | 34 | def test_normalize_numpy(): 35 | 36 | v = np.array([1.0, 2, 3, -5.5, 42]) 37 | 38 | result = mymath.normalize_numpy(data=v) 39 | 40 | assert isinstance(result, np.ndarray) 41 | assert pytest.approx(result) == np.array(v) / np.linalg.norm(v) 42 | 43 | 44 | @pytest.mark.skipif( 45 | sys.platform == "win32", reason="fails with the error: access violation" 46 | ) 47 | def test_assertion(): 48 | 49 | v1 = np.array([1.0, 2, 3, -5.5]) 50 | v2 = np.array([42.0]) 51 | 52 | with pytest.raises(RuntimeError): 53 | _ = mymath.dot(vector1=v1, vector2=v2) 54 | 55 | 56 | @pytest.mark.skipif( 57 | sys.version_info < (3, 7), reason="capture_output and text require Python 3.7" 58 | ) 59 | def test_executable(): 60 | 61 | import subprocess 62 | 63 | result = subprocess.run("print_answer_pybind11", capture_output=True, text=True) 64 | assert result.stdout.strip() == "42" 65 | 66 | result = subprocess.run( 67 | [sys.executable, "-m", "mymath_pybind11.bin", "print_answer_pybind11"], 68 | capture_output=True, 69 | text=True, 70 | ) 71 | assert result.stdout.strip() == "42" 72 | -------------------------------------------------------------------------------- /example/tests/test_swig.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import mymath_swig.bindings as mymath 4 | import numpy as np 5 | import pytest 6 | 7 | 8 | def test_dot(): 9 | 10 | v1 = [1.0, 2, 3, -5.5, 42] 11 | v2 = [-3.2, 0, 13, 6, -3.14] 12 | 13 | result = mymath.dot(vector1=v1, vector2=v2) 14 | assert pytest.approx(result) == np.dot(v1, v2) 15 | 16 | 17 | def test_normalize(): 18 | 19 | v = [1.0, 2, 3, -5.5, 42] 20 | 21 | result = mymath.normalize(data=v) 22 | assert pytest.approx(result) == np.array(v) / np.linalg.norm(v) 23 | 24 | 25 | def test_dot_numpy(): 26 | 27 | v1 = np.array([1.0, 2, 3, -5.5, 42]) 28 | v2 = np.array([-3.2, 0, 13, 6, -3.14]) 29 | 30 | result = mymath.dot_numpy(in_1=v1, in_2=v2) 31 | assert pytest.approx(result) == np.dot(v1, v2) 32 | 33 | 34 | def test_normalize_numpy(): 35 | 36 | v = np.array([1.0, 2, 3, -5.5, 42]) 37 | 38 | result = mymath.normalize_numpy(in_1=v) 39 | 40 | assert isinstance(result, np.ndarray) 41 | assert pytest.approx(result) == np.array(v) / np.linalg.norm(v) 42 | 43 | 44 | def test_assertion(): 45 | 46 | v1 = np.array([1.0, 2, 3, -5.5]) 47 | v2 = np.array([42.0]) 48 | 49 | with pytest.raises(RuntimeError): 50 | _ = mymath.dot_numpy(in_1=v1, in_2=v2) 51 | 52 | 53 | @pytest.mark.skipif( 54 | sys.version_info < (3, 7), reason="capture_output and text require Python 3.7" 55 | ) 56 | def test_executable(): 57 | 58 | import subprocess 59 | 60 | result = subprocess.run("print_answer_swig", capture_output=True, text=True) 61 | assert result.stdout.strip() == "42" 62 | 63 | result = subprocess.run( 64 | [sys.executable, "-m", "mymath_swig.bin", "print_answer_swig"], 65 | capture_output=True, 66 | text=True, 67 | ) 68 | assert result.stdout.strip() == "42" 69 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "wheel", 4 | "setuptools>=45", 5 | "setuptools_scm[toml]>=6.0", 6 | ] 7 | build-backend = "setuptools.build_meta" 8 | 9 | [tool.setuptools_scm] 10 | local_scheme = "dirty-tag" 11 | 12 | [tool.black] 13 | line-length = 88 14 | 15 | [tool.isort] 16 | profile = "black" 17 | multi_line_output = 3 18 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = cmake-build-extension 3 | description = Setuptools extension to build and package CMake projects. 4 | long_description = file: README.md 5 | long_description_content_type = text/markdown 6 | author = Diego Ferigo 7 | author_email = dgferigo@gmail.com 8 | license = MIT 9 | license_file = LICENSE 10 | platforms = any 11 | url = https://github.com/diegoferigo/cmake-build-extension 12 | 13 | project_urls = 14 | Changelog = https://github.com/diegoferigo/cmake-build-extension/releases 15 | Source = https://github.com/diegoferigo/cmake-build-extension 16 | Tracker = https://github.com/diegoferigo/cmake-build-extension/issues 17 | 18 | keywords = 19 | setuptools 20 | extension 21 | cmake 22 | build 23 | package 24 | pypi 25 | 26 | classifiers = 27 | Development Status :: 4 - Beta 28 | Intended Audience :: Developers 29 | License :: OSI Approved :: MIT License 30 | Operating System :: OS Independent 31 | Programming Language :: Python :: 3 :: Only 32 | Programming Language :: Python :: 3 33 | Programming Language :: Python :: 3.8 34 | Programming Language :: Python :: 3.9 35 | Programming Language :: Python :: 3.10 36 | Programming Language :: Python :: 3.11 37 | Programming Language :: Python :: 3.12 38 | Programming Language :: Python :: 3.13 39 | Programming Language :: Python :: Implementation :: CPython 40 | Topic :: Software Development :: Build Tools 41 | Topic :: Software Development :: Libraries :: Python Modules 42 | Topic :: System :: Archiving :: Packaging 43 | 44 | [options] 45 | zip_safe = False 46 | packages = find: 47 | package_dir = 48 | =src 49 | python_requires = >=3.8 50 | install_requires = 51 | cmake 52 | ninja 53 | GitPython 54 | setuptools_scm 55 | 56 | [options.packages.find] 57 | where = src 58 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup() 4 | -------------------------------------------------------------------------------- /src/cmake_build_extension/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | from contextlib import contextmanager 3 | from pathlib import Path 4 | 5 | from . import build_ext_option, sdist_command 6 | from .build_extension import BuildExtension 7 | from .cmake_extension import CMakeExtension 8 | from .sdist_command import GitSdistFolder, GitSdistTree 9 | 10 | 11 | @contextmanager 12 | def build_extension_env(): 13 | """ 14 | Creates a context in which build extensions can be imported. 15 | 16 | It fixes a change of behaviour of Python >= 3.8 in Windows: 17 | https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew 18 | 19 | Other related resources: 20 | 21 | - https://stackoverflow.com/a/23805306 22 | - https://www.mail-archive.com/dev@subversion.apache.org/msg40414.html 23 | 24 | Example: 25 | 26 | .. code-block:: python 27 | 28 | from cmake_build_extension import build_extension_env 29 | 30 | with build_extension_env(): 31 | from . import bindings 32 | """ 33 | 34 | cookies = [] 35 | 36 | # Windows and Python >= 3.8 37 | if hasattr(os, "add_dll_directory"): 38 | 39 | for path in os.environ.get("PATH", "").split(os.pathsep): 40 | 41 | if path and Path(path).is_absolute() and Path(path).is_dir(): 42 | cookies.append(os.add_dll_directory(path)) 43 | 44 | try: 45 | yield 46 | 47 | finally: 48 | for cookie in cookies: 49 | cookie.close() 50 | -------------------------------------------------------------------------------- /src/cmake_build_extension/build_ext_option.py: -------------------------------------------------------------------------------- 1 | from typing import NamedTuple 2 | 3 | from setuptools.command.build_ext import build_ext 4 | 5 | 6 | class BuildExtOption(NamedTuple): 7 | """ 8 | NamedTuple that stores the metadata of a custom build_ext option. 9 | 10 | Example: 11 | 12 | The following option: 13 | 14 | BuildExtOption(variable="define", short="D", help="New compiler define") 15 | 16 | is displayed as follows: 17 | 18 | $ python setup.py build_ext --help 19 | ... 20 | Options for 'BuildExtension' command: 21 | ... 22 | --define (-D) New compiler define 23 | ... 24 | """ 25 | 26 | variable: str 27 | short: str 28 | help: str = "" 29 | 30 | 31 | def add_new_build_ext_option(option: BuildExtOption, override: bool = True): 32 | """ 33 | Workaround to add an existing option shown in python setup.py build_ext -h. 34 | 35 | Args: 36 | option: The new option to add. 37 | override: Delete the option if it already exists. 38 | """ 39 | 40 | if override: 41 | # Remove from the existing build_ext.user_options the option to override 42 | build_ext.user_options = [ 43 | o for o in build_ext.user_options if o[1] is not option.short 44 | ] 45 | else: 46 | # Just check if the option already exists, and raise if it does 47 | for o in build_ext.user_options: 48 | if o[1] == option.short: 49 | raise ValueError(f"Short option '{o[1]}' already exists") 50 | 51 | # The long variable name must finish with =, here we append it 52 | option = option._replace(variable=f"{option.variable}=") 53 | 54 | # Add the new option 55 | build_ext.user_options.append(tuple(option)) 56 | -------------------------------------------------------------------------------- /src/cmake_build_extension/build_extension.py: -------------------------------------------------------------------------------- 1 | import importlib.util 2 | import os 3 | import platform 4 | import shutil 5 | import subprocess 6 | from pathlib import Path 7 | 8 | from setuptools.command.build_ext import build_ext 9 | 10 | from .build_ext_option import BuildExtOption, add_new_build_ext_option 11 | from .cmake_extension import CMakeExtension 12 | 13 | # These options are listed in `python setup.py build_ext -h` 14 | custom_options = [ 15 | BuildExtOption( 16 | variable="define", 17 | short="D", 18 | help="Create or update CMake cache " "(example: '-DBAR=b;FOO=f')", 19 | ), 20 | BuildExtOption( 21 | variable="component", 22 | short="C", 23 | help="Install only a specific CMake component (example: '-Cbindings')", 24 | ), 25 | BuildExtOption( 26 | variable="no-cmake-extension", 27 | short="K", 28 | help="Disable a CMakeExtension module (examples: '-Kall', '-Kbar', '-Kbar;foo')", 29 | ), 30 | ] 31 | 32 | for o in custom_options: 33 | add_new_build_ext_option(option=o, override=True) 34 | 35 | 36 | class BuildExtension(build_ext): 37 | """ 38 | Setuptools build extension handler. 39 | It processes all the extensions listed in the 'ext_modules' entry. 40 | """ 41 | 42 | def initialize_options(self): 43 | 44 | # Initialize base class 45 | build_ext.initialize_options(self) 46 | 47 | # Initialize the '--define' custom option, overriding the pre-existing one. 48 | # Originally, it was aimed to pass C preprocessor definitions, but instead we 49 | # use it to pass custom configuration options to CMake. 50 | self.define = None 51 | 52 | # Initialize the '--component' custom option. 53 | # It overrides the content of the cmake_component option of CMakeExtension. 54 | self.component = None 55 | 56 | # Initialize the 'no-cmake-extension' custom option. 57 | # It allows disabling one or more CMakeExtension from the command line. 58 | self.no_cmake_extension = None 59 | 60 | def finalize_options(self): 61 | 62 | # Parse the custom CMake options and store them in a new attribute 63 | defines = [] if self.define is None else self.define.split(";") 64 | self.cmake_defines = [f"-D{define}" for define in defines] 65 | 66 | # Parse the disabled CMakeExtension modules and store them in a new attribute 67 | self.no_cmake_extensions = ( 68 | [] 69 | if self.no_cmake_extension is None 70 | else self.no_cmake_extension.split(";") 71 | ) 72 | 73 | # Call base class 74 | build_ext.finalize_options(self) 75 | 76 | def run(self) -> None: 77 | """ 78 | Process all the registered extensions executing only the CMakeExtension objects. 79 | """ 80 | 81 | # Filter the CMakeExtension objects 82 | cmake_extensions = [e for e in self.extensions if isinstance(e, CMakeExtension)] 83 | 84 | if len(cmake_extensions) == 0: 85 | raise ValueError("No CMakeExtension objects found") 86 | 87 | # Check that CMake is installed 88 | if shutil.which("cmake") is None: 89 | raise RuntimeError("Required command 'cmake' not found") 90 | 91 | for ext in cmake_extensions: 92 | # Check that Ninja is installed 93 | if (ext.cmake_generator and 94 | ext.cmake_generator.lower() == "ninja" and 95 | shutil.which("ninja") is None): 96 | raise RuntimeError("Required command 'ninja' not found") 97 | 98 | # Disable the extension if specified in the command line 99 | if ( 100 | ext.name in self.no_cmake_extensions 101 | or "all" in self.no_cmake_extensions 102 | ): 103 | continue 104 | 105 | # Disable all extensions if this env variable is present 106 | disabled_set = {"0", "false", "off", "no"} 107 | env_var_name = "CMAKE_BUILD_EXTENSION_ENABLED" 108 | if ( 109 | env_var_name in os.environ 110 | and os.environ[env_var_name].lower() in disabled_set 111 | ): 112 | continue 113 | 114 | self.build_extension(ext) 115 | 116 | def build_extension(self, ext: CMakeExtension) -> None: 117 | """ 118 | Build a CMakeExtension object. 119 | 120 | Args: 121 | ext: The CMakeExtension object to build. 122 | """ 123 | 124 | if self.inplace and ext.disable_editable: 125 | print(f"Editable install recognized. Extension '{ext.name}' disabled.") 126 | return 127 | 128 | # Export CMAKE_PREFIX_PATH of all the dependencies 129 | for pkg in ext.cmake_depends_on: 130 | 131 | try: 132 | importlib.import_module(pkg) 133 | except ImportError: 134 | raise ValueError(f"Failed to import '{pkg}'") 135 | 136 | init = importlib.util.find_spec(pkg).origin 137 | BuildExtension.extend_cmake_prefix_path(path=str(Path(init).parent)) 138 | 139 | # The ext_dir directory can be thought as a temporary site-package folder. 140 | # 141 | # Case 1: regular installation. 142 | # ext_dir is the folder that gets compressed to make the wheel archive. When 143 | # installed, the archive is extracted in the active site-package directory. 144 | # Case 2: editable installation. 145 | # ext_dir is the in-source folder containing the Python packages. In this case, 146 | # the CMake project is installed in-source. 147 | ext_dir = Path(self.get_ext_fullpath(ext.name)).parent.absolute() 148 | cmake_install_prefix = ext_dir / ext.install_prefix 149 | 150 | # Initialize the CMake configuration arguments 151 | configure_args = [] 152 | 153 | # Select the appropriate generator and accompanying settings 154 | if ext.cmake_generator is not None: 155 | configure_args += ["-G", ext.cmake_generator] 156 | 157 | if ext.cmake_generator == "Ninja": 158 | # Fix #26: https://github.com/diegoferigo/cmake-build-extension/issues/26 159 | configure_args += [f"-DCMAKE_MAKE_PROGRAM={shutil.which('ninja')}"] 160 | 161 | # CMake configure arguments 162 | configure_args += [ 163 | f"-DCMAKE_BUILD_TYPE={ext.cmake_build_type}", 164 | f"-DCMAKE_INSTALL_PREFIX:PATH={cmake_install_prefix}", 165 | ] 166 | 167 | # Extend the configure arguments with those passed from the extension 168 | configure_args += ext.cmake_configure_options 169 | 170 | # CMake build arguments 171 | build_args = ["--config", ext.cmake_build_type] 172 | 173 | # CMake install arguments 174 | install_args = ["--config", ext.cmake_build_type] 175 | 176 | if platform.system() == "Windows": 177 | 178 | configure_args += [] 179 | 180 | elif platform.system() in {"Linux", "Darwin", "GNU"}: 181 | 182 | configure_args += [] 183 | 184 | else: 185 | raise RuntimeError(f"Unsupported '{platform.system()}' platform") 186 | 187 | # Parse the optional CMake options. They can be passed as: 188 | # 189 | # python setup.py build_ext -D"BAR=Foo;VAR=TRUE" 190 | # python setup.py bdist_wheel build_ext -D"BAR=Foo;VAR=TRUE" 191 | # python setup.py install build_ext -D"BAR=Foo;VAR=TRUE" 192 | # python setup.py install -e build_ext -D"BAR=Foo;VAR=TRUE" 193 | # pip install --global-option="build_ext" --global-option="-DBAR=Foo;VAR=TRUE" . 194 | # 195 | configure_args += self.cmake_defines 196 | 197 | # Get the absolute path to the build folder 198 | build_folder = str(Path(".").absolute() / f"{self.build_temp}_{ext.name}") 199 | 200 | # Make sure that the build folder exists 201 | Path(build_folder).mkdir(exist_ok=True, parents=True) 202 | 203 | # 1. Compose CMake configure command 204 | configure_command = [ 205 | "cmake", 206 | "-S", 207 | ext.source_dir, 208 | "-B", 209 | build_folder, 210 | ] + configure_args 211 | 212 | # 2. Compose CMake build command 213 | build_command = ["cmake", "--build", build_folder] + build_args 214 | 215 | # 3. Compose CMake install command 216 | install_command = ["cmake", "--install", build_folder] + install_args 217 | 218 | # If the cmake_component option of the CMakeExtension is used, install just 219 | # the specified component. 220 | if self.component is None and ext.cmake_component is not None: 221 | install_command.extend(["--component", ext.cmake_component]) 222 | 223 | # Instead, if the `--component` command line option is used, install just 224 | # the specified component. This has higher priority than what specified in 225 | # the CMakeExtension. 226 | if self.component is not None: 227 | install_command.extend(["--component", self.component]) 228 | 229 | print("") 230 | print("==> Configuring:") 231 | print(f"$ {' '.join(configure_command)}") 232 | print("") 233 | print("==> Building:") 234 | print(f"$ {' '.join(build_command)}") 235 | print("") 236 | print("==> Installing:") 237 | print(f"$ {' '.join(install_command)}") 238 | print("") 239 | 240 | # Call CMake 241 | subprocess.check_call(configure_command) 242 | subprocess.check_call(build_command) 243 | subprocess.check_call(install_command) 244 | 245 | # Write content to the top-level __init__.py 246 | if ext.write_top_level_init is not None: 247 | with open(file=cmake_install_prefix / "__init__.py", mode="w") as f: 248 | f.write(ext.write_top_level_init) 249 | 250 | # Write content to the bin/__main__.py magic file to expose binaries 251 | if len(ext.expose_binaries) > 0: 252 | bin_dirs = {str(Path(d).parents[0]) for d in ext.expose_binaries} 253 | 254 | import inspect 255 | 256 | main_py = inspect.cleandoc( 257 | f""" 258 | from pathlib import Path 259 | import subprocess 260 | import sys 261 | 262 | def main(): 263 | 264 | binary_name = Path(sys.argv[0]).name 265 | prefix = Path(__file__).parent.parent 266 | bin_dirs = {str(bin_dirs)} 267 | 268 | binary_path = "" 269 | 270 | for dir in bin_dirs: 271 | path = prefix / Path(dir) / binary_name 272 | if path.is_file(): 273 | binary_path = str(path) 274 | break 275 | 276 | path = Path(str(path) + ".exe") 277 | if path.is_file(): 278 | binary_path = str(path) 279 | break 280 | 281 | if not Path(binary_path).is_file(): 282 | name = binary_path if binary_path != "" else binary_name 283 | raise RuntimeError(f"Failed to find binary: {{ name }}") 284 | 285 | sys.argv[0] = binary_path 286 | 287 | result = subprocess.run(args=sys.argv, capture_output=False) 288 | exit(result.returncode) 289 | 290 | if __name__ == "__main__" and len(sys.argv) > 1: 291 | sys.argv = sys.argv[1:] 292 | main()""" 293 | ) 294 | 295 | bin_folder = cmake_install_prefix / "bin" 296 | Path(bin_folder).mkdir(exist_ok=True, parents=True) 297 | with open(file=bin_folder / "__main__.py", mode="w") as f: 298 | f.write(main_py) 299 | 300 | @staticmethod 301 | def extend_cmake_prefix_path(path: str) -> None: 302 | 303 | abs_path = Path(path).absolute() 304 | 305 | if not abs_path.exists(): 306 | raise ValueError(f"Path {abs_path} does not exist") 307 | 308 | if "CMAKE_PREFIX_PATH" in os.environ: 309 | os.environ[ 310 | "CMAKE_PREFIX_PATH" 311 | ] = f"{str(path)}:{os.environ['CMAKE_PREFIX_PATH']}" 312 | else: 313 | os.environ["CMAKE_PREFIX_PATH"] = str(path) 314 | -------------------------------------------------------------------------------- /src/cmake_build_extension/cmake_extension.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from typing import List 3 | 4 | from setuptools import Extension 5 | 6 | 7 | class CMakeExtension(Extension): 8 | """ 9 | Custom setuptools extension that configures a CMake project. 10 | 11 | Args: 12 | name: The name of the extension. 13 | install_prefix: The path relative to the site-package directory where the CMake 14 | project is installed (typically the name of the Python package). 15 | disable_editable: Skip this extension in editable mode. 16 | write_top_level_init: Create a new top-level ``__init__.py`` file in the install 17 | prefix and write content. 18 | cmake_configure_options: List of additional CMake configure options (-DBAR=FOO). 19 | source_dir: The location of the main CMakeLists.txt. 20 | cmake_build_type: The default build type of the CMake project. 21 | cmake_component: The name of component to install. Defaults to all components. 22 | cmake_depends_on: List of dependency packages containing required CMake projects. 23 | expose_binaries: List of binary paths to expose, relative to top-level directory. 24 | cmake_generator: The generator to be used by CMake. Defaults to Ninja. 25 | """ 26 | 27 | def __init__( 28 | self, 29 | name: str, 30 | install_prefix: str = "", 31 | disable_editable: bool = False, 32 | write_top_level_init: str = None, 33 | cmake_configure_options: List[str] = (), 34 | source_dir: str = str(Path(".").absolute()), 35 | cmake_build_type: str = "Release", 36 | cmake_component: str = None, 37 | cmake_depends_on: List[str] = (), 38 | expose_binaries: List[str] = (), 39 | cmake_generator: str = "Ninja", 40 | ): 41 | 42 | super().__init__(name=name, sources=[]) 43 | 44 | if not Path(source_dir).is_absolute(): 45 | source_dir = str(Path(".").absolute() / source_dir) 46 | 47 | if not Path(source_dir).absolute().is_dir(): 48 | raise ValueError(f"Directory '{source_dir}' does not exist") 49 | 50 | self.install_prefix = install_prefix 51 | self.cmake_build_type = cmake_build_type 52 | self.disable_editable = disable_editable 53 | self.write_top_level_init = write_top_level_init 54 | self.cmake_depends_on = cmake_depends_on 55 | self.source_dir = str(Path(source_dir).absolute()) 56 | self.cmake_configure_options = cmake_configure_options 57 | self.cmake_component = cmake_component 58 | self.expose_binaries = expose_binaries 59 | self.cmake_generator = cmake_generator 60 | -------------------------------------------------------------------------------- /src/cmake_build_extension/sdist_command.py: -------------------------------------------------------------------------------- 1 | import abc 2 | import os 3 | from pathlib import Path 4 | from shutil import copy2 5 | from typing import Generator, List 6 | 7 | import setuptools.command.sdist 8 | 9 | 10 | class GitSdistABC(abc.ABC, setuptools.command.sdist.sdist): 11 | """ 12 | This class defines a custom command to build source distribution. It covers the case 13 | where projects store the setup.cfg file in a subfolder and are git repositories. 14 | 15 | The problem in this setup is that only the subfolder by default is packaged 16 | in the sdist, resulting in a archive that only contains part of the whole repo. 17 | """ 18 | 19 | def make_release_tree(self, base_dir, files) -> None: 20 | """ 21 | This method is the responsible of building the list of files that are included 22 | in the source distribution. 23 | 24 | These files (that could be the entire git tree) are copied in the subfolder 25 | before creating the archive, resulting in a source distribution like if the 26 | setup.cfg would be part of the top-level folder. 27 | 28 | This method prepares the egg metadata for the source distribution and allows 29 | specifying a list of files that are copied in the location of the setup.cfg. 30 | """ 31 | 32 | import setuptools_scm.integration 33 | 34 | # Build the setuptools_scm configuration, containing useful info for the sdist 35 | config: setuptools_scm.integration.Configuration = ( 36 | setuptools_scm.integration.Configuration.from_file( 37 | dist_name=self.distribution.metadata.name 38 | ) 39 | ) 40 | 41 | # Get the root of the git repository 42 | repo_root = config.absolute_root 43 | 44 | if not Path(repo_root).exists() or not Path(repo_root).is_dir(): 45 | raise RuntimeError(f"Failed to find a git repo in {repo_root}") 46 | 47 | # Prepare the release tree by calling the original method 48 | super(GitSdistABC, self).make_release_tree(base_dir=base_dir, files=files) 49 | 50 | # Collect all the files and copy them in the subfolder containing setup.cfg 51 | for file in self.get_sdist_files(repo_root=repo_root): 52 | 53 | src = Path(file) 54 | dst = Path(base_dir) / Path(file).relative_to(repo_root) 55 | 56 | # Make sure that the parent directory of the destination exists 57 | dst.absolute().parent.mkdir(parents=True, exist_ok=True) 58 | 59 | print(f"{Path(file).relative_to(repo_root)} -> {dst}") 60 | copy2(src=src, dst=dst) 61 | 62 | # Create the updated list of files included in the sdist 63 | all_files_gen = Path(base_dir).glob(pattern="**/*") 64 | all_files = [str(f.relative_to(base_dir)) for f in all_files_gen] 65 | 66 | # Find the SOURCES.txt file 67 | sources_txt_list = list(Path(base_dir).glob(pattern=f"*.egg-info/SOURCES.txt")) 68 | assert len(sources_txt_list) == 1 69 | 70 | # Update the SOURCES.txt files with the real content of the sdist 71 | os.unlink(sources_txt_list[0]) 72 | with open(file=sources_txt_list[0], mode="w") as f: 73 | f.write("\n".join([str(f) for f in all_files])) 74 | 75 | @staticmethod 76 | @abc.abstractmethod 77 | def get_sdist_files(repo_root: str) -> List[Path]: 78 | """ 79 | Return all files that will be included in the source distribution. 80 | 81 | Note: the egg metadata are included by default, there's not need to specify them. 82 | 83 | Args: 84 | repo_root: The path to the root of the git repository. 85 | 86 | Returns: 87 | The list of files to include in the source distribution. 88 | """ 89 | 90 | 91 | class GitSdistTree(GitSdistABC): 92 | """ 93 | This class defines a custom command to build source distribution. It covers the case 94 | where projects store the setup.cfg file in a subfolder and are git repositories. 95 | 96 | The problem in this setup is that only the subfolder by default is packaged 97 | in the sdist, resulting in a archive that only contains part of the whole repo. 98 | 99 | In particular, this class copies all the files that are part of the last git commit. 100 | Any uncommitted or staged files are ignored and are not part of the sdist. 101 | """ 102 | 103 | @staticmethod 104 | def get_sdist_files(repo_root: str) -> List[Path]: 105 | 106 | import git 107 | 108 | # Create the git Repo object 109 | git_repo = git.Repo(path=repo_root) 110 | 111 | # Get all the files of the git repo recursively 112 | def list_paths( 113 | tree: git.Tree, path: Path = Path(".") 114 | ) -> Generator[Path, None, None]: 115 | 116 | for blob in tree.blobs: 117 | yield path / blob.name 118 | 119 | for tree in tree.trees: 120 | yield from list_paths(tree=tree, path=path / tree.name) 121 | 122 | # Return the list of absolute paths to all the git repo files 123 | return list(list_paths(tree=git_repo.commit().tree, path=Path(repo_root))) 124 | 125 | 126 | class GitSdistFolder(GitSdistABC): 127 | """ 128 | This class defines a custom command to build source distribution. It covers the case 129 | where projects store the setup.cfg file in a subfolder and are git repositories. 130 | 131 | The problem in this setup is that only the subfolder by default is packaged 132 | in the sdist, resulting in a archive that only contains part of the whole repo. 133 | 134 | In particular, this class copies all the files that are part of the git folder. 135 | It includes also all uncommitted and staged files. 136 | """ 137 | 138 | @staticmethod 139 | def get_sdist_files(repo_root: str) -> List[Path]: 140 | 141 | # Create the list of files of the git folder 142 | all_files_gen = Path(repo_root).glob(pattern="**/*") 143 | 144 | # Return the list of absolute paths to all the git folder files (also uncommited) 145 | return [f for f in all_files_gen if not f.is_dir() and ".git" not in f.parts] 146 | --------------------------------------------------------------------------------