Skip to content

Commit 120de27

Browse files
committed
pass more ctypes tests
1 parent a70a4e7 commit 120de27

21 files changed

+1456
-672
lines changed

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
*ctypes.test.test_arrays.ArrayTestCase.test_subclass
1111
*ctypes.test.test_arrays.ArrayTestCase.test_zero_length
1212
*ctypes.test.test_as_parameter.AsParamPropertyWrapperTestCase.test_recursive_as_param
13+
*ctypes.test.test_as_parameter.AsParamPropertyWrapperTestCase.test_wchar_parm
1314
*ctypes.test.test_as_parameter.AsParamWrapperTestCase.test_recursive_as_param
15+
*ctypes.test.test_as_parameter.AsParamWrapperTestCase.test_wchar_parm
1416
*ctypes.test.test_as_parameter.BasicWrapTestCase.test_pointers
1517
*ctypes.test.test_as_parameter.BasicWrapTestCase.test_recursive_as_param
1618
*ctypes.test.test_as_parameter.BasicWrapTestCase.test_wchar_parm
@@ -21,7 +23,12 @@
2123
*ctypes.test.test_bitfields.BitFieldTest.test_mixed_4
2224
*ctypes.test.test_bitfields.BitFieldTest.test_nonint_types
2325
*ctypes.test.test_bitfields.BitFieldTest.test_single_bitfield_size
26+
*ctypes.test.test_bitfields.BitFieldTest.test_uint32
27+
*ctypes.test.test_buffers.StringBufferTestCase.test_buffer
2428
*ctypes.test.test_bytes.BytesTest.test_BSTR
29+
*ctypes.test.test_bytes.BytesTest.test_c_char_p
30+
*ctypes.test.test_bytes.BytesTest.test_c_wchar_p
31+
*ctypes.test.test_bytes.BytesTest.test_struct
2532
*ctypes.test.test_bytes.BytesTest.test_struct_W
2633
*ctypes.test.test_byteswap.Test.test_X
2734
*ctypes.test.test_byteswap.Test.test_endian_other
@@ -50,6 +57,7 @@
5057
*ctypes.test.test_callbacks.StdcallCallbacks.test_unsupported_restype_2
5158
*ctypes.test.test_callbacks.StdcallCallbacks.test_ushort
5259
*ctypes.test.test_cast.Test.test_bad_type_arg
60+
*ctypes.test.test_cast.Test.test_wchar_p
5361
*ctypes.test.test_cfuncs.stdcallCFunctions.test_byte
5462
*ctypes.test.test_cfuncs.stdcallCFunctions.test_byte_plus
5563
*ctypes.test.test_cfuncs.stdcallCFunctions.test_callwithresult
@@ -90,8 +98,10 @@
9098
*ctypes.test.test_frombuffer.Test.test_abstract
9199
*ctypes.test.test_frombuffer.Test.test_fortran_contiguous
92100
*ctypes.test.test_frombuffer.Test.test_from_buffer_memoryview
101+
*ctypes.test.test_funcptr.CFuncPtrTestCase.test_abstract
93102
*ctypes.test.test_functions.FunctionTestCase.test_doubleresult
94103
*ctypes.test.test_functions.FunctionTestCase.test_errors
104+
*ctypes.test.test_functions.FunctionTestCase.test_floatresult
95105
*ctypes.test.test_functions.FunctionTestCase.test_longlongresult
96106
*ctypes.test.test_functions.FunctionTestCase.test_mro
97107
*ctypes.test.test_functions.FunctionTestCase.test_stringresult
@@ -101,10 +111,13 @@
101111
*ctypes.test.test_internals.ObjectsTestCase.test_embedded_structs
102112
*ctypes.test.test_internals.ObjectsTestCase.test_ptr_struct
103113
*ctypes.test.test_internals.ObjectsTestCase.test_simple_struct
114+
*ctypes.test.test_internals.ObjectsTestCase.test_xxx
104115
*ctypes.test.test_keeprefs.ArrayTestCase.test_cint_array
105116
*ctypes.test.test_keeprefs.DeletePointerTestCase.test_X
106117
*ctypes.test.test_keeprefs.PointerTestCase.test_p_cint
118+
*ctypes.test.test_keeprefs.SimpleTestCase.test_ccharp
107119
*ctypes.test.test_keeprefs.SimpleTestCase.test_cint
120+
*ctypes.test.test_keeprefs.StructureTestCase.test_ccharp_struct
108121
*ctypes.test.test_keeprefs.StructureTestCase.test_cint_struct
109122
*ctypes.test.test_keeprefs.StructureTestCase.test_struct_struct
110123
*ctypes.test.test_libc.LibTest.test_sqrt
@@ -125,10 +138,14 @@
125138
*ctypes.test.test_numbers.NumberTestCase.test_bool_from_address
126139
*ctypes.test.test_numbers.NumberTestCase.test_bool_values
127140
*ctypes.test.test_numbers.NumberTestCase.test_byref
141+
*ctypes.test.test_numbers.NumberTestCase.test_default_init
128142
*ctypes.test.test_numbers.NumberTestCase.test_float_overflow
143+
*ctypes.test.test_numbers.NumberTestCase.test_floats
129144
*ctypes.test.test_numbers.NumberTestCase.test_from_param
130145
*ctypes.test.test_numbers.NumberTestCase.test_init
146+
*ctypes.test.test_numbers.NumberTestCase.test_integers
131147
*ctypes.test.test_numbers.NumberTestCase.test_perf
148+
*ctypes.test.test_numbers.NumberTestCase.test_signed_values
132149
*ctypes.test.test_numbers.NumberTestCase.test_sizes
133150
*ctypes.test.test_numbers.NumberTestCase.test_typeerror
134151
*ctypes.test.test_numbers.NumberTestCase.test_valid_ranges
@@ -138,9 +155,12 @@
138155
*ctypes.test.test_parameters.SimpleTypesTestCase.test_subclasses
139156
*ctypes.test.test_parameters.SimpleTypesTestCase.test_subclasses_c_wchar_p
140157
*ctypes.test.test_pointers.PointersTestCase.test_abstract
158+
*ctypes.test.test_pointers.PointersTestCase.test_basic
141159
*ctypes.test.test_pointers.PointersTestCase.test_basics
142160
*ctypes.test.test_pointers.PointersTestCase.test_from_address
143161
*ctypes.test.test_pointers.PointersTestCase.test_pointer_crash
162+
*ctypes.test.test_prototypes.CharPointersTestCase.test_c_void_p_arg_with_c_wchar_p
163+
*ctypes.test.test_prototypes.WCharPointersTestCase.test_c_wchar_p_arg
144164
*ctypes.test.test_python_api.PythonAPITestCase.test_PyLong_Long
145165
*ctypes.test.test_python_api.PythonAPITestCase.test_PyObj_FromPtr
146166
*ctypes.test.test_python_api.PythonAPITestCase.test_PyString_FromString
@@ -178,11 +198,13 @@
178198
*ctypes.test.test_structures.StructureTestCase.test_conflicting_initializers
179199
*ctypes.test.test_structures.StructureTestCase.test_empty
180200
*ctypes.test.test_structures.StructureTestCase.test_huge_field_name
201+
*ctypes.test.test_structures.StructureTestCase.test_initializers
181202
*ctypes.test.test_structures.StructureTestCase.test_invalid_field_types
182203
*ctypes.test.test_structures.StructureTestCase.test_invalid_name
183204
*ctypes.test.test_structures.StructureTestCase.test_methods
184205
*ctypes.test.test_structures.StructureTestCase.test_packed_c_limits
185206
*ctypes.test.test_structures.StructureTestCase.test_struct_alignment
207+
*ctypes.test.test_structures.StructureTestCase.test_structures_with_wchar
186208
*ctypes.test.test_structures.StructureTestCase.test_subclass_creation
187209
*ctypes.test.test_structures.StructureTestCase.test_union_by_value
188210
*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)