Skip to content

Commit e0aac13

Browse files
committed
Place utility NFI helpers within ctypes module
1 parent 63e2746 commit e0aac13

File tree

4 files changed

+49
-35
lines changed

4 files changed

+49
-35
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_ctypes.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*ctypes.test.test_arrays.ArrayTestCase.test_empty_element_array
88
*ctypes.test.test_arrays.ArrayTestCase.test_empty_element_struct
99
*ctypes.test.test_arrays.ArrayTestCase.test_large_array
10+
*ctypes.test.test_arrays.ArrayTestCase.test_simple
1011
*ctypes.test.test_arrays.ArrayTestCase.test_subclass
1112
*ctypes.test.test_arrays.ArrayTestCase.test_zero_length
1213
*ctypes.test.test_as_parameter.AsParamPropertyWrapperTestCase.test_recursive_as_param
@@ -25,6 +26,7 @@
2526
*ctypes.test.test_bitfields.BitFieldTest.test_single_bitfield_size
2627
*ctypes.test.test_bitfields.BitFieldTest.test_uint32
2728
*ctypes.test.test_buffers.StringBufferTestCase.test_buffer
29+
*ctypes.test.test_buffers.StringBufferTestCase.test_create_unicode_buffer_non_bmp
2830
*ctypes.test.test_bytes.BytesTest.test_BSTR
2931
*ctypes.test.test_bytes.BytesTest.test_c_char_p
3032
*ctypes.test.test_bytes.BytesTest.test_c_wchar_p
@@ -56,7 +58,9 @@
5658
*ctypes.test.test_callbacks.StdcallCallbacks.test_unsupported_restype_1
5759
*ctypes.test.test_callbacks.StdcallCallbacks.test_unsupported_restype_2
5860
*ctypes.test.test_callbacks.StdcallCallbacks.test_ushort
61+
*ctypes.test.test_cast.Test.test_array2pointer
5962
*ctypes.test.test_cast.Test.test_bad_type_arg
63+
*ctypes.test.test_cast.Test.test_other
6064
*ctypes.test.test_cast.Test.test_wchar_p
6165
*ctypes.test.test_cfuncs.stdcallCFunctions.test_byte
6266
*ctypes.test.test_cfuncs.stdcallCFunctions.test_byte_plus
@@ -97,6 +101,8 @@
97101
*ctypes.test.test_find.Test_OpenGL_libs.test_shell_injection
98102
*ctypes.test.test_frombuffer.Test.test_abstract
99103
*ctypes.test.test_frombuffer.Test.test_fortran_contiguous
104+
*ctypes.test.test_frombuffer.Test.test_from_buffer_copy
105+
*ctypes.test.test_frombuffer.Test.test_from_buffer_copy_with_offset
100106
*ctypes.test.test_frombuffer.Test.test_from_buffer_memoryview
101107
*ctypes.test.test_funcptr.CFuncPtrTestCase.test_abstract
102108
*ctypes.test.test_functions.FunctionTestCase.test_doubleresult
@@ -108,6 +114,7 @@
108114
*ctypes.test.test_functions.FunctionTestCase.test_struct_return_2H_stdcall
109115
*ctypes.test.test_functions.FunctionTestCase.test_struct_return_8H_stdcall
110116
*ctypes.test.test_functions.FunctionTestCase.test_wchar_parm
117+
*ctypes.test.test_functions.FunctionTestCase.test_wchar_result
111118
*ctypes.test.test_internals.ObjectsTestCase.test_embedded_structs
112119
*ctypes.test.test_internals.ObjectsTestCase.test_ptr_struct
113120
*ctypes.test.test_internals.ObjectsTestCase.test_simple_struct
@@ -174,6 +181,8 @@
174181
*ctypes.test.test_sizes.SizesTestCase.test_size_t
175182
*ctypes.test.test_sizes.SizesTestCase.test_ssize_t
176183
*ctypes.test.test_slicing.SlicesTestCase.test_char_array
184+
*ctypes.test.test_slicing.SlicesTestCase.test_getslice_cint
185+
*ctypes.test.test_slicing.SlicesTestCase.test_setslice_cint
177186
*ctypes.test.test_stringptr.StringPtrTestCase.test__POINTER_c_char
178187
*ctypes.test.test_strings.StringArrayTestCase.test_c_buffer_raw
179188
*ctypes.test.test_strings.StringArrayTestCase.test_c_buffer_value
@@ -193,6 +202,7 @@
193202
*ctypes.test.test_struct_fields.StructFieldsTestCase.test_2
194203
*ctypes.test.test_struct_fields.StructFieldsTestCase.test_3
195204
*ctypes.test.test_struct_fields.StructFieldsTestCase.test_4
205+
*ctypes.test.test_structures.StructureTestCase.test_38368
196206
*ctypes.test.test_structures.StructureTestCase.test_abstract_class
197207
*ctypes.test.test_structures.StructureTestCase.test_bitfield_by_value
198208
*ctypes.test.test_structures.StructureTestCase.test_conflicting_initializers
@@ -201,6 +211,7 @@
201211
*ctypes.test.test_structures.StructureTestCase.test_initializers
202212
*ctypes.test.test_structures.StructureTestCase.test_invalid_field_types
203213
*ctypes.test.test_structures.StructureTestCase.test_invalid_name
214+
*ctypes.test.test_structures.StructureTestCase.test_keyword_initializers
204215
*ctypes.test.test_structures.StructureTestCase.test_methods
205216
*ctypes.test.test_structures.StructureTestCase.test_packed_c_limits
206217
*ctypes.test.test_structures.StructureTestCase.test_struct_alignment

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

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
137137
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
138138
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode;
139+
import com.oracle.graal.python.nodes.function.builtins.PythonTernaryBuiltinNode;
139140
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
140141
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryClinicBuiltinNode;
141142
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
@@ -148,6 +149,7 @@
148149
import com.oracle.graal.python.util.PythonUtils;
149150
import com.oracle.truffle.api.CompilerAsserts;
150151
import com.oracle.truffle.api.CompilerDirectives;
152+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
151153
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
152154
import com.oracle.truffle.api.TruffleLogger;
153155
import com.oracle.truffle.api.dsl.Bind;
@@ -182,6 +184,9 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
182184
return CtypesModuleBuiltinsFactory.getFactories();
183185
}
184186

187+
@CompilationFinal private Object strlenFunction;
188+
@CompilationFinal private Object memcpyFunction;
189+
185190
private static final String NFI_LANGUAGE = "nfi";
186191

187192
protected static final int FUNCFLAG_STDCALL = 0x0;
@@ -224,17 +229,24 @@ public void postInitialize(Python3Core core) {
224229
ctypesModule.setAttribute("RTLD_GLOBAL", RTLD_GLOBAL.getValueIfDefined());
225230

226231
DLHandler handle = DlOpenNode.loadNFILibrary(core.getContext(), NFIBackend.NATIVE, "", rtldLocal);
227-
setCtypeNFIHelpers(core.getContext(), handle);
232+
setCtypeNFIHelpers(this, core.getContext(), handle);
228233
NativeFunction memmove = MemMoveFunction.create(handle, core.getContext());
229234
ctypesModule.setAttribute("_memmove_addr", factory.createNativeVoidPtr(memmove, memmove.adr));
230235
NativeFunction memset = MemSetFunction.create(handle, core.getContext());
231236
ctypesModule.setAttribute("_memset_addr", factory.createNativeVoidPtr(memset, memset.adr));
232237
}
233238

234-
private static void setCtypeNFIHelpers(PythonContext context, DLHandler h) {
235-
Object strlen = createNFIHelperFunction(context, h, "strlen", "(POINTER):UINT32");
236-
Object memcpy = createNFIHelperFunction(context, h, "memcpy", "([UINT8], POINTER, UINT32):POINTER");
237-
context.setCtypesNFIHelpers(strlen, memcpy);
239+
Object getStrlenFunction() {
240+
return strlenFunction;
241+
}
242+
243+
Object getMemcpyFunction() {
244+
return memcpyFunction;
245+
}
246+
247+
private static void setCtypeNFIHelpers(CtypesModuleBuiltins ctypesModuleBuiltins, PythonContext context, DLHandler h) {
248+
ctypesModuleBuiltins.strlenFunction = createNFIHelperFunction(context, h, "strlen", "(POINTER):UINT32");
249+
ctypesModuleBuiltins.memcpyFunction = createNFIHelperFunction(context, h, "memcpy", "([UINT8], POINTER, UINT32):POINTER");
238250
}
239251

240252
private static Object createNFIHelperFunction(PythonContext context, DLHandler h, String name, String signature) {
@@ -879,12 +891,12 @@ protected static Object getObjectAt(PythonContext context, Object ptr) {
879891
return ptr;
880892
}
881893

882-
@Builtin(name = "call_function", minNumOfPositionalArgs = 1)
894+
@Builtin(name = "call_function", minNumOfPositionalArgs = 1, declaresExplicitSelf = true)
883895
@GenerateNodeFactory
884-
protected abstract static class CallFunctionNode extends PythonBinaryBuiltinNode {
896+
protected abstract static class CallFunctionNode extends PythonTernaryBuiltinNode {
885897

886898
@Specialization
887-
Object call_function(VirtualFrame frame, Object f, PTuple arguments,
899+
Object call_function(VirtualFrame frame, PythonModule ctypesModule, Object f, PTuple arguments,
888900
@Cached AuditNode auditNode,
889901
@Cached CallProcNode callProcNode,
890902
@Cached GetInternalObjectArrayNode getArray,
@@ -902,7 +914,8 @@ Object call_function(VirtualFrame frame, Object f, PTuple arguments,
902914
null,
903915
ctypes,
904916
factory(),
905-
getContext());
917+
getContext(),
918+
(CtypesModuleBuiltins) ctypesModule.getBuiltins());
906919
}
907920
}
908921

@@ -928,12 +941,12 @@ Object error(VirtualFrame frame, Object o) {
928941
}
929942
}
930943

931-
@Builtin(name = "call_cdeclfunction", minNumOfPositionalArgs = 1)
944+
@Builtin(name = "call_cdeclfunction", minNumOfPositionalArgs = 1, declaresExplicitSelf = true)
932945
@GenerateNodeFactory
933-
protected abstract static class CallCdeclfunctionNode extends PythonBinaryBuiltinNode {
946+
protected abstract static class CallCdeclfunctionNode extends PythonTernaryBuiltinNode {
934947

935948
@Specialization
936-
Object doit(VirtualFrame frame, Object f, PTuple arguments,
949+
Object doit(VirtualFrame frame, PythonModule ctypesModule, Object f, PTuple arguments,
937950
@Cached AuditNode auditNode,
938951
@Cached GetInternalObjectArrayNode getArray,
939952
@Cached CallProcNode callProcNode,
@@ -951,7 +964,8 @@ Object doit(VirtualFrame frame, Object f, PTuple arguments,
951964
null,
952965
ctypes,
953966
factory(),
954-
getContext());
967+
getContext(),
968+
(CtypesModuleBuiltins) ctypesModule.getBuiltins());
955969
}
956970
}
957971

@@ -976,7 +990,8 @@ protected abstract static class CallProcNode extends PNodeWithRaise {
976990
abstract Object execute(VirtualFrame frame, NativeFunction pProc, Object[] argtuple, int flags, Object[] argtypes, Object[] converters, Object restype, Object checker,
977991
CtypesThreadState state,
978992
PythonObjectFactory factory,
979-
PythonContext context);
993+
PythonContext context,
994+
CtypesModuleBuiltins ctypesModuleBuiltins);
980995

981996
/*
982997
* bpo-13097: Max number of arguments _ctypes_callproc will accept.
@@ -997,6 +1012,7 @@ Object _ctypes_callproc(VirtualFrame frame,
9971012
@SuppressWarnings("unused") CtypesThreadState state,
9981013
PythonObjectFactory factory,
9991014
PythonContext context,
1015+
CtypesModuleBuiltins ctypesModuleBuiltins,
10001016
@Cached ConvParamNode convParamNode,
10011017
@Cached PyTypeStgDictNode pyTypeStgDictNode,
10021018
@Cached CallNode callNode,
@@ -1078,7 +1094,7 @@ Object _ctypes_callproc(VirtualFrame frame,
10781094
throw CompilerDirectives.shouldNotReachHere(e);
10791095
}
10801096
} else if (!isLLVM && ilib.isPointer(result)) {
1081-
result = getNativeBytes(getContext(), result, getRaiseNode());
1097+
result = getNativeBytes(ctypesModuleBuiltins, getContext(), result, getRaiseNode());
10821098
} else if (ilib.isNumber(result)) {
10831099
byte[] bytes = new byte[rtype.size];
10841100
CtypesNodes.setValue(rtype.type, bytes, 0, result);
@@ -1139,6 +1155,7 @@ Object doManaged(NativeFunction pProc,
11391155
@SuppressWarnings("unused") CtypesThreadState state,
11401156
@SuppressWarnings("unused") PythonObjectFactory factory,
11411157
@SuppressWarnings("unused") PythonContext context,
1158+
@SuppressWarnings("unused") CtypesModuleBuiltins ctypesModuleBuiltins,
11421159
@CachedLibrary(limit = "1") InteropLibrary ilib) {
11431160
return callManagedFunction(pProc, argarray, ilib);
11441161
}
@@ -1161,11 +1178,11 @@ protected static Object getFunction(NativeFunction pProc, String signature, Pyth
11611178
}
11621179

11631180
@TruffleBoundary
1164-
private static byte[] getNativeBytes(PythonContext context, Object pointer, PRaiseNode raiseNode) {
1181+
private static byte[] getNativeBytes(CtypesModuleBuiltins ctypesModuleBuiltins, PythonContext context, Object pointer, PRaiseNode raiseNode) {
11651182
try {
1166-
long size = (Long) InteropLibrary.getUncached().execute(context.getStrlenFunction(), pointer);
1183+
long size = (Long) InteropLibrary.getUncached().execute(ctypesModuleBuiltins.getStrlenFunction(), pointer);
11671184
byte[] bytes = new byte[(int) size];
1168-
InteropLibrary.getUncached().execute(context.getMemcpyFunction(), context.getEnv().asGuestValue(bytes), pointer, size);
1185+
InteropLibrary.getUncached().execute(ctypesModuleBuiltins.getMemcpyFunction(), context.getEnv().asGuestValue(bytes), pointer, size);
11691186
return bytes;
11701187
} catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
11711188
throw raiseNode.raise(SystemError, e);

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ Object PyCFuncPtr_call(VirtualFrame frame, PyCFuncPtrObject self, Object[] inarg
495495
}
496496
}
497497
CtypesThreadState state = CtypesThreadState.get(getContext(), PythonLanguage.get(this));
498+
CtypesModuleBuiltins ctypesModuleBuiltins = (CtypesModuleBuiltins) getContext().getCore().lookupBuiltinModule("_ctypes").getBuiltins();
498499
Object result = callProcNode.execute(frame, pProc,
499500
callargs,
500501
dict.flags,
@@ -504,7 +505,8 @@ Object PyCFuncPtr_call(VirtualFrame frame, PyCFuncPtrObject self, Object[] inarg
504505
checker,
505506
state,
506507
factory(),
507-
getContext());
508+
getContext(),
509+
ctypesModuleBuiltins);
508510
/* The 'errcheck' protocol */
509511
if (result != null && errcheck != null) {
510512
Object v = callNode.execute(frame, errcheck, result, self, callargs);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,6 @@ PythonThreadState getThreadState() {
418418

419419
// ctypes' used native libraries/functions.
420420
private final ConcurrentHashMap<Long, Object> ptrAdrMap = new ConcurrentHashMap<>();
421-
@CompilationFinal private Object strlenFunction; // ctypes NFI backend helper
422-
@CompilationFinal private Object memcpyFunction; // ctypes NFI backend helper
423421

424422
@CompilationFinal private PosixSupport posixSupport;
425423
@CompilationFinal private NFIZlibSupport nativeZlib;
@@ -969,20 +967,6 @@ public ConcurrentHashMap<Long, Object> getCtypesAdrMap() {
969967
return ptrAdrMap;
970968
}
971969

972-
public Object getStrlenFunction() {
973-
return strlenFunction;
974-
}
975-
976-
public Object getMemcpyFunction() {
977-
return memcpyFunction;
978-
}
979-
980-
public void setCtypesNFIHelpers(Object strlen, Object memcpy) {
981-
assert strlenFunction == null && memcpyFunction == null : "Ctypes NFI helper should only be set once";
982-
strlenFunction = strlen;
983-
memcpyFunction = memcpy;
984-
}
985-
986970
public TruffleLanguage.Env getEnv() {
987971
return env;
988972
}

0 commit comments

Comments
 (0)