funktionsklempner 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. funktionsklempner-1.0.0/.gitlab-ci.yml +22 -0
  2. funktionsklempner-1.0.0/LICENSE +287 -0
  3. funktionsklempner-1.0.0/PKG-INFO +296 -0
  4. funktionsklempner-1.0.0/README.md +280 -0
  5. funktionsklempner-1.0.0/example/LICENSE +25 -0
  6. funktionsklempner-1.0.0/example/README.md +2 -0
  7. funktionsklempner-1.0.0/example/cpp/example.cpp +143 -0
  8. funktionsklempner-1.0.0/example/cpp/example.hpp +79 -0
  9. funktionsklempner-1.0.0/example/funktionsklempner.toml +10 -0
  10. funktionsklempner-1.0.0/example/funkybadger/__init__.py +7 -0
  11. funktionsklempner-1.0.0/example/meson.build +20 -0
  12. funktionsklempner-1.0.0/example/pyproject.toml +27 -0
  13. funktionsklempner-1.0.0/example/testing/test.py +96 -0
  14. funktionsklempner-1.0.0/get_file.py +52 -0
  15. funktionsklempner-1.0.0/meson.build +222 -0
  16. funktionsklempner-1.0.0/pyproject.toml +30 -0
  17. funktionsklempner-1.0.0/pysrc/__init__.py +0 -0
  18. funktionsklempner-1.0.0/pysrc/fklpr_base/__init__.py +0 -0
  19. funktionsklempner-1.0.0/pysrc/fklpr_base/templates/quantityarray.py +57 -0
  20. funktionsklempner-1.0.0/pysrc/fklpr_base/templates/wrapper.py +165 -0
  21. funktionsklempner-1.0.0/pysrc/generate/__init__.py +26 -0
  22. funktionsklempner-1.0.0/pysrc/generate/boilerplate.py +92 -0
  23. funktionsklempner-1.0.0/pysrc/generate/cpp.py +86 -0
  24. funktionsklempner-1.0.0/pysrc/generate/python.py +119 -0
  25. funktionsklempner-1.0.0/pysrc/language/__init__.py +22 -0
  26. funktionsklempner-1.0.0/pysrc/language/abstract.py +177 -0
  27. funktionsklempner-1.0.0/pysrc/language/arrays.py +82 -0
  28. funktionsklempner-1.0.0/pysrc/language/conversion.py +229 -0
  29. funktionsklempner-1.0.0/pysrc/language/cpp.py +89 -0
  30. funktionsklempner-1.0.0/pysrc/language/fundamental.py +167 -0
  31. funktionsklempner-1.0.0/pysrc/language/python.py +139 -0
  32. funktionsklempner-1.0.0/pysrc/language/strings.py +86 -0
  33. funktionsklempner-1.0.0/pysrc/parse/__init__.py +24 -0
  34. funktionsklempner-1.0.0/pysrc/parse/function.py +142 -0
  35. funktionsklempner-1.0.0/pysrc/parse/library.py +153 -0
  36. funktionsklempner-1.0.0/pysrc/parse/macros.py +29 -0
  37. funktionsklempner-1.0.0/pysrc/parse/parse.py +434 -0
  38. funktionsklempner-1.0.0/pysrc/parse/sizecontrol.py +54 -0
  39. funktionsklempner-1.0.0/pysrc/parse/spdx.py +157 -0
  40. funktionsklempner-1.0.0/pysrc/parse/struct.py +74 -0
  41. funktionsklempner-1.0.0/pysrc/parse/usertypes.py +49 -0
  42. funktionsklempner-1.0.0/pysrc/parse/variable.py +298 -0
  43. funktionsklempner-1.0.0/pysrc/py.typed +0 -0
  44. funktionsklempner-1.0.0/pysrc/repo/__init__.py +30 -0
  45. funktionsklempner-1.0.0/pysrc/repo/paths.py +219 -0
  46. funktionsklempner-1.0.0/pysrc/repo/repository.py +47 -0
  47. funktionsklempner-1.0.0/pysrc/repo/tomllib.py +172 -0
  48. funktionsklempner-1.0.0/pysrc/scripts/__init__.py +827 -0
  49. funktionsklempner-1.0.0/pysrc/scripts/pre-commit +18 -0
  50. funktionsklempner-1.0.0/pysrc/tools/__init__.py +27 -0
  51. funktionsklempner-1.0.0/pysrc/tools/views.py +100 -0
  52. funktionsklempner-1.0.0/pysrc/wrap/__init__.py +22 -0
  53. funktionsklempner-1.0.0/pysrc/wrap/array.py +607 -0
  54. funktionsklempner-1.0.0/pysrc/wrap/function.py +421 -0
  55. funktionsklempner-1.0.0/pysrc/wrap/input.py +174 -0
  56. funktionsklempner-1.0.0/pysrc/wrap/library.py +69 -0
  57. funktionsklempner-1.0.0/pysrc/wrap/out.py +124 -0
  58. funktionsklempner-1.0.0/pysrc/wrap/paralist.py +105 -0
  59. funktionsklempner-1.0.0/pysrc/wrap/parameter.py +477 -0
  60. funktionsklempner-1.0.0/pysrc/wrap/string.py +220 -0
  61. funktionsklempner-1.0.0/pysrc/wrap/variablegraph.py +291 -0
  62. funktionsklempner-1.0.0/subprojects/boost-1.90.0.wrap +4 -0
  63. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/call.hpp +85 -0
  64. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/cdecl.hpp +61 -0
  65. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/default_units.hpp +320 -0
  66. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/fixedmap.hpp +95 -0
  67. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/funktionsklempner.hpp +52 -0
  68. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/math.hpp +160 -0
  69. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/ndarray.hpp +132 -0
  70. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/numpytypes.hpp +202 -0
  71. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/quantityarray.hpp +526 -0
  72. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/scalar.hpp +110 -0
  73. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/strings.cpp +118 -0
  74. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/strings.hpp +83 -0
  75. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/tartanllama/expected.hpp +2475 -0
  76. funktionsklempner-1.0.0/subprojects/funktionsklempner/funktionsklempner/units.hpp +696 -0
  77. funktionsklempner-1.0.0/subprojects/funktionsklempner/meson.build +82 -0
  78. funktionsklempner-1.0.0/subprojects/gcem.wrap +6 -0
  79. funktionsklempner-1.0.0/subprojects/objektbuch.wrap +3 -0
  80. funktionsklempner-1.0.0/subprojects/packagefiles/boost/meson.build +8 -0
  81. funktionsklempner-1.0.0/subprojects/packagefiles/boost-1.90.0_units.tar.gz +0 -0
  82. funktionsklempner-1.0.0/subprojects/packagefiles/gcem/meson.build +7 -0
  83. funktionsklempner-1.0.0/test_suite.py +204 -0
  84. funktionsklempner-1.0.0/testsuite/Dockerfile +62 -0
  85. funktionsklempner-1.0.0/testsuite/cpp_src/quantityarray.cpp +360 -0
  86. funktionsklempner-1.0.0/testsuite/cpp_src/units.cpp +194 -0
  87. funktionsklempner-1.0.0/testsuite/funktionsklempner.wrap +3 -0
  88. funktionsklempner-1.0.0/testsuite/pytest/test_tools.py +21 -0
@@ -0,0 +1,22 @@
1
+ # You can override the included template(s) by including variable overrides
2
+ # SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
3
+ # Secret Detection customization: https://docs.gitlab.com/user/application_security/secret_detection/pipeline/configure
4
+ # Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
5
+ # Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
6
+ # Note that environment variables can be set in several places
7
+ # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
8
+ :stages:
9
+ - test
10
+ :sast:
11
+ :stage: test
12
+ :include:
13
+ - :template: Security/SAST.gitlab-ci.yml
14
+ stages:
15
+ - test
16
+ - secret-detection
17
+ variables:
18
+ SECRET_DETECTION_ENABLED: 'true'
19
+ secret_detection:
20
+ stage: secret-detection
21
+ include:
22
+ - template: Security/Secret-Detection.gitlab-ci.yml
@@ -0,0 +1,287 @@
1
+ EUROPEAN UNION PUBLIC LICENCE v. 1.2
2
+ EUPL © the European Union 2007, 2016
3
+
4
+ This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
5
+ below) which is provided under the terms of this Licence. Any use of the Work,
6
+ other than as authorised under this Licence is prohibited (to the extent such
7
+ use is covered by a right of the copyright holder of the Work).
8
+
9
+ The Work is provided under the terms of this Licence when the Licensor (as
10
+ defined below) has placed the following notice immediately following the
11
+ copyright notice for the Work:
12
+
13
+ Licensed under the EUPL
14
+
15
+ or has expressed by any other means his willingness to license under the EUPL.
16
+
17
+ 1. Definitions
18
+
19
+ In this Licence, the following terms have the following meaning:
20
+
21
+ - ‘The Licence’: this Licence.
22
+
23
+ - ‘The Original Work’: the work or software distributed or communicated by the
24
+ Licensor under this Licence, available as Source Code and also as Executable
25
+ Code as the case may be.
26
+
27
+ - ‘Derivative Works’: the works or software that could be created by the
28
+ Licensee, based upon the Original Work or modifications thereof. This Licence
29
+ does not define the extent of modification or dependence on the Original Work
30
+ required in order to classify a work as a Derivative Work; this extent is
31
+ determined by copyright law applicable in the country mentioned in Article 15.
32
+
33
+ - ‘The Work’: the Original Work or its Derivative Works.
34
+
35
+ - ‘The Source Code’: the human-readable form of the Work which is the most
36
+ convenient for people to study and modify.
37
+
38
+ - ‘The Executable Code’: any code which has generally been compiled and which is
39
+ meant to be interpreted by a computer as a program.
40
+
41
+ - ‘The Licensor’: the natural or legal person that distributes or communicates
42
+ the Work under the Licence.
43
+
44
+ - ‘Contributor(s)’: any natural or legal person who modifies the Work under the
45
+ Licence, or otherwise contributes to the creation of a Derivative Work.
46
+
47
+ - ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
48
+ the Work under the terms of the Licence.
49
+
50
+ - ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
51
+ renting, distributing, communicating, transmitting, or otherwise making
52
+ available, online or offline, copies of the Work or providing access to its
53
+ essential functionalities at the disposal of any other natural or legal
54
+ person.
55
+
56
+ 2. Scope of the rights granted by the Licence
57
+
58
+ The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
59
+ sublicensable licence to do the following, for the duration of copyright vested
60
+ in the Original Work:
61
+
62
+ - use the Work in any circumstance and for all usage,
63
+ - reproduce the Work,
64
+ - modify the Work, and make Derivative Works based upon the Work,
65
+ - communicate to the public, including the right to make available or display
66
+ the Work or copies thereof to the public and perform publicly, as the case may
67
+ be, the Work,
68
+ - distribute the Work or copies thereof,
69
+ - lend and rent the Work or copies thereof,
70
+ - sublicense rights in the Work or copies thereof.
71
+
72
+ Those rights can be exercised on any media, supports and formats, whether now
73
+ known or later invented, as far as the applicable law permits so.
74
+
75
+ In the countries where moral rights apply, the Licensor waives his right to
76
+ exercise his moral right to the extent allowed by law in order to make effective
77
+ the licence of the economic rights here above listed.
78
+
79
+ The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
80
+ any patents held by the Licensor, to the extent necessary to make use of the
81
+ rights granted on the Work under this Licence.
82
+
83
+ 3. Communication of the Source Code
84
+
85
+ The Licensor may provide the Work either in its Source Code form, or as
86
+ Executable Code. If the Work is provided as Executable Code, the Licensor
87
+ provides in addition a machine-readable copy of the Source Code of the Work
88
+ along with each copy of the Work that the Licensor distributes or indicates, in
89
+ a notice following the copyright notice attached to the Work, a repository where
90
+ the Source Code is easily and freely accessible for as long as the Licensor
91
+ continues to distribute or communicate the Work.
92
+
93
+ 4. Limitations on copyright
94
+
95
+ Nothing in this Licence is intended to deprive the Licensee of the benefits from
96
+ any exception or limitation to the exclusive rights of the rights owners in the
97
+ Work, of the exhaustion of those rights or of other applicable limitations
98
+ thereto.
99
+
100
+ 5. Obligations of the Licensee
101
+
102
+ The grant of the rights mentioned above is subject to some restrictions and
103
+ obligations imposed on the Licensee. Those obligations are the following:
104
+
105
+ Attribution right: The Licensee shall keep intact all copyright, patent or
106
+ trademarks notices and all notices that refer to the Licence and to the
107
+ disclaimer of warranties. The Licensee must include a copy of such notices and a
108
+ copy of the Licence with every copy of the Work he/she distributes or
109
+ communicates. The Licensee must cause any Derivative Work to carry prominent
110
+ notices stating that the Work has been modified and the date of modification.
111
+
112
+ Copyleft clause: If the Licensee distributes or communicates copies of the
113
+ Original Works or Derivative Works, this Distribution or Communication will be
114
+ done under the terms of this Licence or of a later version of this Licence
115
+ unless the Original Work is expressly distributed only under this version of the
116
+ Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
117
+ (becoming Licensor) cannot offer or impose any additional terms or conditions on
118
+ the Work or Derivative Work that alter or restrict the terms of the Licence.
119
+
120
+ Compatibility clause: If the Licensee Distributes or Communicates Derivative
121
+ Works or copies thereof based upon both the Work and another work licensed under
122
+ a Compatible Licence, this Distribution or Communication can be done under the
123
+ terms of this Compatible Licence. For the sake of this clause, ‘Compatible
124
+ Licence’ refers to the licences listed in the appendix attached to this Licence.
125
+ Should the Licensee's obligations under the Compatible Licence conflict with
126
+ his/her obligations under this Licence, the obligations of the Compatible
127
+ Licence shall prevail.
128
+
129
+ Provision of Source Code: When distributing or communicating copies of the Work,
130
+ the Licensee will provide a machine-readable copy of the Source Code or indicate
131
+ a repository where this Source will be easily and freely available for as long
132
+ as the Licensee continues to distribute or communicate the Work.
133
+
134
+ Legal Protection: This Licence does not grant permission to use the trade names,
135
+ trademarks, service marks, or names of the Licensor, except as required for
136
+ reasonable and customary use in describing the origin of the Work and
137
+ reproducing the content of the copyright notice.
138
+
139
+ 6. Chain of Authorship
140
+
141
+ The original Licensor warrants that the copyright in the Original Work granted
142
+ hereunder is owned by him/her or licensed to him/her and that he/she has the
143
+ power and authority to grant the Licence.
144
+
145
+ Each Contributor warrants that the copyright in the modifications he/she brings
146
+ to the Work are owned by him/her or licensed to him/her and that he/she has the
147
+ power and authority to grant the Licence.
148
+
149
+ Each time You accept the Licence, the original Licensor and subsequent
150
+ Contributors grant You a licence to their contributions to the Work, under the
151
+ terms of this Licence.
152
+
153
+ 7. Disclaimer of Warranty
154
+
155
+ The Work is a work in progress, which is continuously improved by numerous
156
+ Contributors. It is not a finished work and may therefore contain defects or
157
+ ‘bugs’ inherent to this type of development.
158
+
159
+ For the above reason, the Work is provided under the Licence on an ‘as is’ basis
160
+ and without warranties of any kind concerning the Work, including without
161
+ limitation merchantability, fitness for a particular purpose, absence of defects
162
+ or errors, accuracy, non-infringement of intellectual property rights other than
163
+ copyright as stated in Article 6 of this Licence.
164
+
165
+ This disclaimer of warranty is an essential part of the Licence and a condition
166
+ for the grant of any rights to the Work.
167
+
168
+ 8. Disclaimer of Liability
169
+
170
+ Except in the cases of wilful misconduct or damages directly caused to natural
171
+ persons, the Licensor will in no event be liable for any direct or indirect,
172
+ material or moral, damages of any kind, arising out of the Licence or of the use
173
+ of the Work, including without limitation, damages for loss of goodwill, work
174
+ stoppage, computer failure or malfunction, loss of data or any commercial
175
+ damage, even if the Licensor has been advised of the possibility of such damage.
176
+ However, the Licensor will be liable under statutory product liability laws as
177
+ far such laws apply to the Work.
178
+
179
+ 9. Additional agreements
180
+
181
+ While distributing the Work, You may choose to conclude an additional agreement,
182
+ defining obligations or services consistent with this Licence. However, if
183
+ accepting obligations, You may act only on your own behalf and on your sole
184
+ responsibility, not on behalf of the original Licensor or any other Contributor,
185
+ and only if You agree to indemnify, defend, and hold each Contributor harmless
186
+ for any liability incurred by, or claims asserted against such Contributor by
187
+ the fact You have accepted any warranty or additional liability.
188
+
189
+ 10. Acceptance of the Licence
190
+
191
+ The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
192
+ placed under the bottom of a window displaying the text of this Licence or by
193
+ affirming consent in any other similar way, in accordance with the rules of
194
+ applicable law. Clicking on that icon indicates your clear and irrevocable
195
+ acceptance of this Licence and all of its terms and conditions.
196
+
197
+ Similarly, you irrevocably accept this Licence and all of its terms and
198
+ conditions by exercising any rights granted to You by Article 2 of this Licence,
199
+ such as the use of the Work, the creation by You of a Derivative Work or the
200
+ Distribution or Communication by You of the Work or copies thereof.
201
+
202
+ 11. Information to the public
203
+
204
+ In case of any Distribution or Communication of the Work by means of electronic
205
+ communication by You (for example, by offering to download the Work from a
206
+ remote location) the distribution channel or media (for example, a website) must
207
+ at least provide to the public the information requested by the applicable law
208
+ regarding the Licensor, the Licence and the way it may be accessible, concluded,
209
+ stored and reproduced by the Licensee.
210
+
211
+ 12. Termination of the Licence
212
+
213
+ The Licence and the rights granted hereunder will terminate automatically upon
214
+ any breach by the Licensee of the terms of the Licence.
215
+
216
+ Such a termination will not terminate the licences of any person who has
217
+ received the Work from the Licensee under the Licence, provided such persons
218
+ remain in full compliance with the Licence.
219
+
220
+ 13. Miscellaneous
221
+
222
+ Without prejudice of Article 9 above, the Licence represents the complete
223
+ agreement between the Parties as to the Work.
224
+
225
+ If any provision of the Licence is invalid or unenforceable under applicable
226
+ law, this will not affect the validity or enforceability of the Licence as a
227
+ whole. Such provision will be construed or reformed so as necessary to make it
228
+ valid and enforceable.
229
+
230
+ The European Commission may publish other linguistic versions or new versions of
231
+ this Licence or updated versions of the Appendix, so far this is required and
232
+ reasonable, without reducing the scope of the rights granted by the Licence. New
233
+ versions of the Licence will be published with a unique version number.
234
+
235
+ All linguistic versions of this Licence, approved by the European Commission,
236
+ have identical value. Parties can take advantage of the linguistic version of
237
+ their choice.
238
+
239
+ 14. Jurisdiction
240
+
241
+ Without prejudice to specific agreement between parties,
242
+
243
+ - any litigation resulting from the interpretation of this License, arising
244
+ between the European Union institutions, bodies, offices or agencies, as a
245
+ Licensor, and any Licensee, will be subject to the jurisdiction of the Court
246
+ of Justice of the European Union, as laid down in article 272 of the Treaty on
247
+ the Functioning of the European Union,
248
+
249
+ - any litigation arising between other parties and resulting from the
250
+ interpretation of this License, will be subject to the exclusive jurisdiction
251
+ of the competent court where the Licensor resides or conducts its primary
252
+ business.
253
+
254
+ 15. Applicable Law
255
+
256
+ Without prejudice to specific agreement between parties,
257
+
258
+ - this Licence shall be governed by the law of the European Union Member State
259
+ where the Licensor has his seat, resides or has his registered office,
260
+
261
+ - this licence shall be governed by Belgian law if the Licensor has no seat,
262
+ residence or registered office inside a European Union Member State.
263
+
264
+ Appendix
265
+
266
+ ‘Compatible Licences’ according to Article 5 EUPL are:
267
+
268
+ - GNU General Public License (GPL) v. 2, v. 3
269
+ - GNU Affero General Public License (AGPL) v. 3
270
+ - Open Software License (OSL) v. 2.1, v. 3.0
271
+ - Eclipse Public License (EPL) v. 1.0
272
+ - CeCILL v. 2.0, v. 2.1
273
+ - Mozilla Public Licence (MPL) v. 2
274
+ - GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
275
+ - Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
276
+ works other than software
277
+ - European Union Public Licence (EUPL) v. 1.1, v. 1.2
278
+ - Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
279
+ Reciprocity (LiLiQ-R+).
280
+
281
+ The European Commission may update this Appendix to later versions of the above
282
+ licences without producing a new version of the EUPL, as long as they provide
283
+ the rights granted in Article 2 of this Licence and protect the covered Source
284
+ Code from exclusive appropriation.
285
+
286
+ All other changes or additions to this Appendix require the production of a new
287
+ EUPL version.
@@ -0,0 +1,296 @@
1
+ Metadata-Version: 2.4
2
+ Name: funktionsklempner
3
+ Version: 1.0.0
4
+ Summary: Plumbing C++ with a Python frontend via ctypes.
5
+ Author-Email: =?utf-8?q?Malte_J=C3=B6rn_Ziebarth?= <malte.ziebarth@tum.de>
6
+ Maintainer-Email: =?utf-8?q?Malte_J=C3=B6rn_Ziebarth?= <malte.ziebarth@tum.de>
7
+ License-Expression: EUPL-1.2
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 2 - Pre-Alpha
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Intended Audience :: End Users/Desktop
12
+ Classifier: Topic :: Scientific/Engineering
13
+ Requires-Python: >=3.11.4
14
+ Requires-Dist: numpy
15
+ Description-Content-Type: text/markdown
16
+
17
+ # Funktionsklempner
18
+ A library and framework for plumbing C++ code to Python via ctypes.
19
+
20
+ Why ctypes? It has the advantage of being widely available with Python itself, and interfaces C ABIs that can remain stable for long periods of time. This way, a compiled library can work across many different Python versions in which a dynamically linked extension would have to be recompiled due to binary incompatibility. The maintenance burden due to the recurring need to recompile packages is reduced. This comes at the cost of the additional overhead for having to pipe data through a C/ctypes API. Funktionsklempner generates this wrapping code automatically, which reduces the cost to the computational overhead. You may find Funktionsklempner useful for your open source project with low version iteration rate.
21
+
22
+ Funktionsklempner's basic workflow is as follows:
23
+
24
+ 1. Declare the interface in a C++ header (i.e. functions whose equivalents shall be
25
+ passed through to the Python world).
26
+ 2. Declare all such headers in a project-wide `funktionsklempner.toml` file.
27
+ 3. Generated wrapper source files via the `funktionsklempner` command.
28
+ 4. Check the generated wrapper files and check them into your version control
29
+ system.
30
+ 5. Keep the auto-generated files updated via a git pre-commit hook.
31
+
32
+
33
+ ## Usage
34
+ Funktionsklempner assumes that you have created a C++ library with an interface that uses the Funktionsklempner (marker) types. For the sake of brevity, let's use the example in the [example](example) subdirectory; i.e. a project that has an [example.cpp](example/example.cpp) source file and whose interface with the Python world is designed in [example.hpp](example/examples.hpp). Specifically, the important part of the example's interface can be illustrated using the single function
35
+ ```cpp
36
+ int test_function(
37
+ const char* name,
38
+ size_t i,
39
+ double* result
40
+ );
41
+ ```
42
+ that takes a string `name` and an integer `i`, does something with it, and returns a double as `result`. Note in this interface the pointer-to-double type of `result`: to transfer values to Python via ctypes, Funktionsklempner uses preallocated ctypes variables and passes pointers to them when calling the compiled library. The C++ side is then expected to write the return value into this provided pointer. The actual return value of the function is unused; Funktionsklempner convention is to use `void`.
43
+
44
+ Note that the actual function in [example.hpp](example/examples.hpp) looks differently! What I have just described is the mechanism that Funktionsklempner makes use of, which is a bit cumbersome to do by hand. To write more explicit code and to make the parser of Funktionsklempner understand the intention of this function definition, it is annoted using macros and alias types defined in [funktionsklempner/funktionsklempner.hpp](subprojects/funktionsklempner/funktionsklempner/funktionsklempner.hpp) and [funktionsklempner/scalar.hpp](subprojects/funktionsklempner/funktionsklempner/scalar.hpp):
45
+ ```cpp
46
+ FUNKTIONSKLEMPNER_EXPORT_FUNCTION
47
+ int test_function(
48
+ funktionsklempner::input<const char*> name,
49
+ funktionsklempner::input<size_t> i,
50
+ funktionsklempner::output<double> result
51
+ );
52
+ ```
53
+ The first macro `FUNKTIONSKLEMPNER_EXPORT_FUNCTION` tells the parser that what follows is the declaration of a function that shall be callable from the Python world. The templated type alias `funktionsklempner::input<T>` tells the parser that the variables `name` and `i` are input variables passed by value `T`, and the alias `funktionsklempner::output<T>` tells the parser that `result` is a return value of the function (corresponding to a `T*` input parameter). Note that you shall name your variables when exporting via the `FUNKTIONSKLEMPNER_EXPORT_FUNCTION` macro.
54
+
55
+ What does Funktionsklempner do with this C++ function declaration? On the Python side, it will generate a function that takes a string `name`, an int `i`, and returns a float, i.e.
56
+ ```python
57
+ def test_function(
58
+ name: str,
59
+ i: int
60
+ ) -> float:
61
+ ...
62
+ ```
63
+ On the C++ side, it will wrap `test_function` defined in the header by an exception handling function (any uncaught exceptions passing through to the Python world would crash the program!) that caches any occurring error messages. Between this C++ wrapper and the Python `test_function`, glue code will initialize ctypes variables and watch out for such error messages, raising errors on the Python side appropriately.
64
+
65
+ All glue code is generated via the `funktionsklempner generate` command after the header [example.hpp](example/example.hpp) has been properly described in the project-wide [funktionsklempner.toml](example/funktionsklempner.toml). The following two sections describe both the `funktionsklempner` command line tool as well as the `funktionsklempner.toml` configuration file format.
66
+
67
+
68
+ ### `funktionsklempner.toml`
69
+ The `funktionsklempner.toml` file collects all files in a source code repository that shall be wrapped via the `funktionsklempner` command. It has to be placed in the root of the packages source code directory and it is required for the `funktionsklempner` command line utility to work. As an example of its layout, consider the [funktionsklempner.toml](example/funktionsklempner.toml) file of the [example](example) subdirectory:
70
+ ```toml
71
+ [package]
72
+ name = "funkybadger"
73
+ root = "funkybadger"
74
+
75
+ [funkybadger]
76
+ [funkybadger.example]
77
+ header = "cpp/example.hpp"
78
+ sources = [ "cpp/example.cpp" ]
79
+ ```
80
+ First, note that the `[package]` entry---including the `name` and `root` fields---is mandatory. The `package.name` field describes the name of the Python packge, and the `package.root` field describes the location, relative to the source code directory's root, of the package's source code (see [src layout vs flat layout](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/), where `package.root` would correspond to the `awesome_package` folder).
81
+
82
+ Second, there must be one entry per wrapped shared library. In the example, this is `[funkybadger.example]`. All of these entries must be under a root entry that corresponds to the package name (here `[funkybadger]`). The entry's key must correspond to the module name which shall be generated and from which the wrapped functions shall be imported (here the module `funkybadger.example`). Each shared library entry must contain two fields:
83
+
84
+ 1. `header`, a string denoting the path to the Funktionsklempner-annotated, API-defining
85
+ header file (here [`example/example.hpp`](example/example.hpp)). The path shall be relative
86
+ to the source directory's root.
87
+ 2. `sources`, a list of (strings denoting paths to) source files which encompass the shared
88
+ library.
89
+
90
+ #### Optional fields
91
+ There are further optional fields that can be used to tweak the code that Funktionsklempner injects into the Meson build file. This way, necessary information (such as a static library that must be linked to) can be passed to the autogenerated Meson build code. The following optional fields are available:
92
+
93
+ 1. `link_with`, a list of strings denoting `static_library` targets of the injection-targeted
94
+ Meson build file which the Python shared library shall be linked with.
95
+ 2. `dependencies`, a list of strings denoting `dependency` objects of the injection-targeted
96
+ Meson build files on which the Python shared library depends.
97
+ 3. `wrapper_source`, a file name specifying the wrapper C++ source file
98
+ relative to the repository's root.
99
+ 4. `include_root`, a directory name specifying the root include directory
100
+ for the library. If not given, will default to the directory in which
101
+ `header` resides.
102
+
103
+ As an illustration, the code
104
+ ```toml
105
+ [package.library]
106
+ header = "..."
107
+ sources = [ "..." ]
108
+ link_with = [ "linklib" ]
109
+ dependencies = [ "a_dependency" ]
110
+ wrapper_source = "cpp/src/library_wrapped.cpp"
111
+ ```
112
+ in the `funktionsklempner.toml` configuration file will generate a wrapper source file at `cpp/src/library_wrapped.cpp` (relative to the repository root), and inject the following code into the project's Meson build file:
113
+ ```meson
114
+ package_library = shared_library(
115
+ 'library',
116
+ # ...
117
+ 'cpp/src/library_wrapped.cpp',
118
+ dependencies: [
119
+ a_dependency,
120
+ ],
121
+ link_with: [
122
+ linklib,
123
+ ],
124
+ # ...
125
+ )
126
+ ```
127
+
128
+
129
+ ### Command line
130
+ The Funktionsklempner package comes with the `funktionsklempner` command line utility. This program sets up the Meson subprojects and git pre-commit hook, injects the project's main Meson build file, and generates the wrapper code. It has three main commands, two of which are typically used by users themselves.
131
+
132
+ #### `funktionsklempner init`
133
+ This command needs to be called once after the `funktionsklempner.toml` configuration file has been written. The command performs the following tasks:
134
+
135
+ 1. Setup the `funktionsklempner`, `objektbuch`, `gcem-1.18.0`, and (optional) `boost-1.90.0` Meson subprojects that are required for
136
+ the automatic error propagation to the Python side.
137
+ 2. Setup the git pre-commit hook that internally uses `funktionsklempner verify` to check
138
+ that the generated code currently residing in the repository is up to date.
139
+ 3. Start injecting the Funktionsklempner code into the project's Meson build file.
140
+
141
+ Boost will be preferably used from the system side, but particulary during the pip package building, Boost might not be found. In this case, the reduced subset of Boost (shipping code relevant to Boost.Units) will act as a fallback subproject.
142
+
143
+ #### `funktionsklempner generate`
144
+ This command is the main workhorse. It generates or updates wrapper codes for all libraries described in `funktionsklempner.toml`, and updates the injection into the project's Meson build file. Call this command whenever a definition in one of the API-defining headers changes.
145
+
146
+
147
+ #### `funktionsklempner verify`
148
+ This command checks whether the potential result of `funktionsklempner generate` is identical to what is currently found in the source tree, raising an error if not. This command is used by the git pre-commit hook to ensure that the autogenerated code stays up to date with the API header definitions.
149
+
150
+
151
+ ### Header annotation syntax
152
+ The introductory example lays out the basic syntax for annotating C++ headers using `FUNKTIONSKLEMPNER_*` macros. The following macros are available:
153
+
154
+ | Macro | Purpose | Scope |
155
+ | ------------------------------------------- | ------------------------------------------------------------------------------------------------------ | --------------- |
156
+ | `FUNKTIONSKLEMPNER_EXPORT_FUNCTION` | Export the following function to Python module | Top level |
157
+ | `FUNKTIONSKLEMPNER_EXPORT_STRUCT` | Export the following structure to Python module | Top level |
158
+ | `FUNKTIONSKLEMPNER_SIZE_CONTROL("X", "Y")` | Declare variable `X` as an (output) array whose size is controlled by the (input) array(s) or integer `Y` | Function export |
159
+
160
+ #### `FUNKTIONSKLEMPNER_EXPORT_FUNCTION`
161
+ This function will generate a wrapper for the following function and export it to the Python module.
162
+
163
+ #### `FUNKTIONSKLEMPNER_EXPORT_STRUCT`
164
+ This function will generate a `ctypes.Structure` wrapping the following `struct` and export it to the Python module. Functions accepting pointers to this struct (including as return values!) will then be able to pass this data type to and from the Python world. This can be helpful when complex data types shall be transferred with a limited amount of ctypes calls.
165
+
166
+ #### `FUNKTIONSKLEMPNER_SIZE_CONTROL("X", "Y")`
167
+ A way to return NumPy arrays with known size. Works with and is required for `funktionsklempner::OutputNDArray` and `funktionsklempner::OutputQuantityArray`-type variables. Declares that the variable `X` is an array of size given by the variable `Y`. On the Python side, the two C++ parameters `X` and `Y` will be translated into a single NumPy array `X` of shape `Y.shape` (if `Y` is an input array) or `(Y,)` (if `Y` is not an input parameter of the C++ function, in which case it will be generated as an integer input on the Python side). This allows handling the frequent task of performing computational tasks on vector data kept in Numpy arrays.
168
+
169
+ The simplest way to automatically derive the size of an output array is by following the size of an input array:
170
+ ```cpp
171
+ FUNKTIONSKLEMPNER_EXPORT_FUNCTION
172
+ FUNKTIONSKLEMPNER_SIZE_CONTROL("out", "in_")
173
+ void a_function(
174
+ funktionsklempner::InputNDArray<double> in_,
175
+ funktionsklempner::OutputNDArray<double> out
176
+ );
177
+ ```
178
+ Here, `in_` is an automatically converted input array, and the return value `out` of the Python wrapper to this function will be a newly generated Numpy array of size `out.size = in_.size`.
179
+
180
+ ##### Multidimensional size control
181
+ Sometimes, following the size of a single array will not be enough. Think of a two-parameter function evaluated on a meshgrid, for instance. For this particular use case, one can use the size multiplication syntax:
182
+ ```cpp
183
+ FUNKTIONSKLEMPNER_EXPORT_FUNCTION
184
+ FUNKTIONSKLEMPNER_SIZE_CONTROL("X", "Y,Z")
185
+ void a_function(
186
+ funktionsklempner::InputNDArray<double> Y,
187
+ funktionsklempner::InputQuantityArray<boost::units::si::length, double> Z,
188
+ funktionsklempner::OutputNDArray<double> out
189
+ );
190
+ ```
191
+ Here, `Y` is an automatically converted input array of shape `Y.shape`, `Z` is an automatically converted input array of shape `Z.shape` and length dimension, and the return value `X` of the Python wrapper to this function will be a newly generated Numpy array of shape `X.shape = (*Y.shape, *Z.shape)`.
192
+
193
+ The size control works equivalently with QuantityArrays instead of NDArrays.
194
+
195
+ ### `funktionsklempner::NDArray<NumPyDType T>`
196
+ This class is a thin random access range wrapper around a scalar pointer (e.g., a NumPy array buffer). It is accessible in the `funktionsklempner` namespace as `InputNDArray<T>` (=`NDArray<const T>`, read-only access to the underlying buffer) and `OutputNDArray<T>` (=`NDArray<T>`, can be written to).
197
+
198
+ The API of the class is as follows:
199
+ ```cpp
200
+ template<NumPyDType T>
201
+ class NDArray
202
+ {
203
+ public:
204
+ /* Constructors: */
205
+ constexpr NDArray(T* data, size_t N, const char* dtype);
206
+ constexpr NDArray(NDArray&&) noexcept = default;
207
+ constexpr NDArray(const NDArray&) noexcept = default;
208
+
209
+ /* Sized range: */
210
+ constexpr size_t size() const noexcept;
211
+
212
+ /* Random access iterators, pointers to the underlying buffer: */
213
+ constexpr T* begin() const noexcept;
214
+ constexpr T* end() const noexcept;
215
+
216
+ /* Random index-based access: */
217
+ constexpr T& operator[](size_t i) const;
218
+ };
219
+ ```
220
+ Note that `NumPyDType` is a concept that captures the basic scalar types of NumPy array buffers (integer and floating point types).
221
+
222
+
223
+ ### `funktionsklempner::QuantityArray<Unit U, NumPyDType T>`
224
+ A rather thin random access wrapper around a scalar pointer that represents values of a certain physical (SI) unit via Boost.Units. Iterating over the quantity array yields value views that act, basically, as physical quantities of the given unit `U` (`boost::unit::quantity<U, T>`). It is accessible in the `funktionsklempner` namespace as `InputQuantityArray<U, T>` (=`QuantityArray<U, const T>`, read-only access to the underlying buffer) and `OutputQuantityArray<U, T>` (=`QuantityArray<U, T>`, can be written to).
225
+
226
+ The value type of the iterators of `QuantityArray` is the the `QuantityView<U,T>` class, which internally contains a pointer to the numerical buffer of the `QuantityArray` and a `boost::unit::quantity<U, T>` that represents the physical unit. The `QuantityView` can be casted to `boost::unit::quantity<U, T>`, and addition, subtraction, multiplication, and division operators of `QuantityView<U,T>` with `boost::unit::quantity<U, T>` are provided. In case of the `OutputQuantityArray`, assignment and inplace addition and subtraction operators with `boost::unit::quantity<U, T>` are provided as well. Essentially, `QuantityArray<U,T>` can be used to wrap a floating point buffer `T*` in a way that looks like a buffer of quantities, `boost::unit::quantity<U, T>*`.
227
+
228
+ The API of the class is as follows:
229
+ ```cpp
230
+ template<Unit U, NumPyDType T>
231
+ class QuantityArray
232
+ {
233
+ public:
234
+ /* Constructor with given unit of same dimension as `U`. */
235
+ constexpr QuantityArray(
236
+ T* data,
237
+ size_t N,
238
+ const char* dtype,
239
+ const char* unit
240
+ );
241
+
242
+ /* Constructor with default unit `U` */
243
+ constexpr QuantityArray(
244
+ T* data,
245
+ size_t N,
246
+ const char* dtype
247
+ );
248
+
249
+ /* Sized range: */
250
+ constexpr size_t size() const noexcept;
251
+
252
+ /* Random access iterators, pointing to the underlying buffer: */
253
+ constexpr QuantityIterator<U, T> begin() const;
254
+ constexpr const std::decay_t<T>* end() const noexcept;
255
+
256
+ /* Random index-based access: */
257
+ constexpr QuantityView<U, T> operator[](size_t i) const;
258
+
259
+ /* Setting the unit to `u`, a quantity of unit `U`.
260
+ * Note: this method is enabled only if `T` is not a const value
261
+ * (i.e. for OutputQuantityArray<U,T>).
262
+ */
263
+ constexpr void set_unit(const boost::units::quantity<U>& u);
264
+ };
265
+ ```
266
+ Note that `Unit` is a concept that captures `boost::units::unit<Dim, System>` of some dimension `Dim` and system `System` (which essentially has to be the SI system from `boost::units::si` to be able to interact with the remainder of Funktionsklempner). As before, `NumPyDType` is a concept that captures the basic scalar types of NumPy array buffers (integer and floating point types).
267
+
268
+ ## Caveats
269
+ Some known caveats to keep in mind when using Funktionsklempner:
270
+
271
+ 1. This uses a simplified grammar.
272
+ 2. There is some effort in this code base to handle comments. However, this
273
+ effort is designed empirically rather than after a standard. You might
274
+ run into complications with more 'unusual' comment or preprocessor layouts.
275
+ If you hit such a bug, you may try to file a bug report--but there is no
276
+ guarantee that all such bugs will be fixed (in which case reduction to the
277
+ simplified grammar may be the only way to run Funktionsklempner).
278
+
279
+ Note, furthermore, the terms listed in the [LICENSE](LICENSE).
280
+
281
+
282
+ ## License
283
+ Funktionsklempner itself is licensed under the European Public License, v1.2 (`EUPL-1.2`, see [LICENSE](LICENSE) file in this directory). The template code for the code generation is licensed under the BSD 3-Clause license (`BSD-3-Clause`, noted in corresponding source files). The example under the [example/](example) subfolder is equally licensed under the `BSD-3-Clause` license.
284
+
285
+ Funktionsklempner vendors a subset of the Boost C++ Libraries, version 1.90.0 in [subprojects/packagefiles/boost-1.90.0_units.tar.gz](subprojects/packagefiles/boost-1.90.0_units.tar.gz). This code is licensed under the Boost Software License as indicated in the archive. You can find the full Boost library at [boost.org](https://www.boost.org/).
286
+
287
+
288
+ ## Changelog
289
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
290
+ and this project adheres to
291
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
292
+
293
+
294
+ ### [1.0.0] - 2026-03-09
295
+ #### Added
296
+ - Start of the changelog.