1//===-- mlir-c/Interop.h - Constants for Python/C-API interop -----*- C -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM
4// Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9//
10// This header declares constants and helpers necessary for C-level
11// interop with the MLIR Python extension module. Since the Python bindings
12// are a thin wrapper around the MLIR C-API, a further C-API is not provided
13// specifically for the Python extension. Instead, simple facilities are
14// provided for translating between Python types and corresponding MLIR C-API
15// types.
16//
17// This header is standalone, requiring nothing beyond normal linking against
18// the Python implementation.
19//===----------------------------------------------------------------------===//
20
21#ifndef MLIR_C_BINDINGS_PYTHON_INTEROP_H
22#define MLIR_C_BINDINGS_PYTHON_INTEROP_H
23
24// We *should*, in theory, include Python.h here in order to import the correct
25// definitions for what we need below, however, importing Python.h directly on
26// Windows results in the enforcement of either pythonX.lib or pythonX_d.lib
27// depending on the build flavor. Instead, we rely on the fact that this file
28// (Interop.h) is always included AFTER pybind11 and will therefore have access
29// to the definitions from Python.h in addition to having a workaround applied
30// through the pybind11 headers that allows us to control which python library
31// is used.
32#if !defined(_MSC_VER)
33#include <Python.h>
34#endif
35
36#include "mlir-c/AffineExpr.h"
37#include "mlir-c/AffineMap.h"
38#include "mlir-c/ExecutionEngine.h"
39#include "mlir-c/IR.h"
40#include "mlir-c/IntegerSet.h"
41#include "mlir-c/Pass.h"
42#include "mlir-c/Rewrite.h"
43
44// The 'mlir' Python package is relocatable and supports co-existing in multiple
45// projects. Each project must define its outer package prefix with this define
46// in order to provide proper isolation and local name resolution.
47// The default is for the upstream "import mlir" package layout.
48// Note that this prefix is internally stringified, allowing it to be passed
49// unquoted on the compiler command line without shell quote escaping issues.
50#ifndef MLIR_PYTHON_PACKAGE_PREFIX
51#define MLIR_PYTHON_PACKAGE_PREFIX mlir.
52#endif
53
54// Makes a fully-qualified name relative to the MLIR python package.
55#define MLIR_PYTHON_STRINGIZE(s) #s
56#define MLIR_PYTHON_STRINGIZE_ARG(arg) MLIR_PYTHON_STRINGIZE(arg)
57#define MAKE_MLIR_PYTHON_QUALNAME(local) \
58 MLIR_PYTHON_STRINGIZE_ARG(MLIR_PYTHON_PACKAGE_PREFIX) local
59
60#define MLIR_PYTHON_CAPSULE_AFFINE_EXPR \
61 MAKE_MLIR_PYTHON_QUALNAME("ir.AffineExpr._CAPIPtr")
62#define MLIR_PYTHON_CAPSULE_AFFINE_MAP \
63 MAKE_MLIR_PYTHON_QUALNAME("ir.AffineMap._CAPIPtr")
64#define MLIR_PYTHON_CAPSULE_ATTRIBUTE \
65 MAKE_MLIR_PYTHON_QUALNAME("ir.Attribute._CAPIPtr")
66#define MLIR_PYTHON_CAPSULE_BLOCK MAKE_MLIR_PYTHON_QUALNAME("ir.Block._CAPIPtr")
67#define MLIR_PYTHON_CAPSULE_CONTEXT \
68 MAKE_MLIR_PYTHON_QUALNAME("ir.Context._CAPIPtr")
69#define MLIR_PYTHON_CAPSULE_DIALECT_REGISTRY \
70 MAKE_MLIR_PYTHON_QUALNAME("ir.DialectRegistry._CAPIPtr")
71#define MLIR_PYTHON_CAPSULE_EXECUTION_ENGINE \
72 MAKE_MLIR_PYTHON_QUALNAME("execution_engine.ExecutionEngine._CAPIPtr")
73#define MLIR_PYTHON_CAPSULE_INTEGER_SET \
74 MAKE_MLIR_PYTHON_QUALNAME("ir.IntegerSet._CAPIPtr")
75#define MLIR_PYTHON_CAPSULE_LOCATION \
76 MAKE_MLIR_PYTHON_QUALNAME("ir.Location._CAPIPtr")
77#define MLIR_PYTHON_CAPSULE_MODULE \
78 MAKE_MLIR_PYTHON_QUALNAME("ir.Module._CAPIPtr")
79#define MLIR_PYTHON_CAPSULE_OPERATION \
80 MAKE_MLIR_PYTHON_QUALNAME("ir.Operation._CAPIPtr")
81#define MLIR_PYTHON_CAPSULE_TYPE MAKE_MLIR_PYTHON_QUALNAME("ir.Type._CAPIPtr")
82#define MLIR_PYTHON_CAPSULE_PASS_MANAGER \
83 MAKE_MLIR_PYTHON_QUALNAME("passmanager.PassManager._CAPIPtr")
84#define MLIR_PYTHON_CAPSULE_VALUE MAKE_MLIR_PYTHON_QUALNAME("ir.Value._CAPIPtr")
85#define MLIR_PYTHON_CAPSULE_TYPEID \
86 MAKE_MLIR_PYTHON_QUALNAME("ir.TypeID._CAPIPtr")
87
88/** Attribute on MLIR Python objects that expose their C-API pointer.
89 * This will be a type-specific capsule created as per one of the helpers
90 * below.
91 *
92 * Ownership is not transferred by acquiring a capsule in this way: the
93 * validity of the pointer wrapped by the capsule will be bounded by the
94 * lifetime of the Python object that produced it. Only the name and pointer
95 * of the capsule are set. The caller is free to set a destructor and context
96 * as needed to manage anything further. */
97#define MLIR_PYTHON_CAPI_PTR_ATTR "_CAPIPtr"
98
99/** Attribute on MLIR Python objects that exposes a factory function for
100 * constructing the corresponding Python object from a type-specific
101 * capsule wrapping the C-API pointer. The signature of the function is:
102 * def _CAPICreate(capsule) -> object
103 * Calling such a function implies a transfer of ownership of the object the
104 * capsule wraps: after such a call, the capsule should be considered invalid,
105 * and its wrapped pointer must not be destroyed.
106 *
107 * Only a very small number of Python objects can be created in such a fashion
108 * (i.e. top-level types such as Context where the lifetime can be cleanly
109 * delineated). */
110#define MLIR_PYTHON_CAPI_FACTORY_ATTR "_CAPICreate"
111
112/** Attribute on MLIR Python objects that expose a function for downcasting the
113 * corresponding Python object to a subclass if the object is in fact a subclass
114 * (Concrete or mlir_type_subclass) of ir.Type. The signature of the function
115 * is: def maybe_downcast(self) -> object where the resulting object will
116 * (possibly) be an instance of the subclass.
117 */
118#define MLIR_PYTHON_MAYBE_DOWNCAST_ATTR "maybe_downcast"
119
120/** Attribute on main C extension module (_mlir) that corresponds to the
121 * type caster registration binding. The signature of the function is:
122 * def register_type_caster(MlirTypeID mlirTypeID, *, bool replace)
123 * which then takes a typeCaster (register_type_caster is meant to be used as a
124 * decorator from python), and where replace indicates the typeCaster should
125 * replace any existing registered type casters (such as those for upstream
126 * ConcreteTypes). The interface of the typeCaster is: def type_caster(ir.Type)
127 * -> SubClassTypeT where SubClassTypeT indicates the result should be a
128 * subclass (inherit from) ir.Type.
129 */
130#define MLIR_PYTHON_CAPI_TYPE_CASTER_REGISTER_ATTR "register_type_caster"
131
132/** Attribute on main C extension module (_mlir) that corresponds to the
133 * value caster registration binding. The signature of the function is:
134 * def register_value_caster(MlirTypeID mlirTypeID, *, bool replace)
135 * which then takes a valueCaster (register_value_caster is meant to be used as
136 * a decorator, from python), and where replace indicates the valueCaster should
137 * replace any existing registered value casters. The interface of the
138 * valueCaster is: def value_caster(ir.Value) -> SubClassValueT where
139 * SubClassValueT indicates the result should be a subclass (inherit from)
140 * ir.Value.
141 */
142#define MLIR_PYTHON_CAPI_VALUE_CASTER_REGISTER_ATTR "register_value_caster"
143
144/// Gets a void* from a wrapped struct. Needed because const cast is different
145/// between C/C++.
146#ifdef __cplusplus
147#define MLIR_PYTHON_GET_WRAPPED_POINTER(object) \
148 (const_cast<void *>((object).ptr))
149#else
150#define MLIR_PYTHON_GET_WRAPPED_POINTER(object) (void *)(object.ptr)
151#endif
152
153#ifdef __cplusplus
154extern "C" {
155#endif
156
157/** Creates a capsule object encapsulating the raw C-API MlirAffineExpr. The
158 * returned capsule does not extend or affect ownership of any Python objects
159 * that reference the expression in any way.
160 */
161static inline PyObject *mlirPythonAffineExprToCapsule(MlirAffineExpr expr) {
162 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(expr),
163 MLIR_PYTHON_CAPSULE_AFFINE_EXPR, NULL);
164}
165
166/** Extracts an MlirAffineExpr from a capsule as produced from
167 * mlirPythonAffineExprToCapsule. If the capsule is not of the right type, then
168 * a null expression is returned (as checked via mlirAffineExprIsNull). In such
169 * a case, the Python APIs will have already set an error. */
170static inline MlirAffineExpr mlirPythonCapsuleToAffineExpr(PyObject *capsule) {
171 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_AFFINE_EXPR);
172 MlirAffineExpr expr = {.ptr: ptr};
173 return expr;
174}
175
176/** Creates a capsule object encapsulating the raw C-API MlirAttribute.
177 * The returned capsule does not extend or affect ownership of any Python
178 * objects that reference the attribute in any way.
179 */
180static inline PyObject *mlirPythonAttributeToCapsule(MlirAttribute attribute) {
181 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(attribute),
182 MLIR_PYTHON_CAPSULE_ATTRIBUTE, NULL);
183}
184
185/** Extracts an MlirAttribute from a capsule as produced from
186 * mlirPythonAttributeToCapsule. If the capsule is not of the right type, then
187 * a null attribute is returned (as checked via mlirAttributeIsNull). In such a
188 * case, the Python APIs will have already set an error. */
189static inline MlirAttribute mlirPythonCapsuleToAttribute(PyObject *capsule) {
190 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_ATTRIBUTE);
191 MlirAttribute attr = {.ptr: ptr};
192 return attr;
193}
194
195/** Creates a capsule object encapsulating the raw C-API MlirBlock.
196 * The returned capsule does not extend or affect ownership of any Python
197 * objects that reference the module in any way. */
198static inline PyObject *mlirPythonBlockToCapsule(MlirBlock block) {
199 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(block),
200 MLIR_PYTHON_CAPSULE_BLOCK, NULL);
201}
202
203/** Extracts an MlirBlock from a capsule as produced from
204 * mlirPythonBlockToCapsule. If the capsule is not of the right type, then
205 * a null pass manager is returned (as checked via mlirBlockIsNull). */
206static inline MlirBlock mlirPythonCapsuleToBlock(PyObject *capsule) {
207 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_BLOCK);
208 MlirBlock block = {.ptr: ptr};
209 return block;
210}
211
212/** Creates a capsule object encapsulating the raw C-API MlirContext.
213 * The returned capsule does not extend or affect ownership of any Python
214 * objects that reference the context in any way.
215 */
216static inline PyObject *mlirPythonContextToCapsule(MlirContext context) {
217 return PyCapsule_New(context.ptr, MLIR_PYTHON_CAPSULE_CONTEXT, NULL);
218}
219
220/** Extracts a MlirContext from a capsule as produced from
221 * mlirPythonContextToCapsule. If the capsule is not of the right type, then
222 * a null context is returned (as checked via mlirContextIsNull). In such a
223 * case, the Python APIs will have already set an error. */
224static inline MlirContext mlirPythonCapsuleToContext(PyObject *capsule) {
225 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_CONTEXT);
226 MlirContext context = {.ptr: ptr};
227 return context;
228}
229
230/** Creates a capsule object encapsulating the raw C-API MlirDialectRegistry.
231 * The returned capsule does not extend or affect ownership of any Python
232 * objects that reference the context in any way.
233 */
234static inline PyObject *
235mlirPythonDialectRegistryToCapsule(MlirDialectRegistry registry) {
236 return PyCapsule_New(registry.ptr, MLIR_PYTHON_CAPSULE_DIALECT_REGISTRY,
237 NULL);
238}
239
240/** Extracts an MlirDialectRegistry from a capsule as produced from
241 * mlirPythonDialectRegistryToCapsule. If the capsule is not of the right type,
242 * then a null context is returned (as checked via mlirContextIsNull). In such a
243 * case, the Python APIs will have already set an error. */
244static inline MlirDialectRegistry
245mlirPythonCapsuleToDialectRegistry(PyObject *capsule) {
246 void *ptr =
247 PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_DIALECT_REGISTRY);
248 MlirDialectRegistry registry = {.ptr: ptr};
249 return registry;
250}
251
252/** Creates a capsule object encapsulating the raw C-API MlirLocation.
253 * The returned capsule does not extend or affect ownership of any Python
254 * objects that reference the location in any way. */
255static inline PyObject *mlirPythonLocationToCapsule(MlirLocation loc) {
256 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(loc),
257 MLIR_PYTHON_CAPSULE_LOCATION, NULL);
258}
259
260/** Extracts an MlirLocation from a capsule as produced from
261 * mlirPythonLocationToCapsule. If the capsule is not of the right type, then
262 * a null module is returned (as checked via mlirLocationIsNull). In such a
263 * case, the Python APIs will have already set an error. */
264static inline MlirLocation mlirPythonCapsuleToLocation(PyObject *capsule) {
265 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_LOCATION);
266 MlirLocation loc = {.ptr: ptr};
267 return loc;
268}
269
270/** Creates a capsule object encapsulating the raw C-API MlirModule.
271 * The returned capsule does not extend or affect ownership of any Python
272 * objects that reference the module in any way. */
273static inline PyObject *mlirPythonModuleToCapsule(MlirModule module) {
274 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(module),
275 MLIR_PYTHON_CAPSULE_MODULE, NULL);
276}
277
278/** Extracts an MlirModule from a capsule as produced from
279 * mlirPythonModuleToCapsule. If the capsule is not of the right type, then
280 * a null module is returned (as checked via mlirModuleIsNull). In such a
281 * case, the Python APIs will have already set an error. */
282static inline MlirModule mlirPythonCapsuleToModule(PyObject *capsule) {
283 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_MODULE);
284 MlirModule module = {.ptr: ptr};
285 return module;
286}
287
288/** Creates a capsule object encapsulating the raw C-API
289 * MlirFrozenRewritePatternSet.
290 * The returned capsule does not extend or affect ownership of any Python
291 * objects that reference the module in any way. */
292static inline PyObject *
293mlirPythonFrozenRewritePatternSetToCapsule(MlirFrozenRewritePatternSet pm) {
294 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(pm),
295 MLIR_PYTHON_CAPSULE_PASS_MANAGER, NULL);
296}
297
298/** Extracts an MlirFrozenRewritePatternSet from a capsule as produced from
299 * mlirPythonFrozenRewritePatternSetToCapsule. If the capsule is not of the
300 * right type, then a null module is returned. */
301static inline MlirFrozenRewritePatternSet
302mlirPythonCapsuleToFrozenRewritePatternSet(PyObject *capsule) {
303 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_PASS_MANAGER);
304 MlirFrozenRewritePatternSet pm = {.ptr: ptr};
305 return pm;
306}
307
308/** Creates a capsule object encapsulating the raw C-API MlirPassManager.
309 * The returned capsule does not extend or affect ownership of any Python
310 * objects that reference the module in any way. */
311static inline PyObject *mlirPythonPassManagerToCapsule(MlirPassManager pm) {
312 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(pm),
313 MLIR_PYTHON_CAPSULE_PASS_MANAGER, NULL);
314}
315
316/** Extracts an MlirPassManager from a capsule as produced from
317 * mlirPythonPassManagerToCapsule. If the capsule is not of the right type, then
318 * a null pass manager is returned (as checked via mlirPassManagerIsNull). */
319static inline MlirPassManager
320mlirPythonCapsuleToPassManager(PyObject *capsule) {
321 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_PASS_MANAGER);
322 MlirPassManager pm = {.ptr: ptr};
323 return pm;
324}
325
326/** Creates a capsule object encapsulating the raw C-API MlirOperation.
327 * The returned capsule does not extend or affect ownership of any Python
328 * objects that reference the operation in any way.
329 */
330static inline PyObject *mlirPythonOperationToCapsule(MlirOperation operation) {
331 return PyCapsule_New(operation.ptr, MLIR_PYTHON_CAPSULE_OPERATION, NULL);
332}
333
334/** Extracts an MlirOperations from a capsule as produced from
335 * mlirPythonOperationToCapsule. If the capsule is not of the right type, then
336 * a null type is returned (as checked via mlirOperationIsNull). In such a
337 * case, the Python APIs will have already set an error. */
338static inline MlirOperation mlirPythonCapsuleToOperation(PyObject *capsule) {
339 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_OPERATION);
340 MlirOperation op = {.ptr: ptr};
341 return op;
342}
343
344/** Creates a capsule object encapsulating the raw C-API MlirTypeID.
345 * The returned capsule does not extend or affect ownership of any Python
346 * objects that reference the type in any way.
347 */
348static inline PyObject *mlirPythonTypeIDToCapsule(MlirTypeID typeID) {
349 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(typeID),
350 MLIR_PYTHON_CAPSULE_TYPEID, NULL);
351}
352
353/** Extracts an MlirTypeID from a capsule as produced from
354 * mlirPythonTypeIDToCapsule. If the capsule is not of the right type, then
355 * a null type is returned (as checked via mlirTypeIDIsNull). In such a
356 * case, the Python APIs will have already set an error. */
357static inline MlirTypeID mlirPythonCapsuleToTypeID(PyObject *capsule) {
358 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_TYPEID);
359 MlirTypeID typeID = {.ptr: ptr};
360 return typeID;
361}
362
363/** Creates a capsule object encapsulating the raw C-API MlirType.
364 * The returned capsule does not extend or affect ownership of any Python
365 * objects that reference the type in any way.
366 */
367static inline PyObject *mlirPythonTypeToCapsule(MlirType type) {
368 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(type),
369 MLIR_PYTHON_CAPSULE_TYPE, NULL);
370}
371
372/** Extracts an MlirType from a capsule as produced from
373 * mlirPythonTypeToCapsule. If the capsule is not of the right type, then
374 * a null type is returned (as checked via mlirTypeIsNull). In such a
375 * case, the Python APIs will have already set an error. */
376static inline MlirType mlirPythonCapsuleToType(PyObject *capsule) {
377 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_TYPE);
378 MlirType type = {.ptr: ptr};
379 return type;
380}
381
382/** Creates a capsule object encapsulating the raw C-API MlirAffineMap.
383 * The returned capsule does not extend or affect ownership of any Python
384 * objects that reference the type in any way.
385 */
386static inline PyObject *mlirPythonAffineMapToCapsule(MlirAffineMap affineMap) {
387 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(affineMap),
388 MLIR_PYTHON_CAPSULE_AFFINE_MAP, NULL);
389}
390
391/** Extracts an MlirAffineMap from a capsule as produced from
392 * mlirPythonAffineMapToCapsule. If the capsule is not of the right type, then
393 * a null type is returned (as checked via mlirAffineMapIsNull). In such a
394 * case, the Python APIs will have already set an error. */
395static inline MlirAffineMap mlirPythonCapsuleToAffineMap(PyObject *capsule) {
396 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_AFFINE_MAP);
397 MlirAffineMap affineMap = {.ptr: ptr};
398 return affineMap;
399}
400
401/** Creates a capsule object encapsulating the raw C-API MlirIntegerSet.
402 * The returned capsule does not extend or affect ownership of any Python
403 * objects that reference the set in any way. */
404static inline PyObject *
405mlirPythonIntegerSetToCapsule(MlirIntegerSet integerSet) {
406 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(integerSet),
407 MLIR_PYTHON_CAPSULE_INTEGER_SET, NULL);
408}
409
410/** Extracts an MlirIntegerSet from a capsule as produced from
411 * mlirPythonIntegerSetToCapsule. If the capsule is not of the right type, then
412 * a null set is returned (as checked via mlirIntegerSetIsNull). In such a
413 * case, the Python APIs will have already set an error. */
414static inline MlirIntegerSet mlirPythonCapsuleToIntegerSet(PyObject *capsule) {
415 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_INTEGER_SET);
416 MlirIntegerSet integerSet = {.ptr: ptr};
417 return integerSet;
418}
419
420/** Creates a capsule object encapsulating the raw C-API MlirExecutionEngine.
421 * The returned capsule does not extend or affect ownership of any Python
422 * objects that reference the set in any way. */
423static inline PyObject *
424mlirPythonExecutionEngineToCapsule(MlirExecutionEngine jit) {
425 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(jit),
426 MLIR_PYTHON_CAPSULE_EXECUTION_ENGINE, NULL);
427}
428
429/** Extracts an MlirExecutionEngine from a capsule as produced from
430 * mlirPythonIntegerSetToCapsule. If the capsule is not of the right type, then
431 * a null set is returned (as checked via mlirExecutionEngineIsNull). In such a
432 * case, the Python APIs will have already set an error. */
433static inline MlirExecutionEngine
434mlirPythonCapsuleToExecutionEngine(PyObject *capsule) {
435 void *ptr =
436 PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_EXECUTION_ENGINE);
437 MlirExecutionEngine jit = {.ptr: ptr};
438 return jit;
439}
440
441/** Creates a capsule object encapsulating the raw C-API MlirValue.
442 * The returned capsule does not extend or affect ownership of any Python
443 * objects that reference the operation in any way.
444 */
445static inline PyObject *mlirPythonValueToCapsule(MlirValue value) {
446 return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(value),
447 MLIR_PYTHON_CAPSULE_VALUE, NULL);
448}
449
450/** Extracts an MlirValue from a capsule as produced from
451 * mlirPythonValueToCapsule. If the capsule is not of the right type, then a
452 * null type is returned (as checked via mlirValueIsNull). In such a case, the
453 * Python APIs will have already set an error. */
454static inline MlirValue mlirPythonCapsuleToValue(PyObject *capsule) {
455 void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_VALUE);
456 MlirValue value = {.ptr: ptr};
457 return value;
458}
459
460#ifdef __cplusplus
461}
462#endif
463
464#endif // MLIR_C_BINDINGS_PYTHON_INTEROP_H
465

source code of mlir/include/mlir-c/Bindings/Python/Interop.h