Author: Armin Rigo <[email protected]>
Branch:
Changeset: r1620:b3b479ff6ebc
Date: 2015-01-07 18:38 +0100
http://bitbucket.org/cffi/cffi/changeset/b3b479ff6ebc/
Log: issue #172
Fix an inconsistency: the define "UNICODE" must be present
explicitly iff we're declaring TCHAR to be a wchar_t.
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -69,6 +69,7 @@
self._function_caches = []
self._libraries = []
self._cdefsources = []
+ self._windows_unicode = None
if hasattr(backend, 'set_ffi'):
backend.set_ffi(self)
for name in backend.__dict__:
@@ -347,6 +348,8 @@
which requires binary compatibility in the signatures.
"""
from .verifier import Verifier
+ if self._windows_unicode:
+ self._apply_windows_unicode(kwargs)
self.verifier = Verifier(self, source, tmpdir, **kwargs)
lib = self.verifier.load_library()
self._libraries.append(lib)
@@ -408,6 +411,43 @@
def from_handle(self, x):
return self._backend.from_handle(x)
+ def set_unicode(self, unicode_enabled):
+ """Windows: if 'unicode_enabled' is True, enable the UNICODE and
+ _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR
+ to be (pointers to) wchar_t. If 'unicode_enabled' is False,
+ declare these types to be (pointers to) plain 8-bit characters.
+ This is mostly for backward compatibility; you usually want True.
+ """
+ if self._windows_unicode is not None:
+ raise ValueError("set_unicode() can only be called once")
+ if unicode_enabled:
+ self.cdef("typedef wchar_t TBYTE;"
+ "typedef wchar_t TCHAR;"
+ "typedef const wchar_t *LPCTSTR;"
+ "typedef const wchar_t *PCTSTR;"
+ "typedef wchar_t *LPTSTR;"
+ "typedef wchar_t *PTSTR;"
+ "typedef TBYTE *PTBYTE;"
+ "typedef TCHAR *PTCHAR;")
+ else:
+ self.cdef("typedef char TBYTE;"
+ "typedef char TCHAR;"
+ "typedef const char *LPCTSTR;"
+ "typedef const char *PCTSTR;"
+ "typedef char *LPTSTR;"
+ "typedef char *PTSTR;"
+ "typedef TBYTE *PTBYTE;"
+ "typedef TCHAR *PTCHAR;")
+ self._windows_unicode = unicode_enabled
+
+ def _apply_windows_unicode(self, kwds):
+ defmacros = kwds.get('define_macros', ())
+ if not isinstance(defmacros, (list, tuple)):
+ raise TypeError("'define_macros' must be a list or tuple")
+ defmacros = list(defmacros) + [('UNICODE', '1'),
+ ('_UNICODE', '1')]
+ kwds['define_macros'] = defmacros
+
def _load_backend_lib(backend, name, flags):
if name is None:
diff --git a/cffi/commontypes.py b/cffi/commontypes.py
--- a/cffi/commontypes.py
+++ b/cffi/commontypes.py
@@ -86,8 +86,6 @@
"ULONGLONG": "unsigned long long",
"WCHAR": "wchar_t",
"SHORT": "short",
- "TBYTE": "WCHAR",
- "TCHAR": "WCHAR",
"UCHAR": "unsigned char",
"UINT": "unsigned int",
"UINT8": "unsigned char",
@@ -157,14 +155,12 @@
"LPCVOID": model.const_voidp_type,
"LPCWSTR": "const WCHAR *",
- "LPCTSTR": "LPCWSTR",
"LPDWORD": "DWORD *",
"LPHANDLE": "HANDLE *",
"LPINT": "int *",
"LPLONG": "long *",
"LPSTR": "CHAR *",
"LPWSTR": "WCHAR *",
- "LPTSTR": "LPWSTR",
"LPVOID": model.voidp_type,
"LPWORD": "WORD *",
"LRESULT": "LONG_PTR",
@@ -173,7 +169,6 @@
"PBYTE": "BYTE *",
"PCHAR": "CHAR *",
"PCSTR": "const CHAR *",
- "PCTSTR": "LPCWSTR",
"PCWSTR": "const WCHAR *",
"PDWORD": "DWORD *",
"PDWORDLONG": "DWORDLONG *",
@@ -200,9 +195,6 @@
"PSIZE_T": "SIZE_T *",
"PSSIZE_T": "SSIZE_T *",
"PSTR": "CHAR *",
- "PTBYTE": "TBYTE *",
- "PTCHAR": "TCHAR *",
- "PTSTR": "LPWSTR",
"PUCHAR": "UCHAR *",
"PUHALF_PTR": "UHALF_PTR *",
"PUINT": "UINT *",
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -2086,3 +2086,31 @@
assert str(e.value) == (
"ctype 'MyStr' not supported as argument or return value "
"(it is a struct with bit fields)")
+
+def test_verify_extra_arguments():
+ ffi = FFI()
+ ffi.cdef("#define ABA ...")
+ lib = ffi.verify("", define_macros=[('ABA', '42')])
+ assert lib.ABA == 42
+
+def test_implicit_unicode_on_windows():
+ if sys.platform != 'win32':
+ py.test.skip("win32-only test")
+ for with_unicode in [True, False]:
+ ffi = FFI()
+ ffi.set_unicode(with_unicode)
+ ffi.cdef("""
+ DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename,
+ DWORD nSize);
+ """)
+ lib = ffi.verify("""
+ #include <windows.h>
+ """, libraries=['Kernel32'])
+ outbuf = ffi.new("TCHAR[]", 200)
+ n = lib.GetModuleFileName(ffi.NULL, outbuf, 500)
+ assert 0 < n < 500
+ for i in range(n):
+ print repr(outbuf[i])
+ assert ord(outbuf[i]) != 0
+ assert ord(outbuf[n]) == 0
+ assert ord(outbuf[0]) < 128 # should be a letter, or '\'
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit