1717
1818#include " arrow/c/dlpack.h"
1919
20+ #include < memory>
21+ #include < type_traits>
22+ #include < vector>
23+
2024#include " arrow/array/array_base.h"
2125#include " arrow/c/dlpack_abi.h"
2226#include " arrow/device.h"
@@ -59,32 +63,35 @@ Result<DLDataType> GetDLDataType(const DataType& type) {
5963 }
6064}
6165
66+ template <typename DT >
6267struct ManagerCtx {
6368 std::shared_ptr<ArrayData> array;
64- DLManagedTensor tensor;
69+ DT tensor;
6570 int64_t strides = 1 ;
6671};
6772
68- } // namespace
69-
70- Result<DLManagedTensor*> ExportArray (const std::shared_ptr<Array>& arr) {
73+ template <typename DT >
74+ Result<DT *> ExportArrayImpl (const std::shared_ptr<Array>& arr) {
7175 // Define DLDevice struct and check if array type is supported
7276 // by the DLPack protocol at the same time. Raise TypeError if not.
7377 // Supported data types: int, uint, float with no validity buffer.
74- ARROW_ASSIGN_OR_RAISE (auto device, ExportDevice (arr))
78+ ARROW_ASSIGN_OR_RAISE (auto device, ExportDevice (arr));
7579
7680 // Define the DLDataType struct
7781 const DataType& type = *arr->type ();
78- std::shared_ptr<ArrayData> data = arr->data ();
7982 ARROW_ASSIGN_OR_RAISE (auto dlpack_type, GetDLDataType (type));
8083
8184 // Create ManagerCtx that will serve as the owner of the DLManagedTensor
82- auto ctx = std::make_unique<ManagerCtx>();
85+ auto ctx = std::make_unique<ManagerCtx<DT >>();
86+
87+ // Assign the Array data into the context
88+ ctx->array = arr->data ();
89+ auto & data = ctx->array ;
8390
8491 // Define the data pointer to the DLTensor
8592 // If array is of length 0, data pointer should be NULL
8693 if (arr->length () == 0 ) {
87- ctx->tensor .dl_tensor .data = NULL ;
94+ ctx->tensor .dl_tensor .data = nullptr ;
8895 } else {
8996 const auto data_offset = data->offset * type.byte_width ();
9097 ctx->tensor .dl_tensor .data =
@@ -98,15 +105,30 @@ Result<DLManagedTensor*> ExportArray(const std::shared_ptr<Array>& arr) {
98105 ctx->tensor .dl_tensor .byte_offset = 0 ;
99106 // Strides must be non-null when ndim > 0
100107 ctx->tensor .dl_tensor .strides = &ctx->strides ;
108+ if constexpr (std::is_same_v<DT , DLManagedTensorVersioned>) {
109+ ctx->tensor .version = {.major = DLPACK_MAJOR_VERSION , .minor = DLPACK_MINOR_VERSION };
110+ // Arrow contract is that array data is immutable once constructed
111+ ctx->tensor .flags = DLPACK_FLAG_BITMASK_READ_ONLY ;
112+ }
101113
102- ctx->array = std::move (data);
103114 ctx->tensor .manager_ctx = ctx.get ();
104- ctx->tensor .deleter = [](struct DLManagedTensor * self) {
105- delete reinterpret_cast <ManagerCtx*>(self->manager_ctx );
115+ ctx->tensor .deleter = [](DT * self) {
116+ delete reinterpret_cast <ManagerCtx< DT > *>(self->manager_ctx );
106117 };
107118 return &ctx.release ()->tensor ;
108119}
109120
121+ } // namespace
122+
123+ Result<DLManagedTensor*> ExportArray (const std::shared_ptr<Array>& arr) {
124+ return ExportArrayImpl<DLManagedTensor>(arr);
125+ }
126+
127+ Result<DLManagedTensorVersioned*> ExportArrayVersioned (
128+ const std::shared_ptr<Array>& arr) {
129+ return ExportArrayImpl<DLManagedTensorVersioned>(arr);
130+ }
131+
110132Result<DLDevice> ExportDevice (const std::shared_ptr<Array>& arr) {
111133 // Check if array is supported by the DLPack protocol.
112134 if (arr->null_count () > 0 ) {
@@ -133,30 +155,34 @@ Result<DLDevice> ExportDevice(const std::shared_ptr<Array>& arr) {
133155 }
134156}
135157
158+ namespace {
159+
160+ template <typename DT >
136161struct TensorManagerCtx {
137162 std::shared_ptr<Tensor> t;
138163 std::vector<int64_t > strides;
139164 std::vector<int64_t > shape;
140- DLManagedTensor tensor;
165+ DT tensor;
141166};
142167
143- Result<DLManagedTensor*> ExportTensor (const std::shared_ptr<Tensor>& t) {
168+ template <typename DT >
169+ Result<DT *> ExportTensorImpl (const std::shared_ptr<Tensor>& t) {
144170 // Define the DLDataType struct
145171 const DataType& type = *t->type ();
146172 ARROW_ASSIGN_OR_RAISE (auto dlpack_type, GetDLDataType (type));
147173
148174 // Define DLDevice struct
149- ARROW_ASSIGN_OR_RAISE (auto device, ExportDevice (t))
175+ ARROW_ASSIGN_OR_RAISE (auto device, ExportDevice (t));
150176
151177 // Create TensorManagerCtx that will serve as the owner of the DLManagedTensor
152- auto ctx = std::make_unique<TensorManagerCtx>();
178+ auto ctx = std::make_unique<TensorManagerCtx< DT > >();
153179
154180 // Define the data pointer to the DLTensor
155181 // If tensor is of length 0, data pointer should be NULL
156182 if (t->size () == 0 ) {
157- ctx->tensor .dl_tensor .data = NULL ;
183+ ctx->tensor .dl_tensor .data = nullptr ;
158184 } else {
159- ctx->tensor .dl_tensor .data = t->raw_mutable_data ( );
185+ ctx->tensor .dl_tensor .data = const_cast < uint8_t *>( t->raw_data () );
160186 }
161187
162188 ctx->tensor .dl_tensor .device = device;
@@ -173,20 +199,35 @@ Result<DLManagedTensor*> ExportTensor(const std::shared_ptr<Tensor>& t) {
173199
174200 std::vector<int64_t >& strides_arr = ctx->strides ;
175201 strides_arr.reserve (t->ndim ());
176- auto byte_width = t->type ()->byte_width ();
202+ const auto byte_width = t->type ()->byte_width ();
177203 for (auto i : t->strides ()) {
178204 strides_arr.emplace_back (i / byte_width);
179205 }
180206 ctx->tensor .dl_tensor .strides = strides_arr.data ();
207+ if constexpr (std::is_same_v<DT , DLManagedTensorVersioned>) {
208+ ctx->tensor .version = {.major = DLPACK_MAJOR_VERSION , .minor = DLPACK_MINOR_VERSION };
209+ ctx->tensor .flags = t->is_mutable () ? 0 : DLPACK_FLAG_BITMASK_READ_ONLY ;
210+ }
181211
182212 ctx->t = std::move (t);
183213 ctx->tensor .manager_ctx = ctx.get ();
184- ctx->tensor .deleter = [](struct DLManagedTensor * self) {
185- delete reinterpret_cast <TensorManagerCtx*>(self->manager_ctx );
214+ ctx->tensor .deleter = [](DT * self) {
215+ delete reinterpret_cast <TensorManagerCtx< DT > *>(self->manager_ctx );
186216 };
187217 return &ctx.release ()->tensor ;
188218}
189219
220+ } // namespace
221+
222+ Result<DLManagedTensor*> ExportTensor (const std::shared_ptr<Tensor>& t) {
223+ return ExportTensorImpl<DLManagedTensor>(t);
224+ }
225+
226+ Result<DLManagedTensorVersioned*> ExportTensorVersioned (
227+ const std::shared_ptr<Tensor>& t) {
228+ return ExportTensorImpl<DLManagedTensorVersioned>(t);
229+ }
230+
190231Result<DLDevice> ExportDevice (const std::shared_ptr<Tensor>& t) {
191232 // Define DLDevice struct
192233 DLDevice device;
0 commit comments