@@ -363,14 +363,11 @@ typedef struct DLManagedTensorVersioned {
363363// --------------------------------------------------------------------
364364// DLPack C functions for speed exchange
365365// --------------------------------------------------------------------
366- /*
366+ /* !
367367 * \brief A generic C-style allocator that exposes allocation of a Tensor/Array.
368368 *
369- * Array/Tensor libraries can store this field as an int in the type of the Tensor/Array.
370- *
371- * mypackage.Tensor.__c_dlpack_tensor_allocator__ = MyPackageDLPackTensorAllocator
372- *
373369 * This information can then be used to set allocators of a callee to run allocations.
370+ * This function can be exposed by the framework through the DLPackExchangeAPI.
374371 *
375372 * This particular function does not assume a Python environment; as a result,
376373 * the error handling mechanism is different from Python-related functions.
@@ -383,6 +380,8 @@ typedef struct DLManagedTensorVersioned {
383380 * \return 0 on success, -1 on failure.
384381 * The callee should call SetError(error_ctx, kind, message) to set the error kind and message.
385382 * \note Error propagation via SetError.
383+ *
384+ * \sa DLPackExchangeAPI
386385 */
387386typedef int (*DLPackTensorAllocator)( //
388387 DLTensor* prototype, DLManagedTensorVersioned** out, void * error_ctx, //
@@ -398,9 +397,7 @@ typedef int (*DLPackTensorAllocator)( //
398397 * It also provides an option to query the current context stream of the device provided
399398 * by the tensor.
400399 *
401- * Array/Tensor libraries can store this field as an int in the type of the Tensor/Array.
402- *
403- * mypackage.Tensor.__c_dlpack_from_pyobject__ = MyPackageDLPackFromPyObject
400+ * This function is exposed by the framework through the DLPackExchangeAPI.
404401 *
405402 * This information can then be picked up by importers and libraries to run the speed conversion.
406403 * This function should not throw any exceptions; if it fails, it should return -1 and
@@ -414,6 +411,8 @@ typedef int (*DLPackTensorAllocator)( //
414411 * \return 0 on success, -1 on failure. PyError should be set if -1 is returned.
415412 * \note We use void* to avoid dependency on Python.h, so this specific type is
416413 * not dependent on Python.h and can be copied to dlpack.h.
414+ *
415+ * \sa DLPackExchangeAPI
417416 */
418417typedef int (*DLPackFromPyObject)( //
419418 void * py_object, //
@@ -427,18 +426,71 @@ typedef int (*DLPackFromPyObject)( //
427426 * This function is a C-style function pointer to quickly convert a DLManagedTensorVersioned
428427 * to a PyObject* without going through the Python Interpreter.
429428 *
430- * Array/Tensor libraries can store this field as an int in the type of the Tensor/Array.
431- *
432- * mypackage.Tensor.__c_dlpack_to_pyobject__ = MyPackageDLPackToPyObject
429+ * This function is exposed by the framework through the DLPackExchangeAPI.
433430 *
434431 * \param tensor The DLManagedTensorVersioned to convert.
435432 * \param out_py_object The output Python object.
436433 * \return 0 on success, -1 on failure. PyError should be set if -1 is returned.
437434 * \note We use void* to avoid dependency on Python.h, so this specific type is
438435 * not dependent on Python.h and can be copied to dlpack.h.
436+ *
437+ * \sa DLPackExchangeAPI
439438 */
440439typedef int (*DLPackToPyObject)(DLManagedTensorVersioned* tensor, void ** out_py_object);
441440
441+ /* !
442+ * \brief Framework-specific function pointers table for DLPack exchange.
443+ *
444+ * Array/Tensor librarie should statically create and initialize this structure
445+ * then return a pointer to DLPackExchangeAPI as an int value in Tensor/Array.
446+ * The DLPackExchangeAPI* should stay alive throughout the lifetime of process.
447+ *
448+ * One simple way to do so is to create a static instance of DLPackExchangeAPI
449+ * within the framework and return a pointer to it, the following code
450+ * shows an example to do so in c++. It should also be reasonably easy
451+ * to do so in other languages.
452+ *
453+ * \code{.cpp}
454+ * struct MyDLPackExchangeAPI : public DLPackExchangeAPI {
455+ * MyDLPackExchangeAPI() {
456+ * version.major = DLPACK_MAJOR_VERSION;
457+ * version.minor = DLPACK_MINOR_VERSION;
458+ * tensor_allocator = MyDLPackTensorAllocator;
459+ * dlpack_from_py_object = MyDLPackFromPyObject;
460+ * dlpack_to_py_object = MyDLPackToPyObject
461+ * }
462+ *
463+ * const DLPackExchangeAPI* Global() {
464+ * static MyDLPackExchangeAPI inst;
465+ * return &inst;
466+ * }
467+ * };
468+ * \endcode
469+ *
470+ * mypackage.Tensor.__c_dlpack_exchange_api__ = MyPackageDLPackExchangeAPI
471+ */
472+ struct DLPackExchangeAPI {
473+ /* !
474+ * \brief The current DLPack version.
475+ */
476+ DLPackVersion version;
477+ /* !
478+ * \brief Framework-specific function pointer for DLPackTensorAllocator
479+ * \sa DLPackTensorAllocator
480+ */
481+ DLPackTensorAllocator tensor_allocator;
482+ /* !
483+ * \brief Framework-specific function pointer for DLPackFromPyObject
484+ * \sa DLPackFromPyObject
485+ */
486+ DLPackFromPyObject dlpack_from_py_object;
487+ /* !
488+ * \brief Framework-specific function pointer for DLPackToPyObject
489+ * \sa DLPackToPyObject
490+ */
491+ DLPackToPyObject dlpack_to_py_object;
492+ };
493+
442494#ifdef __cplusplus
443495} // DLPACK_EXTERN_C
444496#endif
0 commit comments