| 120 | } |
| 121 | |
| 122 | bool ExternalBuffer::load(PyObject *o) |
| 123 | { |
| 124 | if (!o) |
| 125 | { |
| 126 | return false; |
| 127 | } |
| 128 | |
| 129 | py::object tmp = py::reinterpret_borrow<py::object>(o); |
| 130 | |
| 131 | if (hasattr(tmp, "__cuda_array_interface__")) |
| 132 | { |
| 133 | py::dict iface = tmp.attr("__cuda_array_interface__").cast<py::dict>(); |
| 134 | |
| 135 | if (!iface.contains("shape") || !iface.contains("typestr") || !iface.contains("data") |
| 136 | || !iface.contains("version")) |
| 137 | { |
| 138 | return false; |
| 139 | } |
| 140 | |
| 141 | int version = iface["version"].cast<int>(); |
| 142 | if (version < 2) |
| 143 | { |
| 144 | return false; |
| 145 | } |
| 146 | |
| 147 | DLPackTensor dlTensor; |
| 148 | { |
| 149 | DLManagedTensor dlManagedTensor = {}; |
| 150 | dlManagedTensor.deleter = [](DLManagedTensor *self) |
| 151 | { |
| 152 | delete[] self->dl_tensor.shape; |
| 153 | delete[] self->dl_tensor.strides; |
| 154 | }; |
| 155 | dlTensor = DLPackTensor{std::move(dlManagedTensor)}; |
| 156 | } |
| 157 | |
| 158 | dlTensor->byte_offset = 0; |
| 159 | |
| 160 | // TODO: infer the device type from the memory buffer |
| 161 | dlTensor->device.device_type = kDLCUDA; |
| 162 | // TODO: infer the device from the memory buffer |
| 163 | dlTensor->device.device_id = 0; |
| 164 | |
| 165 | // Convert data |
| 166 | py::tuple tdata = iface["data"].cast<py::tuple>(); |
| 167 | void *ptr = reinterpret_cast<void *>(tdata[0].cast<long>()); |
| 168 | CheckValidCUDABuffer(ptr); |
| 169 | dlTensor->data = ptr; |
| 170 | |
| 171 | // Convert DataType |
| 172 | py::dtype dt = util::ToDType(iface["typestr"].cast<std::string>()); |
| 173 | if (std::optional<nvcv::DataType> dtype = ToNVCVDataType(dt)) |
| 174 | { |
| 175 | dlTensor->dtype = ToDLDataType(*dtype); |
| 176 | } |
| 177 | |
| 178 | // Convert ndim |
| 179 | py::tuple shape = iface["shape"].cast<py::tuple>(); |
nothing calls this directly
no test coverage detected