Skip to content

Commit b04977a

Browse files
committed
Merge pull request #767 from rudi-c/ctypes
Import the ctypes module.
2 parents 2f60cce + 15655a6 commit b04977a

File tree

16 files changed

+286
-48
lines changed

16 files changed

+286
-48
lines changed

from_cpython/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ add_custom_command(OUTPUT
118118
${CMAKE_BINARY_DIR}/lib_pyston/pyexpat.pyston.so
119119
${CMAKE_BINARY_DIR}/lib_pyston/_elementtree.pyston.so
120120
${CMAKE_BINARY_DIR}/lib_pyston/bz2.pyston.so
121+
${CMAKE_BINARY_DIR}/lib_pyston/_ctypes.pyston.so
121122
${CMAKE_BINARY_DIR}/lib_pyston/grp.pyston.so
122123
${CMAKE_BINARY_DIR}/lib_pyston/termios.pyston.so
123124
${CMAKE_BINARY_DIR}/lib_pyston/_curses.pyston.so
@@ -129,6 +130,11 @@ add_custom_command(OUTPUT
129130
Modules/_multiprocessing/multiprocessing.c
130131
Modules/_multiprocessing/semaphore.c
131132
Modules/_multiprocessing/socket_connection.c
133+
Modules/_ctypes/_ctypes.c
134+
Modules/_ctypes/callbacks.c
135+
Modules/_ctypes/callproc.c
136+
Modules/_ctypes/stgdict.c
137+
Modules/_ctypes/cfield.c
132138
Modules/expat/xmlparse.c
133139
Modules/expat/xmlrole.c
134140
Modules/expat/xmltok.c

from_cpython/Include/compile.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
2+
#ifndef Py_COMPILE_H
3+
#define Py_COMPILE_H
4+
5+
#include "code.h"
6+
7+
#ifdef __cplusplus
8+
extern "C" {
9+
#endif
10+
11+
/* Public interface */
12+
struct _node; /* Declare the existence of this type */
13+
PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *);
14+
15+
/* Future feature support */
16+
17+
typedef struct {
18+
int ff_features; /* flags set by future statements */
19+
int ff_lineno; /* line number of last future statement */
20+
} PyFutureFeatures;
21+
22+
#define FUTURE_NESTED_SCOPES "nested_scopes"
23+
#define FUTURE_GENERATORS "generators"
24+
#define FUTURE_DIVISION "division"
25+
#define FUTURE_ABSOLUTE_IMPORT "absolute_import"
26+
#define FUTURE_WITH_STATEMENT "with_statement"
27+
#define FUTURE_PRINT_FUNCTION "print_function"
28+
#define FUTURE_UNICODE_LITERALS "unicode_literals"
29+
30+
31+
struct _mod; /* Declare the existence of this type */
32+
PyAPI_FUNC(PyCodeObject *) PyAST_Compile(struct _mod *, const char *,
33+
PyCompilerFlags *, PyArena *);
34+
PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(struct _mod *, const char *);
35+
36+
37+
#ifdef __cplusplus
38+
}
39+
#endif
40+
#endif /* !Py_COMPILE_H */

from_cpython/Include/pyconfig.h.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define _GNU_SOURCE 1
2121

2222
#define PY_LONG_LONG long long
23+
#define SIZEOF__BOOL 1
2324
#define SIZEOF_VOID_P 8
2425
#define SIZEOF_SIZE_T 8
2526
#define SIZEOF_INT 4

from_cpython/Modules/_ctypes/_ctypes.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2044,13 +2044,21 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
20442044
break;
20452045
}
20462046

2047-
if (ml) {
2047+
// TODO: Pyston change:
2048+
// For now, don't run this code path because we don't support some of
2049+
// the descriptor CAPI functions.
2050+
// We do this to be able to run `import ctypes`, but this will need to be
2051+
// enabled again once we want CType to actually work.
2052+
// if (ml) {
2053+
if (false) {
20482054
#if (PYTHON_API_VERSION >= 1012)
20492055
PyObject *meth;
20502056
int x;
2057+
/*
20512058
meth = PyDescr_NewClassMethod(result, ml);
20522059
if (!meth)
20532060
return NULL;
2061+
*/
20542062
#else
20552063
#error
20562064
PyObject *meth, *func;

from_cpython/Modules/_ctypes/callbacks.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
#include "Python.h"
66
#include "compile.h" /* required only for 2.3, as it seems */
7-
#include "frameobject.h"
7+
8+
// Pyston change: We don't have this file and commented out the function that needs it, but
9+
// we may want to support that function in the future.
10+
//#include "frameobject.h"
811

912
#include <ffi.h>
1013
#ifdef MS_WIN32
@@ -149,6 +152,9 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
149152
/* after code that pyrex generates */
150153
void _ctypes_add_traceback(char *funcname, char *filename, int lineno)
151154
{
155+
// TODO: Pyston change:
156+
// Supporting this will require frameobject.h
157+
#if 0
152158
PyObject *py_globals = 0;
153159
PyCodeObject *py_code = 0;
154160
PyFrameObject *py_frame = 0;
@@ -170,6 +176,9 @@ void _ctypes_add_traceback(char *funcname, char *filename, int lineno)
170176
Py_XDECREF(py_globals);
171177
Py_XDECREF(py_code);
172178
Py_XDECREF(py_frame);
179+
#else
180+
assert(false);
181+
#endif
173182
}
174183

175184
#ifdef MS_WIN32

from_cpython/Modules/_ctypes/cfield.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1291,7 +1291,9 @@ s_get(void *ptr, Py_ssize_t size)
12911291
*/
12921292
slen = strlen(PyString_AS_STRING(result));
12931293
size = min(size, (Py_ssize_t)slen);
1294-
if (result->ob_refcnt == 1) {
1294+
1295+
// Pyston change: no ob_refcnt
1296+
if (false /*result->ob_refcnt == 1*/) {
12951297
/* shorten the result */
12961298
_PyString_Resize(&result, size);
12971299
return result;

from_cpython/setup.py

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,81 @@
22

33
from distutils.core import setup, Extension
44
import os
5+
import sysconfig
56

67
def relpath(fn):
78
r = os.path.join(os.path.dirname(__file__), fn)
89
return r
910

11+
def unique(f):
12+
# Use an array otherwise Python 2 gets confused about scoping.
13+
cache = []
14+
def wrapper(*args):
15+
if len(cache) == 0:
16+
cache.append(f(*args))
17+
return cache[0]
18+
return wrapper
19+
20+
@unique
1021
def multiprocessing_ext():
1122
return Extension("_multiprocessing", sources = map(relpath, [
1223
"Modules/_multiprocessing/multiprocessing.c",
1324
"Modules/_multiprocessing/socket_connection.c",
1425
"Modules/_multiprocessing/semaphore.c",
1526
]))
1627

28+
@unique
1729
def bz2_ext():
1830
return Extension("bz2", sources = map(relpath, [
1931
"Modules/bz2module.c",
2032
]), libraries = ['bz2'])
2133

34+
@unique
35+
def ctypes_ext():
36+
ext = Extension("_ctypes", sources = map(relpath, [
37+
"Modules/_ctypes/_ctypes.c",
38+
"Modules/_ctypes/callbacks.c",
39+
"Modules/_ctypes/callproc.c",
40+
"Modules/_ctypes/stgdict.c",
41+
"Modules/_ctypes/cfield.c"
42+
]))
43+
44+
# Hack: Just copy the values of ffi_inc and ffi_lib from CPython's setup.py
45+
# May want something more robust later.
46+
ffi_inc = ['/usr/include/x86_64-linux-gnu']
47+
ffi_lib = "ffi_pic"
48+
ext.include_dirs.extend(ffi_inc)
49+
ext.libraries.append(ffi_lib)
50+
51+
return ext
52+
53+
@unique
54+
def ctypes_test_ext():
55+
# TODO: I'm not sure how to use the ctypes tests, I just copied it over
56+
# from CPython's setup.py. For now we're only importing ctypes, not passing
57+
# all its tests.
58+
return Extension('_ctypes_test',
59+
sources= map(relpath, ['Modules/_ctypes/_ctypes_test.c']))
60+
61+
@unique
2262
def grp_ext():
2363
return Extension("grp", sources = map(relpath, [
2464
"Modules/grpmodule.c",
2565
]))
2666

67+
@unique
2768
def curses_ext():
2869
return Extension("_curses", sources = map(relpath, [
2970
"Modules/_cursesmodule.c",
3071
]), libraries = ['curses'])
3172

73+
@unique
3274
def termios_ext():
3375
return Extension("termios", sources = map(relpath, [
3476
"Modules/termios.c",
3577
]))
3678

79+
@unique
3780
def pyexpat_ext():
3881
define_macros = [('HAVE_EXPAT_CONFIG_H', '1'),]
3982
expat_sources = map(relpath, ['Modules/expat/xmlparse.c',
@@ -60,6 +103,7 @@ def pyexpat_ext():
60103
depends = expat_depends,
61104
)
62105

106+
@unique
63107
def elementtree_ext():
64108
# elementtree depends on expat
65109
pyexpat = pyexpat_ext()
@@ -71,10 +115,15 @@ def elementtree_ext():
71115
sources = [relpath('Modules/_elementtree.c')],
72116
depends = pyexpat.depends,
73117
)
118+
ext_modules = [multiprocessing_ext(),
119+
pyexpat_ext(),
120+
elementtree_ext(),
121+
bz2_ext(),
122+
ctypes_ext(),
123+
ctypes_test_ext(),
124+
grp_ext(),
125+
curses_ext(),
126+
termios_ext()]
74127

75128

76-
setup(name="Pyston",
77-
version="1.0",
78-
description="Pyston shared modules",
79-
ext_modules=[multiprocessing_ext(), pyexpat_ext(), elementtree_ext(), bz2_ext(), grp_ext(), curses_ext(), termios_ext()]
80-
)
129+
setup(name="Pyston", version="1.0", description="Pyston shared modules", ext_modules=ext_modules)

src/capi/typeobject.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3235,11 +3235,7 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
32353235
| Py_TPFLAGS_TUPLE_SUBCLASS | Py_TPFLAGS_STRING_SUBCLASS | Py_TPFLAGS_UNICODE_SUBCLASS
32363236
| Py_TPFLAGS_DICT_SUBCLASS | Py_TPFLAGS_BASE_EXC_SUBCLASS | Py_TPFLAGS_TYPE_SUBCLASS;
32373237
RELEASE_ASSERT((cls->tp_flags & ~ALLOWABLE_FLAGS) == 0, "");
3238-
if (cls->tp_as_number) {
3239-
RELEASE_ASSERT(cls->tp_flags & Py_TPFLAGS_CHECKTYPES, "Pyston doesn't yet support non-checktypes behavior");
3240-
}
32413238

3242-
RELEASE_ASSERT(cls->tp_descr_set == NULL, "");
32433239
RELEASE_ASSERT(cls->tp_free == NULL || cls->tp_free == PyObject_Del || cls->tp_free == PyObject_GC_Del, "");
32443240
RELEASE_ASSERT(cls->tp_is_gc == NULL, "");
32453241
RELEASE_ASSERT(cls->tp_mro == NULL, "");
@@ -3317,8 +3313,24 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
33173313
cls->gc_visit = &conservativeGCHandler;
33183314
cls->is_user_defined = true;
33193315

3320-
// this should get automatically initialized to 0 on this path:
3321-
assert(cls->attrs_offset == 0);
3316+
3317+
if (!cls->instancesHaveHCAttrs() && cls->tp_base) {
3318+
// These doesn't get copied in inherit_slots like other slots do.
3319+
if (cls->tp_base->instancesHaveHCAttrs()) {
3320+
cls->attrs_offset = cls->tp_base->attrs_offset;
3321+
}
3322+
3323+
// Example of when this code path could be reached and needs to be:
3324+
// If this class is a metaclass defined in a C extension, chances are that some of its
3325+
// instances may be hardcoded in the C extension as well. Those instances will call
3326+
// PyType_Ready and expect their class (this metaclass) to have a place to put attributes.
3327+
// e.g. CTypes does this.
3328+
bool is_metaclass = PyType_IsSubtype(cls, type_cls);
3329+
assert(!is_metaclass || cls->instancesHaveHCAttrs() || cls->instancesHaveDictAttrs());
3330+
} else {
3331+
// this should get automatically initialized to 0 on this path:
3332+
assert(cls->attrs_offset == 0);
3333+
}
33223334

33233335
if (Py_TPFLAGS_BASE_EXC_SUBCLASS & cls->tp_flags) {
33243336
exception_types.push_back(cls);

src/runtime/int.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,16 @@ extern "C" int _PyInt_AsInt(PyObject* obj) noexcept {
184184
return (int)result;
185185
}
186186

187+
#ifdef HAVE_LONG_LONG
188+
extern "C" unsigned PY_LONG_LONG PyInt_AsUnsignedLongLongMask(register PyObject* op) noexcept {
189+
Py_FatalError("unimplemented");
190+
191+
unsigned PY_LONG_LONG val = 0;
192+
193+
return val;
194+
}
195+
#endif
196+
187197
extern "C" PyObject* PyInt_FromString(const char* s, char** pend, int base) noexcept {
188198
char* end;
189199
long x;

0 commit comments

Comments
 (0)