Skip to content

Commit 3a6b091

Browse files
committed
[GR-12550] Pass more ctypes tests
PullRequest: graalpython/1959
2 parents c168fa7 + e0aac13 commit 3a6b091

21 files changed

+1509
-683
lines changed

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
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
14+
*ctypes.test.test_as_parameter.AsParamPropertyWrapperTestCase.test_wchar_parm
1315
*ctypes.test.test_as_parameter.AsParamWrapperTestCase.test_recursive_as_param
16+
*ctypes.test.test_as_parameter.AsParamWrapperTestCase.test_wchar_parm
1417
*ctypes.test.test_as_parameter.BasicWrapTestCase.test_pointers
1518
*ctypes.test.test_as_parameter.BasicWrapTestCase.test_recursive_as_param
1619
*ctypes.test.test_as_parameter.BasicWrapTestCase.test_wchar_parm
@@ -21,7 +24,13 @@
2124
*ctypes.test.test_bitfields.BitFieldTest.test_mixed_4
2225
*ctypes.test.test_bitfields.BitFieldTest.test_nonint_types
2326
*ctypes.test.test_bitfields.BitFieldTest.test_single_bitfield_size
27+
*ctypes.test.test_bitfields.BitFieldTest.test_uint32
28+
*ctypes.test.test_buffers.StringBufferTestCase.test_buffer
29+
*ctypes.test.test_buffers.StringBufferTestCase.test_create_unicode_buffer_non_bmp
2430
*ctypes.test.test_bytes.BytesTest.test_BSTR
31+
*ctypes.test.test_bytes.BytesTest.test_c_char_p
32+
*ctypes.test.test_bytes.BytesTest.test_c_wchar_p
33+
*ctypes.test.test_bytes.BytesTest.test_struct
2534
*ctypes.test.test_bytes.BytesTest.test_struct_W
2635
*ctypes.test.test_byteswap.Test.test_X
2736
*ctypes.test.test_byteswap.Test.test_endian_other
@@ -49,7 +58,10 @@
4958
*ctypes.test.test_callbacks.StdcallCallbacks.test_unsupported_restype_1
5059
*ctypes.test.test_callbacks.StdcallCallbacks.test_unsupported_restype_2
5160
*ctypes.test.test_callbacks.StdcallCallbacks.test_ushort
61+
*ctypes.test.test_cast.Test.test_array2pointer
5262
*ctypes.test.test_cast.Test.test_bad_type_arg
63+
*ctypes.test.test_cast.Test.test_other
64+
*ctypes.test.test_cast.Test.test_wchar_p
5365
*ctypes.test.test_cfuncs.stdcallCFunctions.test_byte
5466
*ctypes.test.test_cfuncs.stdcallCFunctions.test_byte_plus
5567
*ctypes.test.test_cfuncs.stdcallCFunctions.test_callwithresult
@@ -89,22 +101,30 @@
89101
*ctypes.test.test_find.Test_OpenGL_libs.test_shell_injection
90102
*ctypes.test.test_frombuffer.Test.test_abstract
91103
*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
92106
*ctypes.test.test_frombuffer.Test.test_from_buffer_memoryview
107+
*ctypes.test.test_funcptr.CFuncPtrTestCase.test_abstract
93108
*ctypes.test.test_functions.FunctionTestCase.test_doubleresult
94109
*ctypes.test.test_functions.FunctionTestCase.test_errors
110+
*ctypes.test.test_functions.FunctionTestCase.test_floatresult
95111
*ctypes.test.test_functions.FunctionTestCase.test_longlongresult
96112
*ctypes.test.test_functions.FunctionTestCase.test_mro
97113
*ctypes.test.test_functions.FunctionTestCase.test_stringresult
98114
*ctypes.test.test_functions.FunctionTestCase.test_struct_return_2H_stdcall
99115
*ctypes.test.test_functions.FunctionTestCase.test_struct_return_8H_stdcall
100116
*ctypes.test.test_functions.FunctionTestCase.test_wchar_parm
117+
*ctypes.test.test_functions.FunctionTestCase.test_wchar_result
101118
*ctypes.test.test_internals.ObjectsTestCase.test_embedded_structs
102119
*ctypes.test.test_internals.ObjectsTestCase.test_ptr_struct
103120
*ctypes.test.test_internals.ObjectsTestCase.test_simple_struct
121+
*ctypes.test.test_internals.ObjectsTestCase.test_xxx
104122
*ctypes.test.test_keeprefs.ArrayTestCase.test_cint_array
105123
*ctypes.test.test_keeprefs.DeletePointerTestCase.test_X
106124
*ctypes.test.test_keeprefs.PointerTestCase.test_p_cint
125+
*ctypes.test.test_keeprefs.SimpleTestCase.test_ccharp
107126
*ctypes.test.test_keeprefs.SimpleTestCase.test_cint
127+
*ctypes.test.test_keeprefs.StructureTestCase.test_ccharp_struct
108128
*ctypes.test.test_keeprefs.StructureTestCase.test_cint_struct
109129
*ctypes.test.test_keeprefs.StructureTestCase.test_struct_struct
110130
*ctypes.test.test_libc.LibTest.test_sqrt
@@ -125,10 +145,14 @@
125145
*ctypes.test.test_numbers.NumberTestCase.test_bool_from_address
126146
*ctypes.test.test_numbers.NumberTestCase.test_bool_values
127147
*ctypes.test.test_numbers.NumberTestCase.test_byref
148+
*ctypes.test.test_numbers.NumberTestCase.test_default_init
128149
*ctypes.test.test_numbers.NumberTestCase.test_float_overflow
150+
*ctypes.test.test_numbers.NumberTestCase.test_floats
129151
*ctypes.test.test_numbers.NumberTestCase.test_from_param
130152
*ctypes.test.test_numbers.NumberTestCase.test_init
153+
*ctypes.test.test_numbers.NumberTestCase.test_integers
131154
*ctypes.test.test_numbers.NumberTestCase.test_perf
155+
*ctypes.test.test_numbers.NumberTestCase.test_signed_values
132156
*ctypes.test.test_numbers.NumberTestCase.test_sizes
133157
*ctypes.test.test_numbers.NumberTestCase.test_typeerror
134158
*ctypes.test.test_numbers.NumberTestCase.test_valid_ranges
@@ -138,9 +162,12 @@
138162
*ctypes.test.test_parameters.SimpleTypesTestCase.test_subclasses
139163
*ctypes.test.test_parameters.SimpleTypesTestCase.test_subclasses_c_wchar_p
140164
*ctypes.test.test_pointers.PointersTestCase.test_abstract
165+
*ctypes.test.test_pointers.PointersTestCase.test_basic
141166
*ctypes.test.test_pointers.PointersTestCase.test_basics
142167
*ctypes.test.test_pointers.PointersTestCase.test_from_address
143168
*ctypes.test.test_pointers.PointersTestCase.test_pointer_crash
169+
*ctypes.test.test_prototypes.CharPointersTestCase.test_c_void_p_arg_with_c_wchar_p
170+
*ctypes.test.test_prototypes.WCharPointersTestCase.test_c_wchar_p_arg
144171
*ctypes.test.test_python_api.PythonAPITestCase.test_PyLong_Long
145172
*ctypes.test.test_python_api.PythonAPITestCase.test_PyObj_FromPtr
146173
*ctypes.test.test_python_api.PythonAPITestCase.test_PyString_FromString
@@ -154,6 +181,8 @@
154181
*ctypes.test.test_sizes.SizesTestCase.test_size_t
155182
*ctypes.test.test_sizes.SizesTestCase.test_ssize_t
156183
*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
157186
*ctypes.test.test_stringptr.StringPtrTestCase.test__POINTER_c_char
158187
*ctypes.test.test_strings.StringArrayTestCase.test_c_buffer_raw
159188
*ctypes.test.test_strings.StringArrayTestCase.test_c_buffer_value
@@ -173,16 +202,20 @@
173202
*ctypes.test.test_struct_fields.StructFieldsTestCase.test_2
174203
*ctypes.test.test_struct_fields.StructFieldsTestCase.test_3
175204
*ctypes.test.test_struct_fields.StructFieldsTestCase.test_4
205+
*ctypes.test.test_structures.StructureTestCase.test_38368
176206
*ctypes.test.test_structures.StructureTestCase.test_abstract_class
177207
*ctypes.test.test_structures.StructureTestCase.test_bitfield_by_value
178208
*ctypes.test.test_structures.StructureTestCase.test_conflicting_initializers
179209
*ctypes.test.test_structures.StructureTestCase.test_empty
180210
*ctypes.test.test_structures.StructureTestCase.test_huge_field_name
211+
*ctypes.test.test_structures.StructureTestCase.test_initializers
181212
*ctypes.test.test_structures.StructureTestCase.test_invalid_field_types
182213
*ctypes.test.test_structures.StructureTestCase.test_invalid_name
214+
*ctypes.test.test_structures.StructureTestCase.test_keyword_initializers
183215
*ctypes.test.test_structures.StructureTestCase.test_methods
184216
*ctypes.test.test_structures.StructureTestCase.test_packed_c_limits
185217
*ctypes.test.test_structures.StructureTestCase.test_struct_alignment
218+
*ctypes.test.test_structures.StructureTestCase.test_structures_with_wchar
186219
*ctypes.test.test_structures.StructureTestCase.test_subclass_creation
187220
*ctypes.test.test_structures.StructureTestCase.test_union_by_value
188221
*ctypes.test.test_structures.StructureTestCase.test_unions

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,14 @@ Object reduce(VirtualFrame frame, CDataObject self,
166166
int offset = self.b_ptr.offset;
167167
t1[1] = factory().createBytes(PythonUtils.arrayCopyOfRange(byteArrayStorage.value, offset, len), self.b_size);
168168
} else {
169-
throw raise(NotImplementedError);
169+
throw raise(NotImplementedError, "Storage is not covered yet.");
170170
}
171171
Object clazz = getClassNode.execute(self);
172172
Object[] t2 = new Object[]{clazz, factory().createTuple(t1)};
173173
PythonModule ctypes = getContext().getCore().lookupBuiltinModule("_ctypes");
174174
Object unpickle = dylib.getOrDefault(ctypes.getStorage(), UNPICKLE, null);
175175
if (unpickle == null) {
176-
throw raise(NotImplementedError);
176+
throw raise(NotImplementedError, "unpickle isn't supported yet.");
177177
}
178178
Object[] t3 = new Object[]{unpickle, factory().createTuple(t2)};
179179
return factory().createTuple(t3); // "O(O(NN))"
@@ -219,7 +219,7 @@ Object PyCData_setstate(VirtualFrame frame, CDataObject self, PTuple args,
219219

220220
@SuppressWarnings("unused")
221221
private void memmove(Object dest, Object src, int len) {
222-
throw raise(NotImplementedError); // TODO
222+
throw raise(NotImplementedError, "memmove is partially supported."); // TODO
223223
}
224224
}
225225
}

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

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,22 @@
4040
*/
4141
package com.oracle.graal.python.builtins.modules.ctypes;
4242

43+
import com.oracle.graal.python.builtins.modules.ctypes.CtypesNodes.DeRefHandleNode;
4344
import com.oracle.graal.python.builtins.modules.ctypes.PtrValue.ByteArrayStorage;
4445
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
4546
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
47+
import com.oracle.graal.python.builtins.objects.str.PString;
4648
import com.oracle.graal.python.util.PythonUtils;
49+
import com.oracle.truffle.api.dsl.Cached;
50+
import com.oracle.truffle.api.interop.InteropLibrary;
51+
import com.oracle.truffle.api.interop.TruffleObject;
52+
import com.oracle.truffle.api.interop.UnknownIdentifierException;
53+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
54+
import com.oracle.truffle.api.library.CachedLibrary;
4755
import com.oracle.truffle.api.library.ExportLibrary;
4856
import com.oracle.truffle.api.library.ExportMessage;
4957
import com.oracle.truffle.api.object.Shape;
58+
import com.oracle.truffle.llvm.spi.NativeTypeLibrary;
5059

5160
@ExportLibrary(PythonObjectLibrary.class)
5261
public class CDataObject extends PythonBuiltinObject {
@@ -79,6 +88,10 @@ public CDataObject(Object cls, Shape instanceShape) {
7988
this.b_ptr = new PtrValue();
8089
}
8190

91+
protected static CDataObjectWrapper createWrapper(StgDictObject dictObject, byte[] storage) {
92+
return new CDataObjectWrapper(dictObject, storage);
93+
}
94+
8295
@ExportMessage
8396
@SuppressWarnings("static-method")
8497
boolean isBuffer() {
@@ -134,4 +147,109 @@ static int PyCData_NewGetBuffer(Object myself, Py_buffer *view, int flags)
134147
NULL,
135148
};
136149
*/
150+
151+
@SuppressWarnings("static-method")
152+
@ExportLibrary(InteropLibrary.class)
153+
@ExportLibrary(value = NativeTypeLibrary.class, useForAOT = false)
154+
public static class CDataObjectWrapper implements TruffleObject {
155+
156+
final byte[] storage;
157+
final StgDictObject stgDict;
158+
159+
Object nativePointer;
160+
161+
public CDataObjectWrapper(StgDictObject stgDict, byte[] storage) {
162+
this.storage = storage;
163+
assert stgDict != null;
164+
this.stgDict = stgDict;
165+
this.nativePointer = null;
166+
}
167+
168+
private int getIndex(String field) {
169+
for (int i = 0; i < this.stgDict.fieldsNames.length; i++) {
170+
if (PString.equals(this.stgDict.fieldsNames[i], field)) {
171+
return i;
172+
}
173+
}
174+
return -1;
175+
}
176+
177+
@ExportMessage
178+
boolean hasMembers() {
179+
return this.stgDict.fieldsNames.length > 0;
180+
}
181+
182+
@ExportMessage
183+
String[] getMembers(@SuppressWarnings("unused") boolean includeInternal) {
184+
return this.stgDict.fieldsNames;
185+
}
186+
187+
@ExportMessage
188+
boolean isMemberReadable(String member) {
189+
return getIndex(member) != -1;
190+
}
191+
192+
@ExportMessage
193+
final boolean isMemberModifiable(String member) {
194+
return isMemberReadable(member);
195+
}
196+
197+
@ExportMessage
198+
final boolean isMemberInsertable(@SuppressWarnings("unused") String member) {
199+
return false;
200+
}
201+
202+
@ExportMessage
203+
Object readMember(String member) throws UnknownIdentifierException {
204+
int idx = getIndex(member);
205+
if (idx != -1) {
206+
return CtypesNodes.getValue(stgDict.fieldsTypes[idx], storage, stgDict.fieldsOffsets[idx]);
207+
}
208+
throw UnknownIdentifierException.create(member);
209+
}
210+
211+
@ExportMessage
212+
void writeMember(String member, Object value) throws UnknownIdentifierException {
213+
int idx = getIndex(member);
214+
if (idx != -1) {
215+
CtypesNodes.setValue(stgDict.fieldsTypes[idx], storage, stgDict.fieldsOffsets[idx], value);
216+
return;
217+
}
218+
throw UnknownIdentifierException.create(member);
219+
}
220+
221+
@ExportMessage
222+
boolean isPointer() {
223+
return nativePointer != null;
224+
}
225+
226+
@ExportMessage
227+
long asPointer(
228+
@CachedLibrary(limit = "1") InteropLibrary lib) throws UnsupportedMessageException {
229+
return lib.asPointer(nativePointer);
230+
}
231+
232+
@ExportMessage
233+
void toNative(
234+
@Cached DeRefHandleNode deRefHandleNode) {
235+
if (nativePointer == null) {
236+
nativePointer = deRefHandleNode.execute(this);
237+
}
238+
}
239+
240+
@ExportMessage
241+
@SuppressWarnings("static-method")
242+
boolean hasNativeType() {
243+
// TODO implement native type
244+
return false;
245+
}
246+
247+
@ExportMessage
248+
@SuppressWarnings("static-method")
249+
Object getNativeType() {
250+
// TODO implement native type
251+
return null;
252+
}
253+
}
254+
137255
}

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ Object CDataType_from_buffer_copy(Object type, byte[] bytes, int offset,
288288
CDataObject result = factory().createCDataObject(type);
289289
GenericPyCDataNew(dict, result);
290290
// memcpy(result.b_ptr, buffer.buf + offset, dict.size);
291-
result.b_ptr = PtrValue.bytes(PythonUtils.arrayCopyOfRange(bytes, offset, dict.size));
291+
result.b_ptr = PtrValue.bytes(dict.ffi_type_pointer, PythonUtils.arrayCopyOfRange(bytes, offset, dict.size + offset));
292292
return result;
293293
}
294294
}
@@ -342,7 +342,7 @@ CDataObject PyCData_AtAddress_bytes(Object type, byte[] buf, int offset, PythonO
342342

343343
CDataObject pd = factory.createCDataObject(type);
344344
assert pyTypeCheck.isCDataObject(pd);
345-
pd.b_ptr = PtrValue.bytes(buf);
345+
pd.b_ptr = PtrValue.bytes(stgdict.ffi_type_pointer, buf);
346346
pd.b_ptr.offset = offset;
347347
pd.b_length = stgdict.length;
348348
pd.b_size = stgdict.size;
@@ -368,7 +368,8 @@ CDataObject PyCData_AtAddress(Object type, Object obj, @SuppressWarnings("unused
368368
if (obj instanceof PMemoryView) {
369369
pd.b_ptr = PtrValue.memoryView((PMemoryView) obj);
370370
} else {
371-
throw raise(NotImplementedError); // TODO get Objects from numeric pointers.
371+
// TODO get Objects from numeric pointers.
372+
throw raise(NotImplementedError, "Storage is not implemented.");
372373
}
373374
pd.b_length = stgdict.length;
374375
pd.b_size = stgdict.size;
@@ -409,7 +410,7 @@ Object WithoutFunc(Object type,
409410
if (dict != null && dict.getfunc != FieldGet.nil && !pyTypeCheck.ctypesSimpleInstance(type, getBaseClassNode, isSameTypeNode)) {
410411
return getFuncNode.execute(dict.getfunc, adr, size, factory);
411412
}
412-
return PyCData_FromBaseObj(type, src, index, adr, pyTypeCheck, factory, getRaiseNode(), pyTypeStgDictNode);
413+
return PyCData_FromBaseObj(type, src, index, adr, factory, getRaiseNode(), pyTypeStgDictNode);
413414
}
414415
}
415416

@@ -488,7 +489,7 @@ Object PyCDataSetInternal(VirtualFrame frame, Object type, FieldSet setfunc, Obj
488489
pyObjectStgDictNode,
489490
getName);
490491
} else if (value instanceof PNone && pyTypeCheck.isPyCPointerTypeObject(type)) {
491-
// *(void **)ptr = NULL;
492+
ptr.toNil(); // *(void **)ptr = NULL;
492493
return PNone.NONE;
493494
} else {
494495
throw raise(TypeError, EXPECTED_S_INSTANCE_GOT_S, getName.execute(type), getName.execute(value));
@@ -613,7 +614,7 @@ static String unique_key(CDataObject cdata, int index,
613614
}
614615

615616
static void PyCData_MallocBuffer(CDataObject obj, StgDictObject dict) {
616-
obj.b_ptr = PtrValue.bytes(dict.size);
617+
obj.b_ptr = PtrValue.allocate(dict.ffi_type_pointer, dict.size);
617618
/*- XXX: (mq) This might not be necessary in our end but will keep it until we fully support ctypes.
618619
if (dict.size <= sizeof(obj.b_value)) {
619620
/* No need to call malloc, can use the default buffer * /
@@ -639,25 +640,22 @@ static void PyCData_MallocBuffer(CDataObject obj, StgDictObject dict) {
639640
}
640641

641642
static CDataObject PyCData_FromBaseObj(Object type, Object base, int index, PtrValue adr,
642-
PyTypeCheck pyTypeCheck,
643643
PythonObjectFactory factory,
644644
PRaiseNode raiseNode,
645645
PyTypeStgDictNode pyTypeStgDictNode) {
646646
// assert(PyType_Check(type));
647647
StgDictObject dict = pyTypeStgDictNode.checkAbstractClass(type, raiseNode);
648648
dict.flags |= DICTFLAG_FINAL;
649649
CDataObject cmem = factory.createCDataObject(type);
650-
assert pyTypeCheck.isCDataObject(cmem);
651650

652651
cmem.b_length = dict.length;
653652
cmem.b_size = dict.size;
654653
if (base != null) { /* use base's buffer */
655-
assert pyTypeCheck.isCDataObject(base);
656654
cmem.b_ptr = adr;
657655
cmem.b_needsfree = 0;
658656
cmem.b_base = (CDataObject) base;
659657
} else { /* copy contents of adr */
660-
// PyCData_MallocBuffer(cmem, dict); TODO
658+
PyCData_MallocBuffer(cmem, dict);
661659
// memcpy(cmem.b_ptr, adr, dict.size); TODO
662660
cmem.b_ptr = adr;
663661
}

0 commit comments

Comments
 (0)