Author: Armin Rigo <[email protected]>
Branch:
Changeset: r781:09102559bc4c
Date: 2012-08-04 22:03 +0200
http://bitbucket.org/cffi/cffi/changeset/09102559bc4c/
Log: Test and fix.
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -585,7 +585,16 @@
ct->ct_name);
return NULL;
}
- else if (ct->ct_flags & (CT_ARRAY|CT_STRUCT|CT_UNION)) {
+ else if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
+ return new_simple_cdata(data, ct);
+ }
+ else if (ct->ct_flags & CT_ARRAY) {
+ if (ct->ct_length < 0) {
+ /* we can't return a <cdata 'int[]'> here, because we don't
+ know the length to give it. As a compromize, returns
+ <cdata 'int *'> in this case. */
+ ct = (CTypeDescrObject *)ct->ct_stuff;
+ }
return new_simple_cdata(data, ct);
}
}
diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -968,7 +968,10 @@
return funcobj
def read_variable(self, BType, name):
- ctypes_obj = BType._ctype.in_dll(self.cdll, name)
+ try:
+ ctypes_obj = BType._ctype.in_dll(self.cdll, name)
+ except AttributeError, e:
+ raise NotImplementedError(e)
return BType._from_ctypes(ctypes_obj)
def write_variable(self, BType, name, value):
diff --git a/cffi/vengine_gen.py b/cffi/vengine_gen.py
--- a/cffi/vengine_gen.py
+++ b/cffi/vengine_gen.py
@@ -396,6 +396,11 @@
# sense that "a=..." is forbidden
tp_ptr = model.PointerType(tp.item)
value = self._load_constant(False, tp_ptr, name, module)
+ # 'value' is a <cdata 'type *'> which we have to replace with
+ # a <cdata 'type[N]'> if the N is actually known
+ if tp.length is not None:
+ BArray = self.ffi._get_cached_btype(tp)
+ value = self.ffi.cast(BArray, value)
setattr(library, name, value)
return
# remove ptr=<cdata 'int *'> from the library instance, and replace
diff --git a/testing/test_ownlib.py b/testing/test_ownlib.py
--- a/testing/test_ownlib.py
+++ b/testing/test_ownlib.py
@@ -15,6 +15,8 @@
int test_setting_errno(void) {
return errno;
}
+
+int my_array[7] = {0, 1, 2, 3, 4, 5, 6};
"""
class TestOwnLib(object):
@@ -30,9 +32,11 @@
cwd=str(udir), shell=True)
cls.module = str(udir.join('testownlib.so'))
- def test_getting_errno(self):
+ def setup_method(self, meth):
if sys.platform == 'win32':
py.test.skip("fix the auto-generation of the tiny test lib")
+
+ def test_getting_errno(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("""
int test_getting_errno(void);
@@ -43,8 +47,6 @@
assert ffi.errno == 123
def test_setting_errno(self):
- if sys.platform == 'win32':
- py.test.skip("fix the auto-generation of the tiny test lib")
if self.Backend is CTypesBackend and '__pypy__' in sys.modules:
py.test.skip("XXX errno issue with ctypes on pypy?")
ffi = FFI(backend=self.Backend())
@@ -56,3 +58,39 @@
res = ownlib.test_setting_errno()
assert res == 42
assert ffi.errno == 42
+
+ def test_my_array_7(self):
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("""
+ int my_array[7];
+ """)
+ ownlib = ffi.dlopen(self.module)
+ for i in range(7):
+ assert ownlib.my_array[i] == i
+ assert len(ownlib.my_array) == 7
+ if self.Backend is CTypesBackend:
+ py.test.skip("not supported by the ctypes backend")
+ ownlib.my_array = range(10, 17)
+ for i in range(7):
+ assert ownlib.my_array[i] == 10 + i
+ ownlib.my_array = range(7)
+ for i in range(7):
+ assert ownlib.my_array[i] == i
+
+ def test_my_array_no_length(self):
+ if self.Backend is CTypesBackend:
+ py.test.skip("not supported by the ctypes backend")
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("""
+ int my_array[];
+ """)
+ ownlib = ffi.dlopen(self.module)
+ for i in range(7):
+ assert ownlib.my_array[i] == i
+ py.test.raises(TypeError, len, ownlib.my_array)
+ ownlib.my_array = range(10, 17)
+ for i in range(7):
+ assert ownlib.my_array[i] == 10 + i
+ ownlib.my_array = range(7)
+ for i in range(7):
+ assert ownlib.my_array[i] == i
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -426,16 +426,26 @@
assert lib.somenumber == 42
lib.somenumber = 2 # reset for the next run, if any
-def test_access_array_variable():
+def test_access_array_variable(length=5):
ffi = FFI()
ffi.cdef("int foo(int);\n"
- "int somenumber[5];")
+ "int somenumber[%s];" % (length,))
lib = ffi.verify("""
static int somenumber[] = {2, 2, 3, 4, 5};
static int foo(int i) {
return somenumber[i] * 7;
}
""")
+ if length == '':
+ # a global variable of an unknown array length is implicitly
+ # transformed into a global pointer variable, because we can only
+ # work with array instances whose length we know. using a pointer
+ # instead of an array gives the correct effects.
+ assert repr(lib.somenumber).startswith("<cdata 'int *' 0x")
+ py.test.raises(TypeError, len, lib.somenumber)
+ else:
+ assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length)
+ assert len(lib.somenumber) == 5
assert lib.somenumber[3] == 4
assert lib.foo(3) == 28
lib.somenumber[3] = -6
@@ -444,6 +454,9 @@
assert lib.somenumber[4] == 5
lib.somenumber[3] = 4 # reset for the next run, if any
+def test_access_array_variable_length_hidden():
+ test_access_array_variable(length='')
+
def test_access_struct_variable():
ffi = FFI()
ffi.cdef("struct foo { int x; ...; };\n"
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit