Author: Armin Rigo <[email protected]>
Branch: cffi-stdcall
Changeset: r80012:348cafc5db08
Date: 2015-10-07 09:59 +0200
http://bitbucket.org/pypy/pypy/changeset/348cafc5db08/
Log: Port the rest of the win32-stdcall branch
diff --git a/pypy/module/_cffi_backend/realize_c_type.py
b/pypy/module/_cffi_backend/realize_c_type.py
--- a/pypy/module/_cffi_backend/realize_c_type.py
+++ b/pypy/module/_cffi_backend/realize_c_type.py
@@ -5,6 +5,7 @@
from rpython.rtyper.lltypesystem import lltype, rffi
from pypy.interpreter.error import oefmt
from pypy.interpreter.baseobjspace import W_Root
+from pypy.module import _cffi_backend
from pypy.module._cffi_backend.ctypeobj import W_CType
from pypy.module._cffi_backend import cffi_opcode, newtype, ctypestruct
from pypy.module._cffi_backend import parse_c_type
@@ -164,16 +165,28 @@
OP_FUNCTION_END = cffi_opcode.OP_FUNCTION_END
while getop(opcodes[base_index + num_args]) != OP_FUNCTION_END:
num_args += 1
- ellipsis = (getarg(opcodes[base_index + num_args]) & 1) != 0
+ #
+ ellipsis = (getarg(opcodes[base_index + num_args]) & 0x01) != 0
+ abi = (getarg(opcodes[base_index + num_args]) & 0xFE)
+ if abi == 0:
+ abi = _cffi_backend.FFI_DEFAULT_ABI
+ elif abi == 2:
+ if _cffi_backend.has_stdcall:
+ abi = _cffi_backend.FFI_STDCALL
+ else:
+ abi = _cffi_backend.FFI_DEFAULT_ABI
+ else:
+ raise oefmt(ffi.w_FFIError, "abi number %d not supported", abi)
+ #
fargs = [realize_c_type(ffi, opcodes, base_index + i)
for i in range(num_args)]
- return fargs, fret, ellipsis
+ return fargs, fret, ellipsis, abi
def unwrap_as_fnptr(self, ffi):
if self._ctfuncptr is None:
- fargs, fret, ellipsis = self._unpack(ffi)
+ fargs, fret, ellipsis, abi = self._unpack(ffi)
self._ctfuncptr = newtype._new_function_type(
- ffi.space, fargs, fret, ellipsis)
+ ffi.space, fargs, fret, ellipsis, abi)
return self._ctfuncptr
def unwrap_as_fnptr_in_elidable(self):
@@ -190,7 +203,7 @@
# type ptr-to-struct. This is how recompiler.py produces
# trampoline functions for PyPy.
if self.nostruct_ctype is None:
- fargs, fret, ellipsis = self._unpack(ffi)
+ fargs, fret, ellipsis, abi = self._unpack(ffi)
# 'locs' will be a string of the same length as the final fargs,
# containing 'A' where a struct argument was detected, and 'R'
# in first position if a struct return value was detected
@@ -207,7 +220,7 @@
locs = ['R'] + locs
fret = newtype.new_void_type(ffi.space)
ctfuncptr = newtype._new_function_type(
- ffi.space, fargs, fret, ellipsis)
+ ffi.space, fargs, fret, ellipsis, abi)
if locs == ['\x00'] * len(locs):
locs = None
else:
@@ -218,7 +231,7 @@
locs[0] == 'R')
def unexpected_fn_type(self, ffi):
- fargs, fret, ellipsis = self._unpack(ffi)
+ fargs, fret, ellipsis, abi = self._unpack(ffi)
argnames = [farg.name for farg in fargs]
if ellipsis:
argnames.append('...')
diff --git a/pypy/module/_cffi_backend/src/parse_c_type.c
b/pypy/module/_cffi_backend/src/parse_c_type.c
--- a/pypy/module/_cffi_backend/src/parse_c_type.c
+++ b/pypy/module/_cffi_backend/src/parse_c_type.c
@@ -51,6 +51,9 @@
TOK_UNSIGNED,
TOK_VOID,
TOK_VOLATILE,
+
+ TOK_CDECL,
+ TOK_STDCALL,
};
typedef struct {
@@ -165,6 +168,8 @@
switch (*p) {
case '_':
if (tok->size == 5 && !memcmp(p, "_Bool", 5)) tok->kind = TOK__BOOL;
+ if (tok->size == 7 && !memcmp(p,"__cdecl",7)) tok->kind = TOK_CDECL;
+ if (tok->size == 9 && !memcmp(p,"__stdcall",9))tok->kind = TOK_STDCALL;
break;
case 'c':
if (tok->size == 4 && !memcmp(p, "char", 4)) tok->kind = TOK_CHAR;
@@ -236,7 +241,7 @@
type). The 'outer' argument is the index of the opcode outside
this "sequel".
*/
- int check_for_grouping;
+ int check_for_grouping, abi=0;
_cffi_opcode_t result, *p_current;
header:
@@ -253,6 +258,12 @@
/* ignored for now */
next_token(tok);
goto header;
+ case TOK_CDECL:
+ case TOK_STDCALL:
+ /* must be in a function; checked below */
+ abi = tok->kind;
+ next_token(tok);
+ goto header;
default:
break;
}
@@ -269,6 +280,11 @@
while (tok->kind == TOK_OPEN_PAREN) {
next_token(tok);
+ if (tok->kind == TOK_CDECL || tok->kind == TOK_STDCALL) {
+ abi = tok->kind;
+ next_token(tok);
+ }
+
if ((check_for_grouping--) == 1 && (tok->kind == TOK_STAR ||
tok->kind == TOK_CONST ||
tok->kind == TOK_VOLATILE ||
@@ -286,7 +302,14 @@
}
else {
/* function type */
- int arg_total, base_index, arg_next, has_ellipsis=0;
+ int arg_total, base_index, arg_next, flags=0;
+
+ if (abi == TOK_STDCALL) {
+ flags = 2;
+ /* note that an ellipsis below will overwrite this flags,
+ which is the goal: variadic functions are always cdecl */
+ }
+ abi = 0;
if (tok->kind == TOK_VOID && get_following_char(tok) == ')') {
next_token(tok);
@@ -315,7 +338,7 @@
_cffi_opcode_t oarg;
if (tok->kind == TOK_DOTDOTDOT) {
- has_ellipsis = 1;
+ flags = 1; /* ellipsis */
next_token(tok);
break;
}
@@ -339,8 +362,7 @@
next_token(tok);
}
}
- tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END,
- has_ellipsis);
+ tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END, flags);
}
if (tok->kind != TOK_CLOSE_PAREN)
@@ -348,6 +370,9 @@
next_token(tok);
}
+ if (abi != 0)
+ return parse_error(tok, "expected '('");
+
while (tok->kind == TOK_OPEN_BRACKET) {
*p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index);
p_current = tok->output + tok->output_index;
diff --git a/pypy/module/_cffi_backend/test/test_parse_c_type.py
b/pypy/module/_cffi_backend/test/test_parse_c_type.py
--- a/pypy/module/_cffi_backend/test/test_parse_c_type.py
+++ b/pypy/module/_cffi_backend/test/test_parse_c_type.py
@@ -338,3 +338,17 @@
# not supported (really obscure):
# "char[+5]"
# "char['A']"
+
+def test_stdcall_cdecl():
+ assert parse("int __stdcall(int)") == [Prim(cffi_opcode.PRIM_INT),
+ '->', Func(0), NoOp(4), FuncEnd(2),
+ Prim(cffi_opcode.PRIM_INT)]
+ assert parse("int __stdcall func(int)") == parse("int __stdcall(int)")
+ assert parse("int (__stdcall *)()") == [Prim(cffi_opcode.PRIM_INT),
+ NoOp(3), '->', Pointer(1),
+ Func(0), FuncEnd(2), 0]
+ assert parse("int (__stdcall *p)()") == parse("int (__stdcall*)()")
+ parse_error("__stdcall int", "identifier expected", 0)
+ parse_error("__cdecl int", "identifier expected", 0)
+ parse_error("int __stdcall", "expected '('", 13)
+ parse_error("int __cdecl", "expected '('", 11)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit