Author: Armin Rigo <ar...@tunes.org> Branch: cffi-1.0 Changeset: r1699:943c257b5873 Date: 2015-04-14 15:35 +0200 http://bitbucket.org/cffi/cffi/changeset/943c257b5873/
Log: in-progress diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -3338,7 +3338,7 @@ /************************************************************/ -static PyObject *b_new_primitive_type(PyObject *self, PyObject *args) +static CTypeDescrObject *new_primitive_type(const char *name) { #define ENUM_PRIMITIVE_TYPES \ EPTYPE(c, char, CT_PRIMITIVE_CHAR) \ @@ -3403,7 +3403,6 @@ #undef EPTYPE CTypeDescrObject *td; - const char *name; static const struct descr_s { const char *name; int size, align, flags; } types[] = { #define EPTYPE(code, typename, flags) \ @@ -3422,9 +3421,6 @@ int name_size; ffi_type *ffitype; - if (!PyArg_ParseTuple(args, "s:new_primitive_type", &name)) - return NULL; - for (ptypes=types; ; ptypes++) { if (ptypes->name == NULL) { #ifndef HAVE_WCHAR_H @@ -3487,7 +3483,7 @@ td->ct_flags |= CT_PRIMITIVE_FITS_LONG; } td->ct_name_position = strlen(td->ct_name); - return (PyObject *)td; + return td; bad_ffi_type: PyErr_Format(PyExc_NotImplementedError, @@ -3497,15 +3493,19 @@ return NULL; } -static PyObject *b_new_pointer_type(PyObject *self, PyObject *args) -{ - CTypeDescrObject *td, *ctitem; +static PyObject *b_new_primitive_type(PyObject *self, PyObject *args) +{ + char *name; + if (!PyArg_ParseTuple(args, "s:new_primitive_type", &name)) + return NULL; + return (PyObject *)new_primitive_type(name); +} + +static CTypeDescrObject *new_pointer_type(CTypeDescrObject *ctitem) +{ + CTypeDescrObject *td; const char *extra; - if (!PyArg_ParseTuple(args, "O!:new_pointer_type", - &CTypeDescr_Type, &ctitem)) - return NULL; - if (ctitem->ct_flags & CT_ARRAY) extra = "(*)"; /* obscure case: see test_array_add */ else @@ -3525,7 +3525,16 @@ ((ctitem->ct_flags & CT_PRIMITIVE_CHAR) && ctitem->ct_size == sizeof(char))) td->ct_flags |= CT_CAST_ANYTHING; /* 'void *' or 'char *' only */ - return (PyObject *)td; + return td; +} + +static PyObject *b_new_pointer_type(PyObject *self, PyObject *args) +{ + CTypeDescrObject *ctitem; + if (!PyArg_ParseTuple(args, "O!:new_pointer_type", + &CTypeDescr_Type, &ctitem)) + return NULL; + return (PyObject *)new_pointer_type(ctitem); } static PyObject *b_new_array_type(PyObject *self, PyObject *args) @@ -3594,7 +3603,7 @@ return (PyObject *)td; } -static PyObject *b_new_void_type(PyObject *self, PyObject *args) +static CTypeDescrObject *new_void_type(void) { int name_size = strlen("void") + 1; CTypeDescrObject *td = ctypedescr_new(name_size); @@ -3605,7 +3614,12 @@ td->ct_size = -1; td->ct_flags = CT_VOID | CT_IS_OPAQUE; td->ct_name_position = strlen("void"); - return (PyObject *)td; + return td; +} + +static PyObject *b_new_void_type(PyObject *self, PyObject *args) +{ + return (PyObject *)new_void_type(); } static PyObject *_b_struct_or_union_type(const char *name, int flag) @@ -5683,8 +5697,10 @@ } #endif +#include "../new/cffi1_module.c" + static void *cffi_exports[] = { - 0, + (void *)26, _cffi_to_c_i8, _cffi_to_c_u8, _cffi_to_c_i16, @@ -5714,6 +5730,7 @@ _cffi_to_c__Bool, _prepare_pointer_call_argument, convert_array_from_object, + _cffi_init_module, }; /************************************************************/ diff --git a/new/_cffi_include.h b/new/_cffi_include.h new file mode 100644 --- /dev/null +++ b/new/_cffi_include.h @@ -0,0 +1,191 @@ +#include <Python.h> +#include <stddef.h> +#include "parse_c_type.h" + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */ +#if defined(_MSC_VER) +# include <malloc.h> /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include <stdint.h> +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ + typedef unsigned char _Bool; +# endif +#else +# include <stdint.h> +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) +# include <alloca.h> +# endif +#endif + +#if PY_MAJOR_VERSION < 3 +# undef PyCapsule_CheckExact +# undef PyCapsule_GetPointer +# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) +# define PyCapsule_GetPointer(capsule, name) \ + (PyCObject_AsVoidPtr(capsule)) +#endif + +#if PY_MAJOR_VERSION >= 3 +# define PyInt_FromLong PyLong_FromLong +#endif + +#define _cffi_from_c_double PyFloat_FromDouble +#define _cffi_from_c_float PyFloat_FromDouble +#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_ulong PyLong_FromUnsignedLong +#define _cffi_from_c_longlong PyLong_FromLongLong +#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong + +#define _cffi_to_c_double PyFloat_AsDouble +#define _cffi_to_c_float PyFloat_AsDouble + +#define _cffi_from_c_int_const(x) \ + (((x) > 0) ? \ + ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \ + PyInt_FromLong((long)(x)) : \ + PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \ + ((long long)(x) >= (long long)LONG_MIN) ? \ + PyInt_FromLong((long)(x)) : \ + PyLong_FromLongLong((long long)(x))) + +#define _cffi_from_c_int(x, type) \ + (((type)-1) > 0 ? /* unsigned */ \ + (sizeof(type) < sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + sizeof(type) == sizeof(long) ? \ + PyLong_FromUnsignedLong((unsigned long)x) : \ + PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ + (sizeof(type) <= sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + PyLong_FromLongLong((long long)x))) + +#define _cffi_to_c_int(o, type) \ + (sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ + : (type)_cffi_to_c_i8(o)) : \ + sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ + : (type)_cffi_to_c_i16(o)) : \ + sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ + : (type)_cffi_to_c_i32(o)) : \ + sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ + : (type)_cffi_to_c_i64(o)) : \ + (Py_FatalError("unsupported size for type " #type), (type)0)) + +#define _cffi_to_c_i8 \ + ((int(*)(PyObject *))_cffi_exports[1]) +#define _cffi_to_c_u8 \ + ((int(*)(PyObject *))_cffi_exports[2]) +#define _cffi_to_c_i16 \ + ((int(*)(PyObject *))_cffi_exports[3]) +#define _cffi_to_c_u16 \ + ((int(*)(PyObject *))_cffi_exports[4]) +#define _cffi_to_c_i32 \ + ((int(*)(PyObject *))_cffi_exports[5]) +#define _cffi_to_c_u32 \ + ((unsigned int(*)(PyObject *))_cffi_exports[6]) +#define _cffi_to_c_i64 \ + ((long long(*)(PyObject *))_cffi_exports[7]) +#define _cffi_to_c_u64 \ + ((unsigned long long(*)(PyObject *))_cffi_exports[8]) +#define _cffi_to_c_char \ + ((int(*)(PyObject *))_cffi_exports[9]) +#define _cffi_from_c_pointer \ + ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10]) +#define _cffi_to_c_pointer \ + ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11]) +#define _cffi_get_struct_layout \ + ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12]) +#define _cffi_restore_errno \ + ((void(*)(void))_cffi_exports[13]) +#define _cffi_save_errno \ + ((void(*)(void))_cffi_exports[14]) +#define _cffi_from_c_char \ + ((PyObject *(*)(char))_cffi_exports[15]) +#define _cffi_from_c_deref \ + ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16]) +#define _cffi_to_c \ + ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17]) +#define _cffi_from_c_struct \ + ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18]) +#define _cffi_to_c_wchar_t \ + ((wchar_t(*)(PyObject *))_cffi_exports[19]) +#define _cffi_from_c_wchar_t \ + ((PyObject *(*)(wchar_t))_cffi_exports[20]) +#define _cffi_to_c_long_double \ + ((long double(*)(PyObject *))_cffi_exports[21]) +#define _cffi_to_c__Bool \ + ((_Bool(*)(PyObject *))_cffi_exports[22]) +#define _cffi_prepare_pointer_call_argument \ + ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23]) +#define _cffi_convert_array_from_object \ + ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24]) +#define _cffi_init_module \ + ((int(*)(char *, const struct _cffi_type_context_s *))_cffi_exports[25]) +#define _CFFI_NUM_EXPORTS 26 + +typedef struct _ctypedescr CTypeDescrObject; + +static void *_cffi_exports[_CFFI_NUM_EXPORTS]; + + +static int _cffi_init(void) +{ + PyObject *module, *c_api_object = NULL; + void *src; + + module = PyImport_ImportModule("_cffi_backend"); + if (module == NULL) + goto failure; + + c_api_object = PyObject_GetAttrString(module, "_C_API"); + if (c_api_object == NULL) + goto failure; + if (!PyCapsule_CheckExact(c_api_object)) { + PyErr_SetNone(PyExc_ImportError); + goto failure; + } + src = PyCapsule_GetPointer(c_api_object, "cffi"); + if ((uintptr_t)(((void **)src)[0]) < _CFFI_NUM_EXPORTS) { + PyErr_SetString(PyExc_ImportError, + "the _cffi_backend module is an outdated version"); + goto failure; + } + memcpy(_cffi_exports, src, _CFFI_NUM_EXPORTS * sizeof(void *)); + + Py_DECREF(module); + Py_DECREF(c_api_object); + return 0; + + failure: + Py_XDECREF(module); + Py_XDECREF(c_api_object); + return -1; +} diff --git a/new/cffi1_module.c b/new/cffi1_module.c new file mode 100644 --- /dev/null +++ b/new/cffi1_module.c @@ -0,0 +1,52 @@ +#include "parse_c_type.c" +#include "realize_c_type.c" + +typedef struct FFIObject_s FFIObject; +typedef struct LibObject_s LibObject; + +static PyTypeObject FFI_Type; /* forward */ +static PyTypeObject Lib_Type; /* forward */ + +static PyObject *FFIError; + +#include "ffi_obj.c" +//#include "lib_obj.c" + + +static int init_ffi_lib(void) +{ + static int ffi_lib_ok = 0; + if (ffi_lib_ok) + return 0; + + if (!PyType_Ready(&FFI_Type) < 0) + return -1; + if (!PyType_Ready(&Lib_Type) < 0) + return -1; + + FFIError = PyErr_NewException("ffi.error", NULL, NULL); + if (FFIError == NULL) + return -1; + if (PyDict_SetItemString(FFI_Type.tp_dict, "error", FFIError) < 0) + return -1; + + ffi_lib_ok = 1; + return 0; +} + +static int _cffi_init_module(char *module_name, + const struct _cffi_type_context_s *ctx) +{ + if (init_ffi_lib() < 0) + return -1; + + PyObject *m = Py_InitModule(module_name, NULL); + if (m == NULL) + return -1; + + FFIObject *ffi = ffi_internal_new(ctx); + if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0) + return -1; + + return 0; +} diff --git a/new/ffi_obj.c b/new/ffi_obj.c new file mode 100644 --- /dev/null +++ b/new/ffi_obj.c @@ -0,0 +1,603 @@ + +/* An FFI object has methods like ffi.new(). It is also a container + for the type declarations (typedefs and structs) that you can use, + say in ffi.new(). + + CTypeDescrObjects are internally stored in the dict 'types_dict'. + The types_dict is lazily filled with CTypeDescrObjects made from + reading a _cffi_type_context_s structure. + + In "modern" mode, the FFI instance is made by the C extension + module originally created by recompile(). The _cffi_type_context_s + structure comes from global data in the C extension module. + + In "compatibility" mode, an FFI instance is created explicitly by + the user, and its _cffi_type_context_s is initially empty. You + need to call ffi.cdef() to add more information to it. +*/ + +#define FFI_COMPLEXITY_OUTPUT 1200 /* xxx should grow as needed */ + +struct FFIObject_s { + PyObject_HEAD + PyObject *types_dict; + PyObject *gc_wrefs; + struct _cffi_parse_info_s info; + _cffi_opcode_t internal_output[FFI_COMPLEXITY_OUTPUT]; +}; + +static FFIObject *ffi_internal_new(const struct _cffi_type_context_s *ctx) +{ + PyObject *dict = PyDict_New(); + if (dict == NULL) + return NULL; + + FFIObject *ffi = PyObject_GC_New(FFIObject, &FFI_Type); + if (ffi == NULL) { + Py_DECREF(dict); + return NULL; + } + ffi->types_dict = dict; + ffi->gc_wrefs = NULL; + ffi->info.ctx = ctx; + ffi->info.output = ffi->internal_output; + ffi->info.output_size = FFI_COMPLEXITY_OUTPUT; + + PyObject_GC_Track(ffi); + return ffi; +} + +static void ffi_dealloc(FFIObject *ffi) +{ + PyObject_GC_UnTrack(ffi); + Py_DECREF(ffi->types_dict); + Py_XDECREF(ffi->gc_wrefs); + PyObject_GC_Del(ffi); +} + +static int ffi_traverse(FFIObject *ffi, visitproc visit, void *arg) +{ + Py_VISIT(ffi->types_dict); + Py_VISIT(ffi->gc_wrefs); + return 0; +} + +static PyObject *ffiobj_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + /* user-facing initialization code, for explicit FFI() calls */ + /* XXX LATER */ + PyErr_SetString(PyExc_NotImplementedError, "FFI()"); + return NULL; +} + +#define ACCEPT_STRING 1 +#define ACCEPT_CTYPE 2 +#define ACCEPT_CDATA 4 +#define ACCEPT_ALL (ACCEPT_STRING | ACCEPT_CTYPE | ACCEPT_CDATA) + +static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg, + int accept) +{ + /* Returns the CTypeDescrObject from the user-supplied 'arg'. + Does not return a new reference! + */ + if ((accept & ACCEPT_STRING) && PyText_Check(arg)) { + PyObject *x = PyDict_GetItem(ffi->types_dict, arg); + if (x != NULL && CTypeDescr_Check(x)) + return (CTypeDescrObject *)x; + + char *input_text = PyText_AS_UTF8(arg); + int index = parse_c_type(&ffi->info, input_text); + if (index < 0) { + size_t num_spaces = ffi->info.error_location; + char spaces[num_spaces + 1]; + memset(spaces, ' ', num_spaces); + spaces[num_spaces] = '\0'; + PyErr_Format(FFIError, "%s\n%s\n%s^", ffi->info.error_message, + input_text, spaces); + return NULL; + } + CTypeDescrObject *ct = realize_c_type(ffi->info.ctx, + ffi->info.output, index); + if (ct == NULL) + return NULL; + x = PyDict_GetItemString(ffi->types_dict, ct->ct_name); + if (x != NULL) { + Py_INCREF(x); + Py_DECREF(ct); + ct = (CTypeDescrObject *)x; + } + PyDict_SetItemString(ffi->types_dict, ct->ct_name, (PyObject *)ct); + PyDict_SetItem(ffi->types_dict, arg, (PyObject *)ct); + return ct; + } + else if ((accept & ACCEPT_CTYPE) && CTypeDescr_Check(arg)) { + return (CTypeDescrObject *)arg; + } + else if ((accept & ACCEPT_CDATA) && CData_Check(arg)) { + return ((CDataObject *)arg)->c_type; + } + else { + const char *m1 = (accept & ACCEPT_STRING) ? "string" : ""; + const char *m2 = (accept & ACCEPT_CTYPE) ? "ctype object" : ""; + const char *m3 = (accept & ACCEPT_CDATA) ? "cdata object" : ""; + const char *s12 = (*m1 && (*m2 || *m3)) ? " or " : ""; + const char *s23 = (*m2 && *m3) ? " or " : ""; + PyErr_Format(PyExc_TypeError, "expected a %s%s%s%s%s, got '%.200s'", + m1, s12, m2, s23, m3, + Py_TYPE(arg)->tp_name); + return NULL; + } +} + +static PyObject *ffi_sizeof(FFIObject *self, PyObject *arg) +{ + CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL); + if (ct == NULL) + return NULL; + + if (ct->ct_size < 0) { + PyErr_Format(FFIError, "don't know the size of ctype '%s'", + ct->ct_name); + return NULL; + } + return PyInt_FromSsize_t(ct->ct_size); +} + +#if 0 +static PyObject *ffi_typeof(ZefFFIObject *self, PyObject *arg) +{ + PyObject *x = (PyObject *)_ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CDATA); + if (x != NULL) { + Py_INCREF(x); + } + else if (PyCFunction_Check(arg)) { + PyErr_SetString(PyExc_TypeError, "typeof(lib.func) not supported: the " + "exact type of functions is unknown (declare that " + "function as a function pointer instead)"); + } + return x; +} + +static PyObject *ffi_new(ZefFFIObject *self, PyObject *args) +{ + CTypeDescrObject *ct, *ctitem; + CDataObject *cd; + PyObject *arg, *init = Py_None; + Py_ssize_t dataoffset, datasize, explicitlength; + if (!PyArg_ParseTuple(args, "O|O:new", &arg, &init)) + return NULL; + + ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE); + if (ct == NULL) + return NULL; + + explicitlength = -1; + if (ct->ct_flags & (CT_POINTER | CT_STRUCT | CT_UNION)) { + dataoffset = offsetof(CDataObject_own_nolength, alignment); + ctitem = (ct->ct_flags & CT_POINTER) ? ct->ct_itemdescr : ct; + datasize = ctitem->ct_size; + if (datasize < 0) { + PyErr_Format(PyExc_TypeError, + "cannot instantiate ctype '%s' of unknown size", + ctitem->ct_name); + return NULL; + } + if (ctitem->ct_flags & CT_PRIMITIVE_CHAR) + datasize *= 2; /* forcefully add another character: a null */ + + if ((ctitem->ct_flags & CT_WITH_VAR_ARRAY) && init != Py_None) { + Py_ssize_t optvarsize = datasize; + if (convert_struct_from_object(NULL,ctitem, init, &optvarsize) < 0) + return NULL; + datasize = optvarsize; + } + } + else if (ct->ct_flags & CT_ARRAY) { + dataoffset = offsetof(CDataObject_own_nolength, alignment); + datasize = ct->ct_size; + if (datasize < 0) { + explicitlength = get_new_array_length(&init); + if (explicitlength < 0) + return NULL; + ctitem = ct->ct_itemdescr; + dataoffset = offsetof(CDataObject_own_length, alignment); + datasize = explicitlength * ctitem->ct_size; + if (explicitlength > 0 && + (datasize / explicitlength) != ctitem->ct_size) { + PyErr_SetString(PyExc_OverflowError, + "array size would overflow a Py_ssize_t"); + return NULL; + } + } + } + else if (ct->ct_flags & CT_PRIMITIVE_ANY) { + cd = _new_casted_primitive(ct); + datasize = ct->ct_size; + goto initialize_casted_primitive; + } + else { + PyErr_Format(PyExc_TypeError, + "cannot create cdata '%s' objects", ct->ct_name); + return NULL; + } + + cd = allocate_owning_object(dataoffset + datasize, ct); + if (cd == NULL) + return NULL; + + cd->c_data = ((char *)cd) + dataoffset; + if (explicitlength >= 0) + ((CDataObject_own_length*)cd)->length = explicitlength; + + initialize_casted_primitive: + memset(cd->c_data, 0, datasize); + if (init != Py_None) { + if (convert_from_object(cd->c_data, + (ct->ct_flags & CT_POINTER) ? ct->ct_itemdescr : ct, init) < 0) { + Py_DECREF(cd); + return NULL; + } + } + return (PyObject *)cd; +} + +static PyObject *ffi_cast(ZefFFIObject *self, PyObject *args) +{ + CTypeDescrObject *ct; + PyObject *ob, *arg; + if (!PyArg_ParseTuple(args, "OO:cast", &arg, &ob)) + return NULL; + + ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE); + if (ct == NULL) + return NULL; + + return do_cast(ct, ob); +} + +static PyObject *ffi_string(ZefFFIObject *self, PyObject *args) +{ + CDataObject *cd; + Py_ssize_t maxlen = -1; + if (!PyArg_ParseTuple(args, "O!|n:string", + &CData_Type, &cd, &maxlen)) + return NULL; + + if (cd->c_type->ct_itemdescr != NULL && + cd->c_type->ct_itemdescr->ct_flags & (CT_PRIMITIVE_CHAR | + CT_PRIMITIVE_SIGNED | + CT_PRIMITIVE_UNSIGNED)) { + Py_ssize_t length = maxlen; + if (cd->c_data == NULL) { + PyObject *s = cdata_repr(cd); + if (s != NULL) { + PyErr_Format(PyExc_RuntimeError, + "cannot use string() on %s", + PyText_AS_UTF8(s)); + Py_DECREF(s); + } + return NULL; + } + if (length < 0 && cd->c_type->ct_flags & CT_ARRAY) { + length = get_array_length(cd); + } + if (cd->c_type->ct_itemdescr->ct_size == sizeof(char)) { + const char *start = cd->c_data; + if (length < 0) { + /*READ(start, 1)*/ + length = strlen(start); + /*READ(start, length)*/ + } + else { + const char *end; + /*READ(start, length)*/ + end = (const char *)memchr(start, 0, length); + if (end != NULL) + length = end - start; + } + return PyBytes_FromStringAndSize(start, length); + } + } + else if (cd->c_type->ct_flags & CT_IS_ENUM) { + abort(); + //return convert_cdata_to_enum_string(cd, 0); + } + else if (cd->c_type->ct_flags & CT_IS_BOOL) { + /* fall through to TypeError */ + } + else if (cd->c_type->ct_flags & (CT_PRIMITIVE_CHAR | + CT_PRIMITIVE_SIGNED | + CT_PRIMITIVE_UNSIGNED)) { + /*READ(cd->c_data, cd->c_type->ct_size)*/ + if (cd->c_type->ct_size == sizeof(char)) + return PyBytes_FromStringAndSize(cd->c_data, 1); + } + PyErr_Format(PyExc_TypeError, "string(): unexpected cdata '%s' argument", + cd->c_type->ct_name); + return NULL; +} + +static CFieldObject *_ffi_field(CTypeDescrObject *ct, const char *fieldname) +{ + CFieldObject *cf; + if (ct->ct_stuff == NULL) { + PyErr_Format(PyExc_TypeError, "'%s' is incomplete", ct->ct_name); + return NULL; + } + cf = (CFieldObject *)PyDict_GetItemString(ct->ct_stuff, fieldname); + if (cf == NULL) { + PyErr_Format(PyExc_KeyError, "'%s' has got no field '%s'", + ct->ct_name, fieldname); + return NULL; + } + if (cf->cf_bitshift >= 0) { + PyErr_SetString(PyExc_TypeError, "not supported for bitfields"); + return NULL; + } + return cf; +} + +static PyObject *ffi_offsetof(ZefFFIObject *self, PyObject *args) +{ + PyObject *arg; + char *fieldname; + CTypeDescrObject *ct; + CFieldObject *cf; + + if (!PyArg_ParseTuple(args, "Os:offsetof", &arg, &fieldname)) + return NULL; + + ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE); + if (ct == NULL) + return NULL; + + if (!(ct->ct_flags & (CT_STRUCT|CT_UNION))) { + PyErr_Format(PyExc_TypeError, + "expected a struct or union ctype, got '%s'", + ct->ct_name); + return NULL; + } + cf = _ffi_field(ct, fieldname); + if (cf == NULL) + return NULL; + return PyInt_FromSsize_t(cf->cf_offset); +} + +static PyObject *ffi_addressof(ZefFFIObject *self, PyObject *args) +{ + PyObject *obj; + char *fieldname = NULL; + + if (!PyArg_ParseTuple(args, "O|z:addressof", &obj, &fieldname)) + return NULL; + + if (CData_Check(obj)) { + CDataObject *cd = (CDataObject *)obj; + CTypeDescrObject *ct; + Py_ssize_t offset; + + ct = cd->c_type; + if (fieldname != NULL && ct->ct_flags & CT_POINTER) + ct = ct->ct_itemdescr; + + if (!(ct->ct_flags & (CT_STRUCT|CT_UNION))) { + PyErr_Format(PyExc_TypeError, + "expected a struct or union cdata, got '%s'", + ct->ct_name); + return NULL; + } + + if (fieldname == NULL) { + offset = 0; + } + else { + CFieldObject *cf = _ffi_field(ct, fieldname); + if (cf == NULL) + return NULL; + offset = cf->cf_offset; + ct = cf->cf_type; + } + ct = fetch_pointer_type(self->types_dict, ct); + if (ct == NULL) + return NULL; + return new_simple_cdata(cd->c_data + offset, ct); + } + else if (ZefLib_Check(obj)) { + PyObject *attr, *name; + char *reason; + + if (fieldname == NULL) { + PyErr_SetString(PyExc_TypeError, "addressof(Lib, fieldname) " + "cannot be used with only one argument"); + return NULL; + } + name = PyString_FromString(fieldname); + if (name == NULL) + return NULL; + attr = lib_findattr((ZefLibObject *)obj, name, ZefError); + Py_DECREF(name); + if (attr == NULL) + return NULL; + + if (ZefGlobSupport_Check(attr)) { + return addressof_global_var((ZefGlobSupportObject *)attr); + } + + if (PyCFunction_Check(attr)) + reason = "declare that function as a function pointer instead"; + else + reason = "numeric constants don't have addresses"; + + PyErr_Format(PyExc_TypeError, + "cannot take the address of '%s' (%s)", + fieldname, reason); + return NULL; + } + else { + PyErr_SetString(PyExc_TypeError, "addressof() first argument must be " + "a cdata struct or union, a pointer to one, or a Lib " + "object"); + return NULL; + } +} + +static PyObject *ffi_getctype(ZefFFIObject *self, PyObject *args) +{ + PyObject *cdecl, *res; + char *p, *replace_with = ""; + int add_paren, add_space; + CTypeDescrObject *ct; + size_t replace_with_len; + + if (!PyArg_ParseTuple(args, "O|s:getctype", &cdecl, &replace_with)) + return NULL; + + ct = _ffi_type(self, cdecl, ACCEPT_STRING|ACCEPT_CTYPE); + if (ct == NULL) + return NULL; + + while (replace_with[0] != 0 && isspace(replace_with[0])) + replace_with++; + replace_with_len = strlen(replace_with); + while (replace_with_len > 0 && isspace(replace_with[replace_with_len - 1])) + replace_with_len--; + + add_paren = (replace_with[0] == '*' && + ((ct->ct_flags & (CT_ARRAY | CT_FUNCTION)) != 0)); + add_space = (!add_paren && replace_with_len > 0 && + replace_with[0] != '[' && replace_with[0] != '('); + + res = combine_type_name_l(ct, replace_with_len + add_space + 2 * add_paren); + if (res == NULL) + return NULL; + + p = PyString_AS_STRING(res) + ct->ct_name_position; + if (add_paren) + *p++ = '('; + if (add_space) + *p++ = ' '; + memcpy(p, replace_with, replace_with_len); + if (add_paren) + p[replace_with_len] = ')'; + return res; +} + +static PyObject *ffi_new_handle(ZefFFIObject *self, PyObject *arg) +{ + CTypeDescrObject *ct = ZefNULL->c_type; // <ctype 'void *'> + CDataObject *cd; + + cd = (CDataObject *)PyObject_GC_New(CDataObject, &CDataOwningGC_Type); + if (cd == NULL) + return NULL; + Py_INCREF(ct); + cd->c_type = ct; + Py_INCREF(arg); + cd->c_data = ((char *)arg) - 42; + cd->c_weakreflist = NULL; + PyObject_GC_Track(cd); + return (PyObject *)cd; +} + +static PyObject *ffi_from_handle(PyObject *self, PyObject *arg) +{ + CTypeDescrObject *ct; + char *raw; + PyObject *x; + if (!CData_Check(arg)) { + PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object"); + return NULL; + } + ct = ((CDataObject *)arg)->c_type; + raw = ((CDataObject *)arg)->c_data; + if (!(ct->ct_flags & CT_CAST_ANYTHING)) { + PyErr_Format(PyExc_TypeError, + "expected a 'cdata' object with a 'void *' out of " + "new_handle(), got '%s'", ct->ct_name); + return NULL; + } + if (!raw) { + PyErr_SetString(PyExc_RuntimeError, + "cannot use from_handle() on NULL pointer"); + return NULL; + } + x = (PyObject *)(raw + 42); + Py_INCREF(x); + return x; +} + +static PyObject *ffi_gc(ZefFFIObject *self, PyObject *args) +{ + CDataObject *cd; + PyObject *destructor; + + if (!PyArg_ParseTuple(args, "O!O:gc", &CData_Type, &cd, &destructor)) + return NULL; + + return gc_weakrefs_build(self, cd, destructor); +} +#endif + +static PyMethodDef ffi_methods[] = { +#if 0 + {"addressof", (PyCFunction)ffi_addressof, METH_VARARGS}, + {"cast", (PyCFunction)ffi_cast, METH_VARARGS}, + {"close_library", ffi_close_library, METH_VARARGS | METH_STATIC}, + {"from_handle", (PyCFunction)ffi_from_handle,METH_O}, + {"gc", (PyCFunction)ffi_gc, METH_VARARGS}, + {"getctype", (PyCFunction)ffi_getctype, METH_VARARGS}, + {"load_library", (PyCFunction)ffi_load_library,METH_VARARGS|METH_KEYWORDS}, + {"offsetof", (PyCFunction)ffi_offsetof, METH_VARARGS}, + {"new", (PyCFunction)ffi_new, METH_VARARGS}, + {"new_handle", (PyCFunction)ffi_new_handle,METH_O}, +#endif + {"sizeof", (PyCFunction)ffi_sizeof, METH_O}, +#if 0 + {"string", (PyCFunction)ffi_string, METH_VARARGS}, + {"typeof", (PyCFunction)ffi_typeof, METH_O}, +#endif + {NULL} +}; + +static PyTypeObject FFI_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "cffi.FFI", + sizeof(FFIObject), + 0, + (destructor)ffi_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + 0, /* tp_doc */ + (traverseproc)ffi_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + ffi_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + ffiobj_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; diff --git a/new/lib_obj.c b/new/lib_obj.c new file mode 100644 --- /dev/null +++ b/new/lib_obj.c @@ -0,0 +1,197 @@ + +/* A Lib object is what is returned by any of: + + - the "lib" attribute of a C extension module originally created by + recompile() + + - ffi.dlopen() + + - ffi.verify() + + A Lib object is special in the sense that it has a custom + __getattr__ which returns C globals, functions and constants. It + raises AttributeError for anything else, like '__class__'. + + A Lib object has internally a reference back to the FFI object, + which holds the _cffi_type_context_s used to create lazily the + objects returned by __getattr__. For a dlopen()ed Lib object, all + the 'address' fields in _cffi_global_s are NULL, and instead + dlsym() is used lazily on the l_dl_lib. +*/ + +struct LibObject_s { + PyObject_HEAD + PyObject *l_dict; /* content, built lazily */ + struct FFIObject_s *l_ffi; /* ffi object */ + void *l_dl_lib; /* the result of 'dlopen()', or NULL */ +}; + +#define ZefLib_Check(ob) ((Py_TYPE(ob) == &ZefLib_Type)) + +static void lib_dealloc(ZefLibObject *lib) +{ + (void)lib_close(lib); + PyObject_Del(lib); +} + +static PyObject *lib_repr(ZefLibObject *lib) +{ + return PyText_FromFormat("<zeffir.Lib object for '%.200s'%s>", + lib->l_libname, + lib->l_dl_lib == NULL ? " (closed)" : ""); +} + +static PyObject *lib_findattr(ZefLibObject *lib, PyObject *name, PyObject *exc) +{ + /* does not return a new reference! */ + + if (lib->l_dict == NULL) { + PyErr_Format(ZefError, "lib '%.200s' was closed", lib->l_libname); + return NULL; + } + + PyObject *x = PyDict_GetItem(lib->l_dict, name); + if (x == NULL) { + PyErr_Format(exc, + "lib '%.200s' has no function," + " global variable or constant '%.200s'", + lib->l_libname, + PyText_Check(name) ? PyText_AS_UTF8(name) : "?"); + return NULL; + } + return x; +} + +static PyObject *lib_getattr(ZefLibObject *lib, PyObject *name) +{ + PyObject *x = lib_findattr(lib, name, PyExc_AttributeError); + if (x == NULL) + return NULL; + + if (ZefGlobSupport_Check(x)) { + return read_global_var((ZefGlobSupportObject *)x); + } + Py_INCREF(x); + return x; +} + +static int lib_setattr(ZefLibObject *lib, PyObject *name, PyObject *val) +{ + PyObject *x = lib_findattr(lib, name, PyExc_AttributeError); + if (x == NULL) + return -1; + + if (val == NULL) { + PyErr_SetString(PyExc_AttributeError, + "cannot delete attributes from Lib object"); + return -1; + } + + if (ZefGlobSupport_Check(x)) { + return write_global_var((ZefGlobSupportObject *)x, val); + } + + PyErr_Format(PyExc_AttributeError, + "cannot write to function or constant '%.200s'", + PyText_Check(name) ? PyText_AS_UTF8(name) : "?"); + return -1; +} + +static PyObject *lib_dir(PyObject *lib, PyObject *noarg) +{ + return PyDict_Keys(((ZefLibObject *)lib)->l_dict); +} + +static PyMethodDef lib_methods[] = { + {"__dir__", lib_dir, METH_NOARGS}, + {NULL, NULL} /* sentinel */ +}; + +static PyTypeObject ZefLib_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "zeffir.Lib", + sizeof(ZefLibObject), + 0, + (destructor)lib_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc)lib_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + (getattrofunc)lib_getattr, /* tp_getattro */ + (setattrofunc)lib_setattr, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + lib_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(ZefLibObject, l_dict), /* tp_dictoffset */ +}; + +static void lib_dlerror(ZefLibObject *lib) +{ + char *error = dlerror(); + if (error == NULL) + error = "(no error reported)"; + PyErr_Format(PyExc_OSError, "%s: %s", lib->l_libname, error); +} + +static ZefLibObject *lib_create(PyObject *path) +{ + ZefLibObject *lib; + + lib = PyObject_New(ZefLibObject, &ZefLib_Type); + if (lib == NULL) + return NULL; + + lib->l_dl_lib = NULL; + lib->l_libname = PyString_AsString(path); + Py_INCREF(path); + lib->l_libname_obj = path; + lib->l_dict = PyDict_New(); + if (lib->l_dict == NULL) { + Py_DECREF(lib); + return NULL; + } + + lib->l_dl_lib = dlopen(lib->l_libname, RTLD_LAZY); + if (lib->l_dl_lib == NULL) { + lib_dlerror(lib); + Py_DECREF(lib); + return NULL; + } + return lib; +} + +static int lib_close(ZefLibObject *lib) +{ + void *dl_lib; + Py_CLEAR(lib->l_dict); + + dl_lib = lib->l_dl_lib; + if (dl_lib != NULL) { + lib->l_dl_lib = NULL; + if (dlclose(dl_lib) != 0) { + lib_dlerror(lib); + return -1; + } + } + return 0; +} diff --git a/new/manual.c b/new/manual.c new file mode 100644 --- /dev/null +++ b/new/manual.c @@ -0,0 +1,109 @@ +#include "_cffi_include.h" + + +int foo42(int a, int *b) +{ + return a - *b; +} + +int foo64(int a) +{ + return ~a; +} + +/************************************************************/ + +static void *_cffi_types[] = { + _CFFI_OP(_CFFI_OP_FUNCTION, 1), + _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT), + _CFFI_OP(_CFFI_OP_POINTER, 1), + _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), + _CFFI_OP(_CFFI_OP_FUNCTION, 1), + _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT), + _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +}; + +static PyObject * +_cffi_f_foo42(PyObject *self, PyObject *args) +{ + int x0; + int * x1; + Py_ssize_t datasize; + int result; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_ParseTuple(args, "OO:foo42", &arg0, &arg1)) + return NULL; + + x0 = _cffi_to_c_int(arg0, int); + if (x0 == (int)-1 && PyErr_Occurred()) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_types[1], arg1, (char **)&x1); + if (datasize != 0) { + if (datasize < 0) + return NULL; + x1 = alloca(datasize); + memset((void *)x1, 0, datasize); + if (_cffi_convert_array_from_object((char *)x1, _cffi_types[1], arg1) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = foo42(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + return _cffi_from_c_int(result, int); +} + +static PyObject * +_cffi_f_foo64(PyObject *self, PyObject *arg0) +{ + int x0; + int result; + + x0 = _cffi_to_c_int(arg0, int); + if (x0 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = foo64(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + return _cffi_from_c_int(result, int); +} + +static const struct _cffi_global_s _cffi_globals[] = { + { "foo42", &_cffi_f_foo42, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN, 0) }, + { "foo64", &_cffi_f_foo64, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN, 4) }, +}; + +static const struct _cffi_type_context_s _cffi_type_context = { + _cffi_types, + _cffi_globals, + NULL, /* no constants */ + NULL, + NULL, + NULL, + NULL, + 1, /* num_globals */ + 0, + 0, + 0, + 0, +}; + +PyMODINIT_FUNC +initmanual(void) +{ + if (_cffi_init() < 0) + return; + + _cffi_init_module("manual", &_cffi_type_context); +} diff --git a/new/parse_c_type.c b/new/parse_c_type.c --- a/new/parse_c_type.c +++ b/new/parse_c_type.c @@ -41,9 +41,9 @@ typedef struct { struct _cffi_parse_info_s *info; - const char *p; + const char *input, *p; + size_t size; // the next token is at 'p' and of length 'size' enum token_e kind; - size_t size; _cffi_opcode_t *output; size_t output_index; } token_t; @@ -177,7 +177,7 @@ { if (tok->kind != TOK_ERROR) { tok->kind = TOK_ERROR; - tok->info->error_location = tok->p; + tok->info->error_location = tok->p - tok->input; tok->info->error_message = msg; } return -1; @@ -349,7 +349,7 @@ return _CFFI_GETARG(result); } -static int search_struct_union(struct _cffi_type_context_s *ctx, +static int search_struct_union(const struct _cffi_type_context_s *ctx, const char *search, size_t search_len) { int left = 0, right = ctx->num_structs_unions; @@ -368,7 +368,7 @@ return -1; } -static int search_typename(struct _cffi_type_context_s *ctx, +static int search_typename(const struct _cffi_type_context_s *ctx, const char *search, size_t search_len) { int left = 0, right = ctx->num_typenames; @@ -554,6 +554,7 @@ token.info = info; token.kind = TOK_START; + token.input = input; token.p = input; token.size = 0; token.output = info->output; diff --git a/new/parse_c_type.h b/new/parse_c_type.h --- a/new/parse_c_type.h +++ b/new/parse_c_type.h @@ -95,10 +95,10 @@ }; struct _cffi_parse_info_s { - struct _cffi_type_context_s *ctx; + const struct _cffi_type_context_s *ctx; _cffi_opcode_t *output; int output_size; - const char *error_location; + size_t error_location; const char *error_message; }; diff --git a/new/realize_c_type.c b/new/realize_c_type.c --- a/new/realize_c_type.c +++ b/new/realize_c_type.c @@ -1,22 +1,19 @@ -#include <Python.h> -#include "parse_c_type.h" +static CTypeDescrObject *all_primitives[_CFFI__NUM_PRIM]; -static PyObject *all_primitives[_CFFI__NUM_PRIM]; - -PyObject *build_primitive_type(int num) +CTypeDescrObject *build_primitive_type(int num) { - PyObject *x; + CTypeDescrObject *x; switch (num) { case _CFFI_PRIM_VOID: - x = PyString_FromString("VOID"); + x = new_void_type(); break; case _CFFI_PRIM_INT: - x = PyString_FromString("INT"); + x = new_primitive_type("int"); break; default: @@ -29,15 +26,21 @@ } -PyObject *realize_c_type(struct _cffi_type_context_s *ctx, - _cffi_opcode_t opcodes[], int index) +/* Interpret an opcodes[] array. If opcodes == ctx->types, store all + the intermediate types back in the opcodes[]. Returns a new + reference. +*/ +CTypeDescrObject *realize_c_type(const struct _cffi_type_context_s *ctx, + _cffi_opcode_t opcodes[], int index) { - PyObject *x, *y; + CTypeDescrObject *ct; + CTypeDescrObject *x, *y; _cffi_opcode_t op = opcodes[index]; + if ((((uintptr_t)op) & 1) == 0) { - x = (PyObject *)op; - Py_INCREF(x); - return x; + ct = (CTypeDescrObject *)op; + Py_INCREF(ct); + return ct; } switch (_CFFI_GETOP(op)) { @@ -53,7 +56,7 @@ y = realize_c_type(ctx, opcodes, _CFFI_GETARG(op)); if (y == NULL) return NULL; - x = Py_BuildValue("sO", "pointer", y); + x = new_pointer_type(y); Py_DECREF(y); break; @@ -62,44 +65,10 @@ return NULL; } - if (opcodes == ctx->types) { + if (x != NULL && opcodes == ctx->types) { + assert((((uintptr_t)x) & 1) == 0); Py_INCREF(x); opcodes[index] = x; } return x; }; - - -static PyObject *b_test(PyObject *self, PyObject *args) -{ - char *s; - if (!PyArg_ParseTuple(args, "s", &s)) - return NULL; - - _cffi_opcode_t opcodes[100]; - struct _cffi_type_context_s global_ctx = { NULL }; - struct _cffi_parse_info_s parse_info = { - .ctx = &global_ctx, - .output = opcodes, - .output_size = 100, - }; - int res = parse_c_type(&parse_info, s); - if (res < 0) { - PyErr_SetString(PyExc_ValueError, parse_info.error_message); - return NULL; - } - - return realize_c_type(&global_ctx, opcodes, res); -} - -static PyMethodDef MyMethods[] = { - {"test", b_test, METH_VARARGS}, - {NULL, NULL} /* Sentinel */ -}; - -PyMODINIT_FUNC -initrealize_c_type(void) -{ - PyObject *m = Py_InitModule("realize_c_type", MyMethods); - (void)m; -} diff --git a/new/setup_manual.py b/new/setup_manual.py new file mode 100644 --- /dev/null +++ b/new/setup_manual.py @@ -0,0 +1,5 @@ +from distutils.core import setup +from distutils.extension import Extension +setup(name='manual', + ext_modules=[Extension(name='manual', + sources=['manual.c'])]) diff --git a/new/test_parse_c_type.py b/new/test_parse_c_type.py --- a/new/test_parse_c_type.py +++ b/new/test_parse_c_type.py @@ -49,11 +49,10 @@ info.output_size = len(out) for j in range(len(out)): out[j] = ffi.cast("void *", -424242) - c_input = ffi.new("char[]", input) - res = lib.parse_c_type(info, c_input) + res = lib.parse_c_type(info, input) if res < 0: raise ParseError(ffi.string(info.error_message), - info.error_location - c_input) + info.error_location) assert 0 <= res < len(out) result = [] for j in range(len(out)): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit