Skip to content

Commit

Permalink
Use cffi out-of-line API mode #10
Browse files Browse the repository at this point in the history
  • Loading branch information
ifduyue committed Feb 9, 2017
1 parent 2364f2b commit 2977600
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 94 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ include README.rst
include LICENSE
include c-xxhash/xxhash.h
include c-xxhash/xxhash.c
include ffibuild.py
graft tests
global-exclude __pycache__
global-exclude *.py[co]
48 changes: 48 additions & 0 deletions ffibuild.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import cffi

ffi = cffi.FFI()

ffi.set_source(
'_cffi',
'#include "xxhash.h"',
sources=['c-xxhash/xxhash.c'],
include_dirs=['c-xxhash']
)

ffi.cdef('''
#define XXH_VERSION_MAJOR ...
#define XXH_VERSION_MINOR ...
#define XXH_VERSION_RELEASE ...
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
typedef unsigned int XXH32_hash_t;
typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */
XXH32_state_t* XXH32_createState(void);
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
void XXH32_copyState(XXH32_state_t* restrict dst_state, const XXH32_state_t* restrict src_state);
XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed);
XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);
typedef unsigned long long XXH64_hash_t;
typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
XXH64_state_t* XXH64_createState(void);
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
void XXH64_copyState(XXH64_state_t* restrict dst_state, const XXH64_state_t* restrict src_state);
XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr);
''')




if __name__ == '__main__':
ffi.compile()
15 changes: 11 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,23 @@
else:
extra_compile_args = None

setup_requires = ['nose>=1.3.0']
if USE_CPYTHON:
install_requires = None
ext_modules = [
Extension(
'xxhash_cpython',
'cpython',
['xxhash/cpython.c', 'c-xxhash/xxhash.c'],
extra_compile_args=extra_compile_args,
include_dirs=['c-xxhash']
)
]
cffi_modules = None
else:
import xxhash.cffi
ext_modules = [xxhash.cffi.ffibuilder.verifier.get_extension()]
install_requires = ['cffi']
setup_requires.append('cffi')
cffi_modules = ['ffibuild.py:ffi']
ext_modules = None

setup(
name='xxhash',
Expand All @@ -49,7 +54,9 @@
packages=['xxhash'],
ext_package='xxhash',
ext_modules=ext_modules,
setup_requires=["nose>=1.3.0"],
cffi_modules=cffi_modules,
setup_requires=setup_requires,
install_requires=install_requires,
test_suite='nose.collector',
classifiers=[
'Development Status :: 4 - Beta',
Expand Down
2 changes: 1 addition & 1 deletion xxhash/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import absolute_import

try:
from xxhash.xxhash_cpython import xxh32, xxh64, XXHASH_VERSION
from xxhash.cpython import xxh32, xxh64, XXHASH_VERSION
except ImportError:
from xxhash.cffi import xxh32, xxh64, XXHASH_VERSION

Expand Down
52 changes: 4 additions & 48 deletions xxhash/cffi.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,10 @@
from __future__ import absolute_import

import sys
import cffi
import struct
import binascii

PY3 = sys.version_info[0] == 3

ffibuilder = cffi.FFI()
ffibuilder.cdef('''
#define XXH_VERSION_MAJOR ...
#define XXH_VERSION_MINOR ...
#define XXH_VERSION_RELEASE ...
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
typedef unsigned int XXH32_hash_t;
typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */
XXH32_state_t* XXH32_createState(void);
XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
void XXH32_copyState(XXH32_state_t* restrict dst_state, const XXH32_state_t* restrict src_state);
XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed);
XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);
typedef unsigned long long XXH64_hash_t;
typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
XXH64_state_t* XXH64_createState(void);
XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
void XXH64_copyState(XXH64_state_t* restrict dst_state, const XXH64_state_t* restrict src_state);
XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr);
''')


lib = ffibuilder.verify(
'''#include "xxhash.h"''',
modulename='xxhash_cffi',
ext_package='xxhash',
sources=['c-xxhash/xxhash.c'],
include_dirs=['c-xxhash']
)
from xxhash._cffi import ffi, lib

PY3 = sys.version_info[0] == 3

XXHASH_VERSION = "%d.%d.%d" % (lib.XXH_VERSION_MAJOR,
lib.XXH_VERSION_MINOR,
Expand All @@ -57,7 +13,7 @@

class xxh32(object):
def __init__(self, input=None, seed=0):
self.xxhash_state = ffibuilder.gc(lib.XXH32_createState(), lib.XXH32_freeState)
self.xxhash_state = ffi.gc(lib.XXH32_createState(), lib.XXH32_freeState)
self.seed = seed
self.reset()
if input:
Expand Down Expand Up @@ -90,7 +46,7 @@ def copy(self):

class xxh64(object):
def __init__(self, input=None, seed=0):
self.xxhash_state = ffibuilder.gc(lib.XXH64_createState(), lib.XXH64_freeState)
self.xxhash_state = ffi.gc(lib.XXH64_createState(), lib.XXH64_freeState)
self.seed = seed
self.reset()
if input:
Expand Down
48 changes: 7 additions & 41 deletions xxhash/cpython.c
Original file line number Diff line number Diff line change
Expand Up @@ -778,80 +778,46 @@ static PyTypeObject PYXXH64Type = {

/* ref: https://docs.python.org/2/howto/cporting.html */

struct module_state {
PyObject *error;
};

#if PY_MAJOR_VERSION >= 3
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
#else
#define GETSTATE(m) (&_state)
static struct module_state _state;
#endif

static PyMethodDef methods[] = {
{NULL, NULL, 0, NULL}
};

#if PY_MAJOR_VERSION >= 3

static int myextension_traverse(PyObject *m, visitproc visit, void *arg)
{
Py_VISIT(GETSTATE(m)->error);
return 0;
}

static int myextension_clear(PyObject *m)
{
Py_CLEAR(GETSTATE(m)->error);
return 0;
}


static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"xxhash_cpython",
"cpython",
NULL,
sizeof(struct module_state),
-1,
methods,
NULL,
myextension_traverse,
myextension_clear,
NULL,
NULL,
NULL
};

#define INITERROR return NULL

PyObject *PyInit_xxhash_cpython(void)
PyObject *PyInit_cpython(void)

#else
#define INITERROR return

void initxxhash_cpython(void)
void initcpython(void)
#endif
{
PyObject *module;
struct module_state *st;

#if PY_MAJOR_VERSION >= 3
module = PyModule_Create(&moduledef);
#else
module = Py_InitModule("xxhash_cpython", methods);
module = Py_InitModule("cpython", methods);
#endif

if (module == NULL) {
INITERROR;
}

st = GETSTATE(module);

st->error = PyErr_NewException("xxhash_cpython.Error", NULL, NULL);

if (st->error == NULL) {
Py_DECREF(module);
INITERROR;
}

if (PyType_Ready(&PYXXH32Type) < 0) {
INITERROR;
}
Expand Down

0 comments on commit 2977600

Please sign in to comment.