Skip to content

Commit add0db0

Browse files
committed
Add PyCapsule_New and PyCapsule_GetPointer
These are critical when interacting with PyCapsules created by other libraries in the system. The current use case is interacting with PyArrow. Signed-off-by: Marius Seritan <[email protected]>
1 parent 84c3eef commit add0db0

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

mojo/stdlib/src/python/_cpython.mojo

+28
Original file line numberDiff line numberDiff line change
@@ -1939,3 +1939,31 @@ struct CPython:
19391939

19401940
self._inc_total_rc()
19411941
return r
1942+
1943+
# ===-------------------------------------------------------------------===#
1944+
# Python Capsule API
1945+
# ===-------------------------------------------------------------------===#
1946+
fn PyCapsule_New(
1947+
mut self,
1948+
pointer: OpaquePointer,
1949+
name: StringSlice,
1950+
destructor: destructor,
1951+
) -> PyObjectPtr:
1952+
"""[Reference](
1953+
https://docs.python.org/3/c-api/capsule.html#c.PyCapsule_New).
1954+
"""
1955+
return self.lib.call["PyCapsule_New", PyObjectPtr](
1956+
pointer, name.unsafe_ptr(), destructor
1957+
)
1958+
1959+
fn PyCapsule_GetPointer(
1960+
mut self,
1961+
capsule: PyObjectPtr,
1962+
name: StringSlice,
1963+
) -> OpaquePointer:
1964+
"""[Reference](
1965+
https://docs.python.org/3/c-api/capsule.html#c.PyCapsule_GetPointer).
1966+
"""
1967+
return self.lib.call["PyCapsule_GetPointer", OpaquePointer](
1968+
capsule, name.unsafe_ptr()
1969+
)

mojo/stdlib/test/python/test_python_cpython.mojo

+29
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
# RUN: %mojo %s
1515

1616
from python import Python, PythonObject
17+
from python._cpython import PyObjectPtr
18+
from memory import UnsafePointer
1719
from testing import assert_equal, assert_false, assert_raises, assert_true
1820

1921

@@ -34,7 +36,34 @@ def test_PyObject_HasAttrString(mut python: Python):
3436
_ = the_object
3537

3638

39+
fn destructor(capsule: PyObjectPtr) -> None:
40+
pass
41+
42+
43+
def test_PyCapsule(mut python: Python):
44+
var Cpython_env = python.impl._cpython
45+
46+
# Not a PyCapsule, a NULL pointer is expected.
47+
var the_object = PythonObject(0)
48+
var result = Cpython_env[].PyCapsule_GetPointer(
49+
the_object.py_object, "some_name"
50+
)
51+
var expected = UnsafePointer[NoneType]()
52+
assert_equal(expected, result)
53+
54+
# Build a capsule.
55+
var capsule_impl = UnsafePointer[UInt64].alloc(1)
56+
var capsule = Cpython_env[].PyCapsule_New(
57+
capsule_impl.bitcast[NoneType](), "some_name", destructor
58+
)
59+
var capsule_pointer = Cpython_env[].PyCapsule_GetPointer(
60+
capsule, "some_name"
61+
)
62+
assert_equal(capsule_impl.bitcast[NoneType](), capsule_pointer)
63+
64+
3765
def main():
3866
# initializing Python instance calls init_python
3967
var python = Python()
4068
test_PyObject_HasAttrString(python)
69+
test_PyCapsule(python)

0 commit comments

Comments
 (0)