Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit