| 483 | } |
| 484 | |
| 485 | Status PyArrayToTF_Tensor(PyObject* ndarray, Safe_TF_TensorPtr* out_tensor) { |
| 486 | DCHECK(out_tensor != nullptr); |
| 487 | |
| 488 | // Make sure we dereference this array object in case of error, etc. |
| 489 | Safe_PyObjectPtr array_safe(make_safe( |
| 490 | PyArray_FromAny(ndarray, nullptr, 0, 0, NPY_ARRAY_CARRAY_RO, nullptr))); |
| 491 | if (!array_safe) return errors::InvalidArgument("Not a ndarray."); |
| 492 | PyArrayObject* array = reinterpret_cast<PyArrayObject*>(array_safe.get()); |
| 493 | |
| 494 | // Convert numpy dtype to TensorFlow dtype. |
| 495 | TF_DataType dtype = TF_FLOAT; |
| 496 | TF_RETURN_IF_ERROR(PyArray_TYPE_to_TF_DataType(array, &dtype)); |
| 497 | |
| 498 | tensorflow::int64 nelems = 1; |
| 499 | gtl::InlinedVector<int64_t, 4> dims; |
| 500 | for (int i = 0; i < PyArray_NDIM(array); ++i) { |
| 501 | dims.push_back(PyArray_SHAPE(array)[i]); |
| 502 | nelems *= dims[i]; |
| 503 | } |
| 504 | |
| 505 | // Create a TF_Tensor based on the fed data. In the case of non-string data |
| 506 | // type, this steals a reference to array, which will be relinquished when |
| 507 | // the underlying buffer is deallocated. For string, a new temporary buffer |
| 508 | // is allocated into which the strings are encoded. |
| 509 | if (dtype == TF_RESOURCE) { |
| 510 | size_t size = PyArray_NBYTES(array); |
| 511 | array_safe.release(); |
| 512 | *out_tensor = make_safe(TF_NewTensor(dtype, {}, 0, PyArray_DATA(array), |
| 513 | size, &DelayedNumpyDecref, array)); |
| 514 | |
| 515 | } else if (dtype != TF_STRING) { |
| 516 | size_t size = PyArray_NBYTES(array); |
| 517 | array_safe.release(); |
| 518 | *out_tensor = make_safe(TF_NewTensor(dtype, dims.data(), dims.size(), |
| 519 | PyArray_DATA(array), size, |
| 520 | &DelayedNumpyDecref, array)); |
| 521 | } else { |
| 522 | size_t size = 0; |
| 523 | void* encoded = nullptr; |
| 524 | TF_RETURN_IF_ERROR(EncodePyBytesArray(array, nelems, &size, &encoded)); |
| 525 | *out_tensor = |
| 526 | make_safe(TF_NewTensor(dtype, dims.data(), dims.size(), encoded, size, |
| 527 | [](void* data, size_t len, void* arg) { |
| 528 | delete[] reinterpret_cast<char*>(data); |
| 529 | }, |
| 530 | nullptr)); |
| 531 | } |
| 532 | return Status::OK(); |
| 533 | } |
| 534 | |
| 535 | Status TF_TensorToTensor(const TF_Tensor* src, Tensor* dst); |
| 536 | TF_Tensor* TF_TensorFromTensor(const tensorflow::Tensor& src, |
no test coverage detected