~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_static_tuple_c.h

messy but working.

Start exposing the C API using a nice python dict, rather than offsets into an array.
This is much more convenient and allows a small amount of api skew without
serious problems. It also allows some safety checks to be performed during
import.


Mostly we just need to clean up the code a bit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
#ifndef _STATIC_TUPLE_H_
19
19
#define _STATIC_TUPLE_H_
20
20
#include <Python.h>
 
21
#include <string.h>
21
22
 
22
23
#define STATIC_TUPLE_HAS_HASH 0
23
24
/* Caching the hash adds memory, but allows us to save a little time during
64
65
    PyObject_VAR_HEAD
65
66
    PyObject *table[0];
66
67
} KeyIntern;
67
 
// extern PyTypeObject StaticTuple_Type;
68
68
 
69
69
#define StaticTuple_CheckExact(op) (Py_TYPE(op) == &StaticTuple_Type)
70
70
#define StaticTuple_SET_ITEM(key, offset, val) \
72
72
#define StaticTuple_GET_ITEM(key, offset) (((StaticTuple*)key)->items[offset])
73
73
 
74
74
 
75
 
/* C API Functions */
76
 
#define StaticTuple_New_NUM 0
77
 
#define StaticTuple_intern_NUM 1
78
 
#define StaticTuple_CheckExact_NUM 2
79
 
 
80
 
/* Total number of C API Pointers */
81
 
#define StaticTuple_API_pointers 3
 
75
static const char *_C_API_NAME = "_C_API";
82
76
 
83
77
#ifdef STATIC_TUPLE_MODULE
84
78
/* Used when compiling _static_tuple_c.c */
87
81
static StaticTuple * StaticTuple_intern(StaticTuple *self);
88
82
 
89
83
#else
90
 
/* Used by foriegn callers */
91
 
static void **StaticTuple_API;
 
84
/* Used as the foreign api */
92
85
 
93
86
static StaticTuple *(*StaticTuple_New)(Py_ssize_t);
94
87
static StaticTuple *(*StaticTuple_intern)(StaticTuple *);
95
 
#undef StaticTuple_CheckExact
96
 
static int (*StaticTuple_CheckExact)(PyObject *);
 
88
static PyTypeObject *_p_StaticTuple_Type;
 
89
 
 
90
#define StaticTuple_CheckExact(op) (Py_TYPE(op) == _p_StaticTuple_Type)
 
91
static int (*_StaticTuple_CheckExact)(PyObject *);
 
92
 
 
93
 
 
94
static int _import_function(PyObject *module, char *funcname,
 
95
                            void **f, char *signature)
 
96
{
 
97
    PyObject *d = NULL;
 
98
    PyObject *c_obj = NULL;
 
99
    char *desc = NULL;
 
100
 
 
101
    d = PyObject_GetAttrString(module, _C_API_NAME);
 
102
    if (!d) {
 
103
        // PyObject_GetAttrString sets an appropriate exception
 
104
        goto bad;
 
105
    }
 
106
    c_obj = PyDict_GetItemString(d, funcname);
 
107
    if (!c_obj) {
 
108
        // PyDict_GetItemString does not set an exception
 
109
        PyErr_Format(PyExc_AttributeError,
 
110
            "Module %s did not export a function named %s\n",
 
111
            PyModule_GetName(module), funcname);
 
112
        goto bad;
 
113
    }
 
114
    desc = (char *)PyCObject_GetDesc(c_obj);
 
115
    if (!desc || strcmp(desc, signature) != 0) {
 
116
        if (desc == NULL) {
 
117
            desc = "<null>";
 
118
        }
 
119
        PyErr_Format(PyExc_TypeError,
 
120
            "C function %s.%s has wrong signature (expected %s, got %s)",
 
121
                PyModule_GetName(module), funcname, signature, desc);
 
122
        goto bad;
 
123
    }
 
124
    *f = PyCObject_AsVoidPtr(c_obj);
 
125
    fprintf(stderr, "Imported function %s @%x\n", funcname, *f);
 
126
    Py_DECREF(d);
 
127
    return 0;
 
128
bad:
 
129
    fprintf(stderr, "Returning -1\n");
 
130
    Py_XDECREF(d);
 
131
    return -1;
 
132
}
 
133
 
 
134
 
 
135
static PyTypeObject *
 
136
_import_type(PyObject *module, char *class_name)
 
137
{
 
138
    PyObject *type = NULL;
 
139
 
 
140
    type = PyObject_GetAttrString(module, class_name);
 
141
    if (!type) {
 
142
        goto bad;
 
143
    }
 
144
    if (!PyType_Check(type)) {
 
145
        PyErr_Format(PyExc_TypeError,
 
146
            "%s.%s is not a type object",
 
147
            PyModule_GetName(module), class_name);
 
148
        goto bad;
 
149
    }
 
150
    return (PyTypeObject *)type;
 
151
bad:
 
152
    Py_XDECREF(type);
 
153
    return NULL;
 
154
}
97
155
 
98
156
 
99
157
/* Return -1 and set exception on error, 0 on success */
100
158
static int
101
 
import_static_tuple(void)
 
159
import_static_tuple_c(void)
102
160
{
103
 
    PyObject *module = PyImport_ImportModule("bzrlib._static_tuple_c");
104
 
    PyObject *c_api_object;
105
 
 
106
 
    if (module == NULL) {
107
 
        fprintf(stderr, "Failed to find module _static_tuple_c.\n");
108
 
        return -1;
109
 
    }
110
 
    c_api_object = PyObject_GetAttrString(module, "_C_API");
111
 
    if (c_api_object == NULL) {
112
 
        fprintf(stderr, "Failed to find _static_tuple_c._C_API.\n");
113
 
        return -1;
114
 
    }
115
 
    if (!PyCObject_Check(c_api_object)) {
116
 
        fprintf(stderr, "_static_tuple_c._C_API not a CObject.\n");
117
 
        Py_DECREF(c_api_object);
118
 
        return -1;
119
 
    }
120
 
    StaticTuple_API = (void **)PyCObject_AsVoidPtr(c_api_object);
121
 
    StaticTuple_New = StaticTuple_API[StaticTuple_New_NUM];
122
 
    StaticTuple_intern = StaticTuple_API[StaticTuple_intern_NUM];
123
 
    StaticTuple_CheckExact = StaticTuple_API[StaticTuple_CheckExact_NUM];
124
 
    Py_DECREF(c_api_object);
 
161
    /* This is modeled after the implementation in Pyrex, which uses a
 
162
     * dictionary and descriptors, rather than using plain offsets into a
 
163
     * void ** array.
 
164
     */
 
165
    PyObject *module = NULL;
 
166
    
 
167
    module = PyImport_ImportModule("bzrlib._static_tuple_c");
 
168
    if (!module) goto bad;
 
169
    if (_import_function(module, "StaticTuple_New", (void **)&StaticTuple_New,
 
170
                         "StaticTuple *(Py_ssize_t)") < 0)
 
171
        goto bad;
 
172
    if (_import_function(module, "StaticTuple_intern",
 
173
                         (void **)&StaticTuple_intern,
 
174
                         "StaticTuple *(StaticTuple *)") < 0)
 
175
        goto bad;
 
176
    if (_import_function(module, "_StaticTuple_CheckExact",
 
177
                         (void **)&_StaticTuple_CheckExact,
 
178
                         "int(PyObject *)") < 0)
 
179
        goto bad;
 
180
    _p_StaticTuple_Type = _import_type(module, "StaticTuple");
 
181
    if (!_p_StaticTuple_Type) {
 
182
        goto bad;
 
183
    }
 
184
    Py_DECREF(module); 
125
185
    return 0;
 
186
bad:
 
187
    Py_XDECREF(module);
 
188
    return -1;
126
189
}
127
190
 
128
 
#endif
129
 
#endif // _STATIC_TUPLE_H_
 
191
#endif // !STATIC_TUPLE_MODULE
 
192
#endif // !_STATIC_TUPLE_H_