Skip to content

Commit dc6fb46

Browse files
committed
Implement native buffer API for ctypes CData types
1 parent 9609737 commit dc6fb46

File tree

11 files changed

+284
-1
lines changed

11 files changed

+284
-1
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,27 @@ PyAPI_FUNC(void) mmap_init_bufferprotocol(PyObject* mmap_type) {
249249
(getbufferproc)mmap_getbuffer,
250250
(releasebufferproc)NULL,
251251
};
252-
set_PyTypeObject_tp_as_buffer(mmap_type, &mmap_as_buffer);
252+
GraalPy_set_PyTypeObject_tp_as_buffer(mmap_type, &mmap_as_buffer);
253253
((PyTypeObject*) mmap_type)->tp_as_buffer = &mmap_as_buffer;
254254
}
255255

256+
static int PyTruffleCData_NewGetBuffer(PyObject* type, Py_buffer* view, int flags) {
257+
return GraalPyTruffleCData_NewGetBuffer(type, view, flags);
258+
}
259+
260+
static void PyTruffleCData_ReleaseBuffer(PyObject* obj, Py_buffer* view) {
261+
return GraalPyTruffleCData_ReleaseBuffer(obj, view);
262+
}
263+
264+
PyAPI_FUNC(void) PyTruffleCData_InitBufferProtocol(PyObject* type) {
265+
static PyBufferProcs cdata_as_buffer = {
266+
PyTruffleCData_NewGetBuffer,
267+
PyTruffleCData_ReleaseBuffer,
268+
};
269+
GraalPy_set_PyTypeObject_tp_as_buffer(type, &cdata_as_buffer);
270+
((PyTypeObject*) type)->tp_as_buffer = &cdata_as_buffer;
271+
}
272+
256273
struct _longobject* _Py_FalseStructReference;
257274
struct _longobject* _Py_TrueStructReference;
258275
PyObject* _Py_EllipsisObjectReference;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import ctypes
2+
import struct
3+
4+
from tests.cpyext import CPyExtTestCase, CPyExtType
5+
6+
BufferTester = CPyExtType(
7+
'BufferTester',
8+
cmembers='Py_buffer buffer;',
9+
code='''
10+
static PyObject* buffer_tester_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
11+
PyObject* obj;
12+
if (PyArg_ParseTuple(args, "O", &obj) < 0)
13+
return NULL;
14+
PyObject* self = type->tp_alloc(type, 0);
15+
if (!self)
16+
return NULL;
17+
if (PyObject_GetBuffer(obj, &((BufferTesterObject*)self)->buffer, PyBUF_CONTIG_RO) < 0) {
18+
Py_DECREF(self);
19+
return NULL;
20+
}
21+
return self;
22+
}
23+
24+
static PyObject* buffer_tester_enter(PyObject* self) {
25+
return Py_NewRef(self);
26+
}
27+
28+
static PyObject* buffer_tester_exit(BufferTesterObject* self, PyObject* args) {
29+
PyBuffer_Release(&self->buffer);
30+
Py_RETURN_NONE;
31+
}
32+
33+
static PyObject* buffer_tester_obj(BufferTesterObject* self) {
34+
return Py_NewRef(self->buffer.obj);
35+
}
36+
37+
static PyObject* buffer_tester_bytes(BufferTesterObject* self) {
38+
return PyBytes_FromStringAndSize(self->buffer.buf, self->buffer.len);
39+
}
40+
41+
static PyObject* buffer_tester_itemsize(BufferTesterObject* self) {
42+
return PyLong_FromLong(self->buffer.itemsize);
43+
}
44+
45+
static PyObject* buffer_tester_format(BufferTesterObject* self) {
46+
return PyBytes_FromString(self->buffer.format);
47+
}
48+
''',
49+
tp_new='buffer_tester_new',
50+
tp_methods='''
51+
{"__enter__", (PyCFunction)buffer_tester_enter, METH_NOARGS, ""},
52+
{"__exit__", (PyCFunction)buffer_tester_exit, METH_VARARGS, ""}
53+
''',
54+
tp_getset='''
55+
{"obj", (getter)buffer_tester_obj, NULL, NULL, NULL},
56+
{"bytes", (getter)buffer_tester_bytes, NULL, NULL, NULL},
57+
{"itemsize", (getter)buffer_tester_itemsize, NULL, NULL, NULL},
58+
{"format", (getter)buffer_tester_format, NULL, NULL, NULL}
59+
''',
60+
)
61+
62+
63+
class TestCDataBuffer(CPyExtTestCase):
64+
def test_buffer(self):
65+
numbers = [1, 2, 3, 4]
66+
array = (ctypes.c_int * 4)(*numbers)
67+
with BufferTester(array) as buffer:
68+
assert buffer.obj is array
69+
assert buffer.bytes == b''.join(struct.pack("i", n) for n in numbers)
70+
assert buffer.itemsize == 4
71+
assert buffer.format == b'<i'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.oracle.graal.python.builtins.modules.cext;
2+
3+
import static com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath.Ignored;
4+
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.Int;
5+
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PY_BUFFER_PTR;
6+
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObject;
7+
8+
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBinaryBuiltinNode;
9+
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin;
10+
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiTernaryBuiltinNode;
11+
import com.oracle.graal.python.builtins.modules.ctypes.CDataObject;
12+
import com.oracle.graal.python.builtins.modules.ctypes.CtypesNodes;
13+
import com.oracle.graal.python.builtins.objects.PNone;
14+
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor;
15+
import com.oracle.truffle.api.dsl.Bind;
16+
import com.oracle.truffle.api.dsl.Cached;
17+
import com.oracle.truffle.api.dsl.Specialization;
18+
import com.oracle.truffle.api.interop.InteropLibrary;
19+
import com.oracle.truffle.api.library.CachedLibrary;
20+
import com.oracle.truffle.api.nodes.Node;
21+
22+
public final class PythonCextCDataBuiltins {
23+
@CApiBuiltin(ret = Int, args = {PyObject, PY_BUFFER_PTR, Int}, call = Ignored)
24+
abstract static class PyTruffleCData_NewGetBuffer extends CApiTernaryBuiltinNode {
25+
@Specialization
26+
static int getBuffer(CDataObject self, Object view, int flags,
27+
@Bind("this") Node inliningTarget,
28+
@CachedLibrary(limit = "1") InteropLibrary lib,
29+
@Cached CtypesNodes.CDataGetBufferNode getBufferNode) {
30+
if (lib.isNull(view)) {
31+
return 0;
32+
}
33+
getBufferNode.execute(inliningTarget, self, view, flags);
34+
return 0;
35+
}
36+
}
37+
38+
@CApiBuiltin(ret = ArgDescriptor.Void, args = {PyObject, PY_BUFFER_PTR}, call = Ignored)
39+
abstract static class PyTruffleCData_ReleaseBuffer extends CApiBinaryBuiltinNode {
40+
@Specialization
41+
static Object releaseBuffer(@SuppressWarnings("unused") CDataObject self, Object view,
42+
@Bind("this") Node inliningTarget,
43+
@Cached CtypesNodes.CDataReleaseBufferNode releaseBufferNode) {
44+
releaseBufferNode.execute(inliningTarget, view);
45+
return PNone.NO_VALUE;
46+
}
47+
}
48+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CDataBuiltins.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltins.TYPEFLAG_HASPOINTER;
4545
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltins.TYPEFLAG_ISPOINTER;
4646
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltins.T_UNPICKLE;
47+
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PY_TRUFFLE_CDATA_INIT_BUFFER_PROTOCOL;
4748
import static com.oracle.graal.python.nodes.BuiltinNames.T__CTYPES;
4849
import static com.oracle.graal.python.nodes.ErrorMessages.CTYPES_OBJECTS_CONTAINING_POINTERS_CANNOT_BE_PICKLED;
4950
import static com.oracle.graal.python.nodes.ErrorMessages.S_DICT_MUST_BE_A_DICTIONARY_NOT_S;
@@ -60,10 +61,13 @@
6061

6162
import com.oracle.graal.python.builtins.Builtin;
6263
import com.oracle.graal.python.builtins.CoreFunctions;
64+
import com.oracle.graal.python.builtins.Python3Core;
6365
import com.oracle.graal.python.builtins.PythonBuiltins;
6466
import com.oracle.graal.python.builtins.modules.ctypes.StgDictBuiltins.PyObjectStgDictNode;
6567
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerNodes;
6668
import com.oracle.graal.python.builtins.objects.PNone;
69+
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
70+
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeNode;
6771
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageAddAllToOther;
6872
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
6973
import com.oracle.graal.python.builtins.objects.dict.PDict;
@@ -101,6 +105,12 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
101105
return CDataBuiltinsFactory.getFactories();
102106
}
103107

108+
@Override
109+
public void postInitialize(Python3Core core) {
110+
super.postInitialize(core);
111+
core.getContext().registerCApiHook(() -> PCallCapiFunction.getUncached().call(FUN_PY_TRUFFLE_CDATA_INIT_BUFFER_PROTOCOL, PythonToNativeNode.executeUncached(PyCData)));
112+
}
113+
104114
@Builtin(name = "_b_base_", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 1, isGetter = true, doc = "the base object")
105115
@GenerateNodeFactory
106116
protected abstract static class BBaseNode extends PythonUnaryBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/CtypesNodes.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,20 @@
5555
import static com.oracle.graal.python.nodes.truffle.TruffleStringMigrationHelpers.isJavaString;
5656
import static com.oracle.graal.python.util.PythonUtils.ARRAY_ACCESSOR;
5757
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
58+
import static com.oracle.truffle.api.strings.TruffleString.Encoding.US_ASCII;
5859

60+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
5961
import com.oracle.graal.python.builtins.PythonOS;
6062
import com.oracle.graal.python.builtins.modules.ctypes.FFIType.FFI_TYPES;
6163
import com.oracle.graal.python.builtins.modules.ctypes.memory.Pointer;
6264
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerNodes;
6365
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerReference;
66+
import com.oracle.graal.python.builtins.objects.cext.common.NativePointer;
67+
import com.oracle.graal.python.builtins.objects.cext.structs.CFields;
68+
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess;
6469
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
6570
import com.oracle.graal.python.builtins.objects.type.TypeNodes.IsSameTypeNode;
71+
import com.oracle.graal.python.lib.PyObjectTypeCheck;
6672
import com.oracle.graal.python.nodes.PRaiseNode;
6773
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
6874
import com.oracle.graal.python.nodes.object.GetClassNode;
@@ -76,6 +82,7 @@
7682
import com.oracle.truffle.api.dsl.GenerateUncached;
7783
import com.oracle.truffle.api.dsl.Specialization;
7884
import com.oracle.truffle.api.nodes.Node;
85+
import com.oracle.truffle.api.strings.InternalByteArray;
7986
import com.oracle.truffle.api.strings.TruffleString;
8087

8188
public class CtypesNodes {
@@ -379,4 +386,77 @@ static CDataObject doCreate(Node inliningTarget, Object type, StgDictObject dict
379386
return obj;
380387
}
381388
}
389+
390+
@GenerateInline
391+
@GenerateCached(false)
392+
public abstract static class CDataGetBufferNode extends Node {
393+
public abstract void execute(Node inliningTarget, CDataObject self, Object view, int flags);
394+
395+
@Specialization
396+
static void getBuffer(Node inliningTarget, CDataObject self, Object view, @SuppressWarnings("unused") int flags,
397+
@Cached PointerNodes.GetPointerValueAsObjectNode getPointerValue,
398+
@Cached GetClassNode getClassNode,
399+
@Cached PyObjectTypeCheck typeCheck,
400+
@Cached StgDictBuiltins.PyTypeStgDictNode stgDictNode,
401+
@Cached(inline = false) TruffleString.SwitchEncodingNode switchEncodingNode,
402+
@Cached(inline = false) TruffleString.GetInternalByteArrayNode getInternalByteArrayNode,
403+
@Cached(inline = false) CStructAccess.AllocateNode allocateNode,
404+
@Cached(inline = false) CStructAccess.WriteByteNode writeByteNode,
405+
@Cached(inline = false) CStructAccess.WritePointerNode writePointerNode,
406+
@Cached(inline = false) CStructAccess.WriteObjectNewRefNode writeObjectNewRefNode,
407+
@Cached(inline = false) CStructAccess.WriteLongNode writeLongNode,
408+
@Cached(inline = false) CStructAccess.WriteIntNode writeIntNode) {
409+
Object itemType = getClassNode.execute(inliningTarget, self);
410+
StgDictObject dict = stgDictNode.execute(inliningTarget, itemType);
411+
while (typeCheck.execute(inliningTarget, itemType, PythonBuiltinClassType.PyCArrayType)) {
412+
StgDictObject stgDict = stgDictNode.execute(inliningTarget, itemType);
413+
itemType = stgDict.proto;
414+
}
415+
StgDictObject itemDict = stgDictNode.execute(inliningTarget, itemType);
416+
417+
NativePointer nativeNull = PythonContext.get(inliningTarget).getNativeNull();
418+
419+
writePointerNode.write(view, CFields.Py_buffer__buf, getPointerValue.execute(inliningTarget, self.b_ptr));
420+
writeLongNode.write(view, CFields.Py_buffer__len, self.b_size);
421+
writeObjectNewRefNode.write(view, CFields.Py_buffer__obj, self);
422+
writeIntNode.write(view, CFields.Py_buffer__readonly, 0);
423+
424+
Object formatPtr;
425+
if (dict.format != null) {
426+
InternalByteArray formatArray = getInternalByteArrayNode.execute(switchEncodingNode.execute(dict.format, US_ASCII), US_ASCII);
427+
formatPtr = allocateNode.alloc(formatArray.getLength() + 1);
428+
writeByteNode.writeByteArray(formatPtr, formatArray.getArray(), formatArray.getLength(), formatArray.getOffset(), 0);
429+
} else {
430+
formatPtr = allocateNode.alloc(2);
431+
writeByteNode.write(formatPtr, (byte) 'B');
432+
}
433+
writePointerNode.write(view, CFields.Py_buffer__format, formatPtr);
434+
writeIntNode.write(view, CFields.Py_buffer__ndim, dict.ndim);
435+
Object shapePtr = allocateNode.alloc(dict.shape.length * Long.BYTES);
436+
long[] shapeArray = new long[dict.shape.length];
437+
for (int i = 0; i < dict.shape.length; i++) {
438+
shapeArray[i] = dict.shape[i];
439+
}
440+
writeLongNode.writeLongArray(shapePtr, shapeArray);
441+
writePointerNode.write(view, CFields.Py_buffer__shape, shapePtr);
442+
writeLongNode.write(view, CFields.Py_buffer__itemsize, itemDict.size);
443+
writePointerNode.write(view, CFields.Py_buffer__strides, nativeNull);
444+
writePointerNode.write(view, CFields.Py_buffer__suboffsets, nativeNull);
445+
writePointerNode.write(view, CFields.Py_buffer__internal, nativeNull);
446+
}
447+
}
448+
449+
@GenerateInline
450+
@GenerateCached(false)
451+
public abstract static class CDataReleaseBufferNode extends Node {
452+
public abstract void execute(Node inliningTarget, Object view);
453+
454+
@Specialization
455+
static void getBuffer(Object view,
456+
@Cached(inline = false) CStructAccess.ReadPointerNode readPointerNode,
457+
@Cached(inline = false) CStructAccess.FreeNode freeNode) {
458+
freeNode.free(readPointerNode.read(view, CFields.Py_buffer__format));
459+
freeNode.free(readPointerNode.read(view, CFields.Py_buffer__shape));
460+
}
461+
}
382462
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/PyCArrayBuiltins.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.builtins.modules.ctypes;
4242

4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PyCArray;
44+
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PY_TRUFFLE_CDATA_INIT_BUFFER_PROTOCOL;
4445
import static com.oracle.graal.python.nodes.ErrorMessages.ARRAY_DOES_NOT_SUPPORT_ITEM_DELETION;
4546
import static com.oracle.graal.python.nodes.ErrorMessages.CAN_ONLY_ASSIGN_SEQUENCE_OF_SAME_SIZE;
4647
import static com.oracle.graal.python.nodes.ErrorMessages.INDICES_MUST_BE_INTEGER;
@@ -63,6 +64,7 @@
6364
import com.oracle.graal.python.annotations.Slot.SlotKind;
6465
import com.oracle.graal.python.builtins.Builtin;
6566
import com.oracle.graal.python.builtins.CoreFunctions;
67+
import com.oracle.graal.python.builtins.Python3Core;
6668
import com.oracle.graal.python.builtins.PythonBuiltins;
6769
import com.oracle.graal.python.builtins.modules.ctypes.CDataTypeBuiltins.PyCDataGetNode;
6870
import com.oracle.graal.python.builtins.modules.ctypes.CDataTypeBuiltins.PyCDataSetNode;
@@ -71,6 +73,8 @@
7173
import com.oracle.graal.python.builtins.modules.ctypes.StgDictBuiltins.PyTypeStgDictNode;
7274
import com.oracle.graal.python.builtins.objects.PNone;
7375
import com.oracle.graal.python.builtins.objects.buffer.PythonBufferAccessLibrary;
76+
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
77+
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeNode;
7478
import com.oracle.graal.python.builtins.objects.function.PKeyword;
7579
import com.oracle.graal.python.builtins.objects.slice.PSlice;
7680
import com.oracle.graal.python.builtins.objects.slice.SliceNodes.AdjustIndices;
@@ -112,6 +116,12 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
112116
return PyCArrayBuiltinsFactory.getFactories();
113117
}
114118

119+
@Override
120+
public void postInitialize(Python3Core core) {
121+
super.postInitialize(core);
122+
core.getContext().registerCApiHook(() -> PCallCapiFunction.getUncached().call(FUN_PY_TRUFFLE_CDATA_INIT_BUFFER_PROTOCOL, PythonToNativeNode.executeUncached(PyCArray)));
123+
}
124+
115125
@Builtin(name = J___NEW__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
116126
@GenerateNodeFactory
117127
protected abstract static class NewNode extends PythonBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ctypes/PyCFuncPtrBuiltins.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.builtins.modules.ctypes;
4242

4343
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.NotImplementedError;
44+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PyCFuncPtr;
4445
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.RuntimeError;
4546
import static com.oracle.graal.python.builtins.modules.ctypes.CDataTypeBuiltins.T__HANDLE;
4647
import static com.oracle.graal.python.builtins.modules.ctypes.CtypesModuleBuiltins.FUNCFLAG_CDECL;
@@ -51,6 +52,7 @@
5152
import static com.oracle.graal.python.builtins.modules.ctypes.PyCFuncPtrTypeBuiltins.T__CHECK_RETVAL_;
5253
import static com.oracle.graal.python.builtins.modules.ctypes.PyCFuncPtrTypeBuiltins.T___CTYPES_FROM_OUTPARAM__;
5354
import static com.oracle.graal.python.builtins.modules.ctypes.PyCFuncPtrTypeBuiltins.PyCFuncPtrTypeNewNode.converters_from_argtypes;
55+
import static com.oracle.graal.python.builtins.objects.cext.capi.NativeCAPISymbol.FUN_PY_TRUFFLE_CDATA_INIT_BUFFER_PROTOCOL;
5456
import static com.oracle.graal.python.nodes.ErrorMessages.ARGTYPES_MUST_BE_A_SEQUENCE_OF_TYPES;
5557
import static com.oracle.graal.python.nodes.ErrorMessages.ARGUMENT_MUST_BE_CALLABLE_OR_INTEGER_FUNCTION_ADDRESS;
5658
import static com.oracle.graal.python.nodes.ErrorMessages.CALL_TAKES_EXACTLY_D_ARGUMENTS_D_GIVEN;
@@ -86,6 +88,7 @@
8688
import com.oracle.graal.python.annotations.Slot.SlotKind;
8789
import com.oracle.graal.python.builtins.Builtin;
8890
import com.oracle.graal.python.builtins.CoreFunctions;
91+
import com.oracle.graal.python.builtins.Python3Core;
8992
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
9093
import com.oracle.graal.python.builtins.PythonBuiltins;
9194
import com.oracle.graal.python.builtins.modules.SysModuleBuiltins.AuditNode;
@@ -101,6 +104,8 @@
101104
import com.oracle.graal.python.builtins.modules.ctypes.memory.PointerNodes;
102105
import com.oracle.graal.python.builtins.objects.PNone;
103106
import com.oracle.graal.python.builtins.objects.cext.PythonNativeVoidPtr;
107+
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
108+
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.PythonToNativeNode;
104109
import com.oracle.graal.python.builtins.objects.common.KeywordsStorage;
105110
import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes.GetInternalObjectArrayNode;
106111
import com.oracle.graal.python.builtins.objects.function.PKeyword;
@@ -157,6 +162,12 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
157162
return PyCFuncPtrBuiltinsFactory.getFactories();
158163
}
159164

165+
@Override
166+
public void postInitialize(Python3Core core) {
167+
super.postInitialize(core);
168+
core.getContext().registerCApiHook(() -> PCallCapiFunction.getUncached().call(FUN_PY_TRUFFLE_CDATA_INIT_BUFFER_PROTOCOL, PythonToNativeNode.executeUncached(PyCFuncPtr)));
169+
}
170+
160171
/*
161172
* PyCFuncPtr_new accepts different argument lists in addition to the standard _basespec_
162173
* keyword arg:

0 commit comments

Comments
 (0)