Library of Assembled Shared Sources
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-2025 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 * ### Module Components
64 *
65 * A Python module can contain:
66 *
67 * - **Functions**: C++ functions exported with various signatures
68 * - **Classes**: C++ classes exported as Python classes
69 * - **Enums**: C++ enums exported as Python enum types
70 * - **Objects**: Arbitrary Python objects (constants, instances, etc.)
71 * - **Values**: Simple values like integers and strings
72 *
73 *
74 * ### Usage Overview
75 *
76 * To create a Python module, you typically use macros that work with ModuleDefinition:
77 *
78 * ```cpp
79 * // Define module
80 * PY_DECLARE_MODULE_NAME_DOC(mymodule, "mymodule", "My example module")
81 *
82 * // Add functions
83 * PY_MODULE_FUNCTION(mymodule, myFunction)
84 *
85 * // Add classes
86 * PY_MODULE_CLASS(mymodule, MyClass)
87 *
88 * // Add enums
89 * PY_MODULE_ENUM(mymodule, MyEnum)
90 *
91 * // Create module entrypoint for Python extension
92 * PY_MODULE_ENTRYPOINT(mymodule)
93 * ```
94 *
95 * The ModuleDefinition class is typically not used directly. Instead, use the provided
96 * macros in pyobject_macros.h that work with ModuleDefinition instances.
97 *
98 * @ingroup Python
99 */
100
102
103/** Definition of a Python module.
104 *
105 * Holds the definition of a Python module and can create the module by calling inject().
106 * This class manages all components that make up a Python module: functions, classes,
107 * enums, and other objects.
108 *
109 * The module definition accumulates all components during the program initialization
110 * phase, then creates the actual Python module when inject() is called.
111 *
112 * This class is typically not used directly by user code. Use the provided
113 * macros in pyobject_macros.h that work with ModuleDefinition instances.
114 *
115 * @ingroup ModuleDefinition
116 */
118{
119public:
120 /** Callback type for pre-injection hooks (called before module creation). */
122
123 /** Callback type for post-injection hooks (called after module creation with module object). */
125
126 /** Construct module definition with name and optional documentation.
127 * @param name Python module name (will be copied and stored internally)
128 * @param doc Optional module docstring (will be copied and stored internally, or nullptr)
129 */
130 ModuleDefinition(const char* name, const char* doc = 0);
131 /** Get the module name. */
132 const char* name() const { return name_.get(); }
133
134 /** Set the module name.
135 * @param name New module name (will be copied and stored internally)
136 */
137 void setName(const char* name);
138
139 /** Get the module documentation string. */
140 const char* doc() const { return doc_.get(); }
141
142 /** Set the module documentation string.
143 * @param doc New docstring (will be copied and stored internally, or nullptr)
144 */
145 void setDoc(const char* doc);
146
147 /** Get the Python module object (available after inject() has been called). */
148 PyObject* module() const { return module_; }
149
150 /** Set callback to be executed before module injection.
151 * Useful for performing setup tasks before the module is created.
152 * @param callback Function to call before injection
153 */
154 void setPreInject(const TPreInject& callback);
155
156 /** Set callback to be executed after module injection.
157 * Useful for performing additional setup on the created module.
158 * @param callback Function to call with the module object after injection
159 */
160 void setPostInject(const TPostInject& callback);
161
162 /** Add a function dispatcher to the module.
163 * Used internally by function export macros to register C++ functions.
164 * @param dispatcher Function dispatcher for overload resolution
165 * @param name Python function name
166 * @param doc Function documentation string
167 * @param overloadChain Reference to overload chain for this function name
168 */
169 void addFunctionDispatcher(PyCFunction dispatcher, const char* name, const char* doc, PyCFunction& overloadChain);
170
171 /** Add a class definition to the module.
172 * The class will be created and added when the module is injected.
173 * @param classDef Class definition containing class export information
174 */
175 void addClass(impl::ClassDefinition& classDef);
176
177 /** Add an enum definition to the module.
178 * The enum type will be created and added when the module is injected.
179 * @param enumDef Enum definition containing enum export information
180 */
181 void addEnum(EnumDefinitionBase* enumDef);
182
183 /** Add an arbitrary Python object to the module.
184 * The object will be added directly to the module namespace.
185 * @param object Python object to add
186 * @param name Name for the object in the module namespace
187 */
188 void addObject(PyObject* object, const char* name);
189
190 /** Add a long integer constant to the module.
191 * @param object Long value to add as module constant
192 * @param name Name for the constant in the module namespace
193 */
194 void addLong(long object, const char* name);
195
196 /** Add a string constant to the module.
197 * @param object String value to add as module constant
198 * @param name Name for the string in the module namespace
199 */
200 void addString(const char* object, const char* name);
201
202 /** Inject a long integer directly into an already created module.
203 * This is for immediate injection, unlike addLong() which defers until inject().
204 * @param name Name for the constant in the module namespace
205 * @param value Long value to inject
206 */
207 void injectLong(const char* name, long value);
208
209 /** Inject a string directly into an already created module.
210 * This is for immediate injection, unlike addString() which defers until inject().
211 * @param name Name for the string in the module namespace
212 * @param value String value to inject
213 */
214 void injectString(const char* name, const char* value);
215
216 /** Inject an arbitrary object directly into an already created module.
217 * This is for immediate injection, unlike addObject() which defers until inject().
218 * @param object Object to inject (will be converted to Python object)
219 * @param name Name for the object in the module namespace
220 */
221 template <typename T>
222 void injectObject(T&& object, const char* name)
223 {
224 PyModule_AddObject(module_, name, lass::python::pyBuildSimpleObject( std::forward<T>(object) ));
225 }
226
227 /** Inject a class definition directly into an already created module.
228 * @param classDef Class definition to inject
229 * @return true on success, false on failure
230 */
231 bool injectClass(impl::ClassDefinition& classDef);
232
233 /** Create and inject the Python module with all accumulated definitions.
234 * This method should typically not be called directly. Use module registration
235 * macros which call this at the appropriate time during Python initialization.
236 * @return The created Python module object
237 */
238 PyObject* inject();
239private:
240 typedef std::unique_ptr<char[]> TScopedCString;
241 typedef std::vector<impl::ClassDefinition*> TClassDefs;
242 typedef std::vector<EnumDefinitionBase*> TEnumDefs;
243 typedef std::vector<PyMethodDef> TMethods;
244 struct NamedObject
245 {
246 TScopedCString name;
247 PyObject* object;
248 };
249 struct LongObject
250 {
251 TScopedCString name;
252 long object;
253 };
254 struct StringObject
255 {
256 TScopedCString name;
257 TScopedCString object;
258 };
259 typedef std::vector<NamedObject*> TObjects;
260 typedef std::vector<LongObject*> TLongObjects;
261 typedef std::vector<StringObject*> TStringObjects;
262
263 /** Implementation of module injection process. */
264 PyObject* doInject();
265
266 TClassDefs classes_;
267 TEnumDefs enums_;
268 TMethods methods_;
269 TObjects objects_;
270 TLongObjects longObjects_;
271 TStringObjects stringObjects_;
272 TScopedCString name_;
273 TScopedCString doc_;
274 TPreInject preInject_;
275 TPostInject postInject_;
276 PyObject* module_;
277 PyModuleDef def_;
278 bool isInjected_;
279};
280
281}
282}
283
284#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