Library of Assembled Shared Sources
 
Loading...
Searching...
No Matches
module_definition.h
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2026 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_MODULE_DEFINITION_H
44#define LASS_GUARDIAN_OF_INCLUSION_UTIL_MODULE_DEFINITION_H
45
46#include "python_common.h"
47#include "pyobject_plus.h"
48#include "../util/callback_0.h"
49#include "../util/callback_1.h"
50
51namespace lass
52{
53namespace python
54{
55
56/** @defgroup ModuleDefinition Module Definitions
57 * @brief Defining Python modules from C++ with classes, functions, and enums.
58 *
59 * This module provides helper classes and macros to define Python modules that can contain
60 * C++ classes, functions, enums, and other objects exported to Python.
61 *
62 *
63 *
64 * @par Module Components
65 *
66 * A Python module can contain:
67 *
68 * - @ref ModuleFunctions "Functions": C++ functions exported with various signatures
69 * - @ref ClassDefinition "Classes": C++ classes exported as Python classes
70 * - @ref EnumDefinition "Enums": C++ enums exported as Python enum types
71 * - @ref ModuleMembers "Objects": Arbitrary Python objects (constants, instances, etc.)
72 * - @ref ModuleMembers "Values": Simple values like integers and strings
73 *
74 * But every module must also be @ref PyModuleDeclaration "declared", and have an
75 * @ref PyModuleEntrypoint "entrypoint".
76 *
77 * @par Usage Overview
78 *
79 * To create a Python module, you typically use macros that work with ModuleDefinition:
80 * Macro names follow a consistent grammar, see @ref PythonMacroName.
81 *
82 * ```cpp
83 * // Define module
84 * PY_DECLARE_MODULE_NAME_DOC(mymodule, "mymodule", "My example module")
85 *
86 * // Add functions
87 * PY_MODULE_FUNCTION(mymodule, myFunction)
88 *
89 * // Add classes
90 * PY_MODULE_CLASS(mymodule, MyClass)
91 *
92 * // Add enums
93 * PY_MODULE_ENUM(mymodule, MyEnum)
94 *
95 * // Create module entrypoint for Python extension
96 * PY_MODULE_ENTRYPOINT(mymodule)
97 * ```
98 *
99 * The ModuleDefinition class is typically not used directly. Instead, use the provided
100 * macros in pyobject_macros.h that work with ModuleDefinition instances.
101 *
102 * @ingroup Python
103 */
104
106
107/** Definition of a Python module.
108 *
109 * Holds the definition of a Python module and can create the module by calling inject().
110 * This class manages all components that make up a Python module: functions, classes,
111 * enums, and other objects.
112 *
113 * The module definition accumulates all components during the program initialization
114 * phase, then creates the actual Python module when inject() is called.
115 *
116 * This class is typically not used directly by user code. Use the provided
117 * macros in pyobject_macros.h that work with ModuleDefinition instances.
118 *
119 * @ingroup ModuleDefinition
120 */
122{
123public:
124 /** Callback type for pre-injection hooks (called before module creation). */
126
127 /** Callback type for post-injection hooks (called after module creation with module object). */
129
130 /** Construct module definition with name and optional documentation.
131 * @param name Python module name (will be copied and stored internally)
132 * @param doc Optional module docstring (will be copied and stored internally, or nullptr)
133 */
134 ModuleDefinition(const char* name, const char* doc = 0);
135 /** Get the module name. */
136 const char* name() const { return name_.get(); }
137
138 /** Set the module name.
139 * @param name New module name (will be copied and stored internally)
140 */
141 void setName(const char* name);
142
143 /** Get the module documentation string. */
144 const char* doc() const { return doc_.get(); }
145
146 /** Set the module documentation string.
147 * @param doc New docstring (will be copied and stored internally, or nullptr)
148 */
149 void setDoc(const char* doc);
150
151 /** Get the Python module object (available after inject() has been called). */
152 PyObject* module() const { return module_; }
153
154 /** Set callback to be executed before module injection.
155 * Useful for performing setup tasks before the module is created.
156 * @param callback Function to call before injection
157 */
158 void setPreInject(const TPreInject& callback);
159
160 /** Set callback to be executed after module injection.
161 * Useful for performing additional setup on the created module.
162 * @param callback Function to call with the module object after injection
163 */
164 void setPostInject(const TPostInject& callback);
165
166 /** Add a function dispatcher to the module.
167 * Used internally by function export macros to register C++ functions.
168 * @param dispatcher Function dispatcher for overload resolution
169 * @param name Python function name
170 * @param doc Function documentation string
171 * @param overloadChain Reference to overload chain for this function name
172 */
173 void addFunctionDispatcher(PyCFunction dispatcher, const char* name, const char* doc, PyCFunction& overloadChain);
174
175 /** Add a class definition to the module.
176 * The class will be created and added when the module is injected.
177 * @param classDef Class definition containing class export information
178 */
179 void addClass(impl::ClassDefinition& classDef);
180
181 /** Add an enum definition to the module.
182 * The enum type will be created and added when the module is injected.
183 * @param enumDef Enum definition containing enum export information
184 */
185 void addEnum(EnumDefinitionBase* enumDef);
186
187 /** Add an arbitrary Python object to the module.
188 * The object will be added directly to the module namespace.
189 * @param object Python object to add
190 * @param name Name for the object in the module namespace
191 */
192 void addObject(PyObject* object, const char* name);
193
194 /** Add a long integer constant to the module.
195 * @param object Long value to add as module constant
196 * @param name Name for the constant in the module namespace
197 */
198 void addLong(long object, const char* name);
199
200 /** Add a string constant to the module.
201 * @param object String value to add as module constant
202 * @param name Name for the string in the module namespace
203 */
204 void addString(const char* object, const char* name);
205
206 /** Inject a long integer directly into an already created module.
207 * This is for immediate injection, unlike addLong() which defers until inject().
208 * @param name Name for the constant in the module namespace
209 * @param value Long value to inject
210 */
211 void injectLong(const char* name, long value);
212
213 /** Inject a string directly into an already created module.
214 * This is for immediate injection, unlike addString() which defers until inject().
215 * @param name Name for the string in the module namespace
216 * @param value String value to inject
217 */
218 void injectString(const char* name, const char* value);
219
220 /** Inject an arbitrary object directly into an already created module.
221 * This is for immediate injection, unlike addObject() which defers until inject().
222 * @param object Object to inject (will be converted to Python object)
223 * @param name Name for the object in the module namespace
224 */
225 template <typename T>
226 void injectObject(T&& object, const char* name)
227 {
228 PyModule_AddObject(module_, name, lass::python::pyBuildSimpleObject( std::forward<T>(object) ));
229 }
230
231 /** Inject a class definition directly into an already created module.
232 * @param classDef Class definition to inject
233 * @return true on success, false on failure
234 */
235 bool injectClass(impl::ClassDefinition& classDef);
236
237 /** Create and inject the Python module with all accumulated definitions.
238 * This method should typically not be called directly. Use module registration
239 * macros which call this at the appropriate time during Python initialization.
240 * @return The created Python module object
241 */
242 PyObject* inject();
243private:
244 typedef std::unique_ptr<char[]> TScopedCString;
245 typedef std::vector<impl::ClassDefinition*> TClassDefs;
246 typedef std::vector<EnumDefinitionBase*> TEnumDefs;
247 typedef std::vector<PyMethodDef> TMethods;
248 struct NamedObject
249 {
250 TScopedCString name;
251 PyObject* object;
252 };
253 struct LongObject
254 {
255 TScopedCString name;
256 long object;
257 };
258 struct StringObject
259 {
260 TScopedCString name;
261 TScopedCString object;
262 };
263 typedef std::vector<NamedObject*> TObjects;
264 typedef std::vector<LongObject*> TLongObjects;
265 typedef std::vector<StringObject*> TStringObjects;
266
267 /** Implementation of module injection process. */
268 PyObject* doInject();
269
270 TClassDefs classes_;
271 TEnumDefs enums_;
272 TMethods methods_;
273 TObjects objects_;
274 TLongObjects longObjects_;
275 TStringObjects stringObjects_;
276 TScopedCString name_;
277 TScopedCString doc_;
278 TPreInject preInject_;
279 TPostInject postInject_;
280 PyObject* module_;
281 PyModuleDef def_;
282 bool isInjected_;
283};
284
285}
286}
287
288#endif
Base class of all enum definitions.
const char * doc() const
Get the module documentation string.
const char * name() const
Get the module name.
void injectObject(T &&object, const char *name)
Inject an arbitrary object directly into an already created module.
PyObject * module() const
Get the Python module object (available after inject() has been called).
ModuleDefinition(const char *name, const char *doc=0)
Construct module definition with name and optional documentation.
util::Callback1< PyObject * > TPostInject
Callback type for post-injection hooks (called after module creation with module object).
util::Callback0 TPreInject
Callback type for pre-injection hooks (called before module creation).
Definition of a Python class.
callback with 0 parameter(s) and without returnvalue.
Definition callback_0.h:84
callback with 1 parameter(s) but without returnvalue.
Definition callback_1.h:97
use as base class if derived should not be copyable
Comprehensive C++ to Python binding library.
Library for Assembled Shared Sources.
Definition config.h:53