kylebarron commented on issue #5067:
URL: https://github.com/apache/arrow-rs/issues/5067#issuecomment-1807223646
> std::ptr::read to obtain an owned value
Awesome! Sorry, I'm still learning low-level FFI stuff in Rust and didn't
know
With that I got it to work!
```rs
#[pyfunction]
pub fn read_array(ob: &'_ PyAny) -> PyResult<()> {
let arr = pyobj_to_array(ob)?;
println!("{:?}", arr);
Ok(())
}
pub fn pyobj_to_array(ob: &'_ PyAny) -> PyResult<ArrayData> {
if ob.hasattr("__arrow_c_array__")? {
let tuple = ob.getattr("__arrow_c_array__")?.call0()?;
if !tuple.is_instance_of::<PyTuple>() {
return Err(PyTypeError::new_err(
"Expected __arrow_c_array__ to return a tuple.",
));
}
let schema_capsule = tuple.get_item(0)?;
if !schema_capsule.is_instance_of::<PyCapsule>() {
return Err(PyTypeError::new_err(
"Expected __arrow_c_array__ first element to be PyCapsule.",
));
}
let schema_capsule: &PyCapsule =
PyTryInto::try_into(schema_capsule)?;
let schema_capsule_name = schema_capsule.name()?;
if schema_capsule_name.is_none() {
return Err(PyValueError::new_err(
"Expected PyCapsule to have name set.",
));
}
let schema_capsule_name = schema_capsule_name.unwrap().to_str()?;
if schema_capsule_name != "arrow_schema" {
return Err(PyValueError::new_err(
"Expected name 'arrow_schema' in PyCapsule.",
));
}
let array_capsule = tuple.get_item(1)?;
if !array_capsule.is_instance_of::<PyCapsule>() {
return Err(PyTypeError::new_err(
"Expected __arrow_c_array__ second element to be PyCapsule.",
));
}
let array_capsule: &PyCapsule = PyTryInto::try_into(array_capsule)?;
let array_capsule_name = array_capsule.name()?;
if array_capsule_name.is_none() {
return Err(PyValueError::new_err(
"Expected PyCapsule to have name set.",
));
}
let array_capsule_name = array_capsule_name.unwrap().to_str()?;
if array_capsule_name != "arrow_array" {
return Err(PyValueError::new_err(
"Expected name 'arrow_array' in PyCapsule.",
));
}
let array_ptr = array_capsule.pointer();
let array_ptr = array_ptr as *const ffi::FFI_ArrowArray;
let owned_array_ptr = unsafe { std::ptr::read(array_ptr) };
let arr = unsafe {
ffi::from_ffi(
owned_array_ptr,
schema_capsule.reference::<ffi::FFI_ArrowSchema>(),
)
.unwrap()
};
return Ok(arr);
}
Err(PyValueError::new_err(
"Expected an object with dunder __arrow_c_array__",
))
}
```
Then in Python:
```py
>>> import pyarrow as pa
>>> arr = pa.array([1, 2, 3, 4])
>>> geoarrow.rust.rust.read_array(arr)
ArrayData { data_type: Int64, len: 4, offset: 0, buffers: [Buffer { data:
Bytes { ptr: 0x596540300c0, len: 32, data: [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0] }, ptr:
0x596540300c0, length: 32 }], child_data: [], nulls: None }
```
I'm still not 100% understanding the ownership model of the pycapsule, but
at least the proof of concept works
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]