From d50d9861bc6d5966baf12bd4d0376b190981541b Mon Sep 17 00:00:00 2001 From: Andre Masella Date: Thu, 18 Aug 2022 16:30:55 -0400 Subject: [PATCH 1/2] Make C++ extensions compile with correct compiler Some extension files are C++ but have `.c` extensions. GCC will compile these as C++, but clang will not. --- docs/source/developer/repomap.rst | 4 +-- numba/{_hashtable.c => _hashtable.cpp} | 38 +++++++++++++------------- numba/_hashtable.h | 30 ++++++++++---------- numba/{_typeof.c => _typeof.cpp} | 20 ++++++++------ setup.py | 6 ++-- 5 files changed, 52 insertions(+), 46 deletions(-) rename numba/{_hashtable.c => _hashtable.cpp} (96%) rename numba/{_typeof.c => _typeof.cpp} (98%) diff --git a/docs/source/developer/repomap.rst b/docs/source/developer/repomap.rst index dcf36e6ac0a..1694e80e773 100644 --- a/docs/source/developer/repomap.rst +++ b/docs/source/developer/repomap.rst @@ -201,7 +201,7 @@ with CPython APIs. - :ghfile:`numba/_pymodule.h` - C macros for Python 2/3 portable naming of C API functions - :ghfile:`numba/mviewbuf.c` - Handles Python memoryviews -- :ghfile:`numba/_typeof.{h,c}` - C implementation of type fingerprinting, +- :ghfile:`numba/_typeof.{h,cpp}` - C++ implementation of type fingerprinting, used by dispatcher - :ghfile:`numba/_numba_common.h` - Portable C macro for marking symbols that can be shared between object files, but not outside the @@ -267,7 +267,7 @@ Misc Support Core Python Data Types '''''''''''''''''''''' -- :ghfile:`numba/_hashtable.{h,c}` - Adaptation of the Python 3.7 hash table +- :ghfile:`numba/_hashtable.{h,cpp}` - Adaptation of the Python 3.7 hash table implementation - :ghfile:`numba/cext/dictobject.{h,c}` - C level implementation of typed dictionary diff --git a/numba/_hashtable.c b/numba/_hashtable.cpp similarity index 96% rename from numba/_hashtable.c rename to numba/_hashtable.cpp index 76392f79ebb..c0815b20f20 100644 --- a/numba/_hashtable.c +++ b/numba/_hashtable.cpp @@ -98,19 +98,19 @@ _Py_slist_remove(_Py_slist_t *list, _Py_slist_item_t *previous, list->head = item->next; } -Py_uhash_t +extern "C" Py_uhash_t _Numba_hashtable_hash_int(const void *key) { return (Py_uhash_t)key; } -Py_uhash_t +extern "C" Py_uhash_t _Numba_hashtable_hash_ptr(const void *key) { return (Py_uhash_t)_Py_HashPointer((void *)key); } -int +extern "C" int _Numba_hashtable_compare_direct(const void *key, const _Numba_hashtable_entry_t *entry) { return entry->key == key; @@ -129,7 +129,7 @@ round_size(size_t s) return i; } -_Numba_hashtable_t * +extern "C" _Numba_hashtable_t * _Numba_hashtable_new_full(size_t data_size, size_t init_size, _Numba_hashtable_hash_func hash_func, _Numba_hashtable_compare_func compare_func, @@ -158,7 +158,7 @@ _Numba_hashtable_new_full(size_t data_size, size_t init_size, ht->data_size = data_size; buckets_size = ht->num_buckets * sizeof(ht->buckets[0]); - ht->buckets = alloc.malloc(buckets_size); + ht->buckets = (_Py_slist_t *) alloc.malloc(buckets_size); if (ht->buckets == NULL) { alloc.free(ht); return NULL; @@ -174,7 +174,7 @@ _Numba_hashtable_new_full(size_t data_size, size_t init_size, return ht; } -_Numba_hashtable_t * +extern "C" _Numba_hashtable_t * _Numba_hashtable_new(size_t data_size, _Numba_hashtable_hash_func hash_func, _Numba_hashtable_compare_func compare_func) @@ -184,7 +184,7 @@ _Numba_hashtable_new(size_t data_size, NULL, NULL, NULL, NULL); } -size_t +extern "C" size_t _Numba_hashtable_size(_Numba_hashtable_t *ht) { size_t size; @@ -215,7 +215,7 @@ _Numba_hashtable_size(_Numba_hashtable_t *ht) } #ifdef Py_DEBUG -void +extern "C" void _Numba_hashtable_print_stats(_Numba_hashtable_t *ht) { size_t size; @@ -255,7 +255,7 @@ _Numba_hashtable_print_stats(_Numba_hashtable_t *ht) #endif /* Get an entry. Return NULL if the key does not exist. */ -_Numba_hashtable_entry_t * +extern "C" _Numba_hashtable_entry_t * _Numba_hashtable_get_entry(_Numba_hashtable_t *ht, const void *key) { Py_uhash_t key_hash; @@ -308,7 +308,7 @@ _hashtable_pop_entry(_Numba_hashtable_t *ht, const void *key, void *data, size_t /* Add a new entry to the hash. The key must not be present in the hash table. Return 0 on success, -1 on memory error. */ -int +extern "C" int _Numba_hashtable_set(_Numba_hashtable_t *ht, const void *key, void *data, size_t data_size) { @@ -328,7 +328,7 @@ _Numba_hashtable_set(_Numba_hashtable_t *ht, const void *key, key_hash = ht->hash_func(key); index = key_hash & (ht->num_buckets - 1); - entry = ht->alloc.malloc(HASHTABLE_ITEM_SIZE(ht)); + entry = (_Numba_hashtable_entry_t *) ht->alloc.malloc(HASHTABLE_ITEM_SIZE(ht)); if (entry == NULL) { /* memory allocation failed */ return -1; @@ -350,7 +350,7 @@ _Numba_hashtable_set(_Numba_hashtable_t *ht, const void *key, /* Get data from an entry. Copy entry data into data and return 1 if the entry exists, return 0 if the entry does not exist. */ -int +extern "C" int _Numba_hashtable_get(_Numba_hashtable_t *ht, const void *key, void *data, size_t data_size) { _Numba_hashtable_entry_t *entry; @@ -364,7 +364,7 @@ _Numba_hashtable_get(_Numba_hashtable_t *ht, const void *key, void *data, size_t return 1; } -int +extern "C" int _Numba_hashtable_pop(_Numba_hashtable_t *ht, const void *key, void *data, size_t data_size) { assert(data != NULL); @@ -373,7 +373,7 @@ _Numba_hashtable_pop(_Numba_hashtable_t *ht, const void *key, void *data, size_t } /* Delete an entry. The entry must exist. */ -void +extern "C" void _Numba_hashtable_delete(_Numba_hashtable_t *ht, const void *key) { #ifndef NDEBUG @@ -387,7 +387,7 @@ _Numba_hashtable_delete(_Numba_hashtable_t *ht, const void *key) /* Prototype for a pointer to a function to be called foreach key/value pair in the hash by hashtable_foreach(). Iteration stops if a non-zero value is returned. */ -int +extern "C" int _Numba_hashtable_foreach(_Numba_hashtable_t *ht, int (*func) (_Numba_hashtable_entry_t *entry, void *arg), void *arg) @@ -420,7 +420,7 @@ hashtable_rehash(_Numba_hashtable_t *ht) buckets_size = new_size * sizeof(ht->buckets[0]); old_buckets = ht->buckets; - ht->buckets = ht->alloc.malloc(buckets_size); + ht->buckets = (_Py_slist_t *) ht->alloc.malloc(buckets_size); if (ht->buckets == NULL) { /* cancel rehash on memory allocation failure */ ht->buckets = old_buckets ; @@ -447,7 +447,7 @@ hashtable_rehash(_Numba_hashtable_t *ht) ht->alloc.free(old_buckets); } -void +extern "C" void _Numba_hashtable_clear(_Numba_hashtable_t *ht) { _Numba_hashtable_entry_t *entry, *next; @@ -466,7 +466,7 @@ _Numba_hashtable_clear(_Numba_hashtable_t *ht) hashtable_rehash(ht); } -void +extern "C" void _Numba_hashtable_destroy(_Numba_hashtable_t *ht) { size_t i; @@ -487,7 +487,7 @@ _Numba_hashtable_destroy(_Numba_hashtable_t *ht) } /* Return a copy of the hash table */ -_Numba_hashtable_t * +extern "C" _Numba_hashtable_t * _Numba_hashtable_copy(_Numba_hashtable_t *src) { _Numba_hashtable_t *dst; diff --git a/numba/_hashtable.h b/numba/_hashtable.h index 37430429d87..fbc6d60130d 100644 --- a/numba/_hashtable.h +++ b/numba/_hashtable.h @@ -71,15 +71,15 @@ typedef struct { } _Numba_hashtable_t; /* hash and compare functions for integers and pointers */ -PyAPI_FUNC(Py_uhash_t) _Numba_hashtable_hash_ptr(const void *key); -PyAPI_FUNC(Py_uhash_t) _Numba_hashtable_hash_int(const void *key); -PyAPI_FUNC(int) _Numba_hashtable_compare_direct(const void *key, const _Numba_hashtable_entry_t *entry); +extern "C" PyAPI_FUNC(Py_uhash_t) _Numba_hashtable_hash_ptr(const void *key); +extern "C" PyAPI_FUNC(Py_uhash_t) _Numba_hashtable_hash_int(const void *key); +extern "C" PyAPI_FUNC(int) _Numba_hashtable_compare_direct(const void *key, const _Numba_hashtable_entry_t *entry); -PyAPI_FUNC(_Numba_hashtable_t *) _Numba_hashtable_new( +extern "C" PyAPI_FUNC(_Numba_hashtable_t *) _Numba_hashtable_new( size_t data_size, _Numba_hashtable_hash_func hash_func, _Numba_hashtable_compare_func compare_func); -PyAPI_FUNC(_Numba_hashtable_t *) _Numba_hashtable_new_full( +extern "C" PyAPI_FUNC(_Numba_hashtable_t *) _Numba_hashtable_new_full( size_t data_size, size_t init_size, _Numba_hashtable_hash_func hash_func, @@ -88,36 +88,36 @@ PyAPI_FUNC(_Numba_hashtable_t *) _Numba_hashtable_new_full( _Numba_hashtable_free_data_func free_data_func, _Numba_hashtable_get_data_size_func get_data_size_func, _Numba_hashtable_allocator_t *allocator); -PyAPI_FUNC(_Numba_hashtable_t *) _Numba_hashtable_copy(_Numba_hashtable_t *src); -PyAPI_FUNC(void) _Numba_hashtable_clear(_Numba_hashtable_t *ht); -PyAPI_FUNC(void) _Numba_hashtable_destroy(_Numba_hashtable_t *ht); +extern "C" PyAPI_FUNC(_Numba_hashtable_t *) _Numba_hashtable_copy(_Numba_hashtable_t *src); +extern "C" PyAPI_FUNC(void) _Numba_hashtable_clear(_Numba_hashtable_t *ht); +extern "C" PyAPI_FUNC(void) _Numba_hashtable_destroy(_Numba_hashtable_t *ht); typedef int (*_Numba_hashtable_foreach_func) (_Numba_hashtable_entry_t *entry, void *arg); -PyAPI_FUNC(int) _Numba_hashtable_foreach( +extern "C" PyAPI_FUNC(int) _Numba_hashtable_foreach( _Numba_hashtable_t *ht, _Numba_hashtable_foreach_func func, void *arg); -PyAPI_FUNC(size_t) _Numba_hashtable_size(_Numba_hashtable_t *ht); +extern "C" PyAPI_FUNC(size_t) _Numba_hashtable_size(_Numba_hashtable_t *ht); -PyAPI_FUNC(_Numba_hashtable_entry_t*) _Numba_hashtable_get_entry( +extern "C" PyAPI_FUNC(_Numba_hashtable_entry_t*) _Numba_hashtable_get_entry( _Numba_hashtable_t *ht, const void *key); -PyAPI_FUNC(int) _Numba_hashtable_set( +extern "C" PyAPI_FUNC(int) _Numba_hashtable_set( _Numba_hashtable_t *ht, const void *key, void *data, size_t data_size); -PyAPI_FUNC(int) _Numba_hashtable_get( +extern "C" PyAPI_FUNC(int) _Numba_hashtable_get( _Numba_hashtable_t *ht, const void *key, void *data, size_t data_size); -PyAPI_FUNC(int) _Numba_hashtable_pop( +extern "C" PyAPI_FUNC(int) _Numba_hashtable_pop( _Numba_hashtable_t *ht, const void *key, void *data, size_t data_size); -PyAPI_FUNC(void) _Numba_hashtable_delete( +extern "C" PyAPI_FUNC(void) _Numba_hashtable_delete( _Numba_hashtable_t *ht, const void *key); diff --git a/numba/_typeof.c b/numba/_typeof.cpp similarity index 98% rename from numba/_typeof.c rename to numba/_typeof.cpp index 334ff2b999f..5d56c3b2419 100644 --- a/numba/_typeof.c +++ b/numba/_typeof.cpp @@ -101,9 +101,9 @@ string_writer_ensure(string_writer_t *w, size_t bytes) if (newsize < bytes) newsize = bytes; if (w->buf == w->static_buf) - w->buf = malloc(newsize); + w->buf = (char *) malloc(newsize); else - w->buf = realloc(w->buf, newsize); + w->buf = (char *) realloc(w->buf, newsize); if (w->buf) { w->allocated = newsize; return 0; @@ -842,6 +842,10 @@ int typecode_devicendarray(PyObject *dispatcher, PyObject *ary) int dtype; int ndim; int layout = 0; + PyObject *ndim_obj = nullptr; + PyObject* num_obj = nullptr; + PyObject* dtype_obj = nullptr; + int dtype_num = 0; PyObject* flags = PyObject_GetAttrString(ary, "flags"); if (flags == NULL) @@ -858,7 +862,7 @@ int typecode_devicendarray(PyObject *dispatcher, PyObject *ary) Py_DECREF(flags); - PyObject *ndim_obj = PyObject_GetAttrString(ary, "ndim"); + ndim_obj = PyObject_GetAttrString(ary, "ndim"); if (ndim_obj == NULL) { /* If there's no ndim, try to proceed by clearing the error and using the * fallback. */ @@ -879,14 +883,14 @@ int typecode_devicendarray(PyObject *dispatcher, PyObject *ary) if (ndim <= 0 || ndim > N_NDIM) goto FALLBACK; - PyObject* dtype_obj = PyObject_GetAttrString(ary, "dtype"); + dtype_obj = PyObject_GetAttrString(ary, "dtype"); if (dtype_obj == NULL) { /* No dtype: try the fallback. */ PyErr_Clear(); goto FALLBACK; } - PyObject* num_obj = PyObject_GetAttrString(dtype_obj, "num"); + num_obj = PyObject_GetAttrString(dtype_obj, "num"); Py_DECREF(dtype_obj); if (num_obj == NULL) { @@ -895,7 +899,7 @@ int typecode_devicendarray(PyObject *dispatcher, PyObject *ary) goto FALLBACK; } - int dtype_num = PyLong_AsLong(num_obj); + dtype_num = PyLong_AsLong(num_obj); Py_DECREF(num_obj); if (PyErr_Occurred()) { @@ -934,7 +938,7 @@ int typecode_devicendarray(PyObject *dispatcher, PyObject *ary) return typecode_using_fingerprint(dispatcher, (PyObject *) ary); } -int +extern "C" int typeof_typecode(PyObject *dispatcher, PyObject *val) { PyTypeObject *tyobj = Py_TYPE(val); @@ -1051,7 +1055,7 @@ int init_numpy(void) { * typeof_init(omittedarg_type, typecode_dict) * (called from dispatcher.py to fill in missing information) */ -PyObject * +extern "C" PyObject * typeof_init(PyObject *self, PyObject *args) { PyObject *tmpobj; diff --git a/setup.py b/setup.py index efb943516c9..298b3695f6b 100644 --- a/setup.py +++ b/setup.py @@ -161,12 +161,13 @@ def get_ext_modules(): ext_dispatcher = Extension(name="numba._dispatcher", sources=['numba/_dispatcher.cpp', - 'numba/_typeof.c', - 'numba/_hashtable.c', + 'numba/_typeof.cpp', + 'numba/_hashtable.cpp', 'numba/core/typeconv/typeconv.cpp'], depends=["numba/_pymodule.h", "numba/_typeof.h", "numba/_hashtable.h"], + extra_compile_args=['-std=c++11'], **np_compile_args) ext_helperlib = Extension(name="numba._helperlib", @@ -191,6 +192,7 @@ def get_ext_modules(): sources=["numba/core/typeconv/typeconv.cpp", "numba/core/typeconv/_typeconv.cpp"], depends=["numba/_pymodule.h"], + extra_compile_args=['-std=c++11'], ) ext_np_ufunc = Extension(name="numba.np.ufunc._internal", From 3379a215cde6c9e76f7e35344df1606a5c9f52e4 Mon Sep 17 00:00:00 2001 From: Andre Masella Date: Tue, 13 Sep 2022 08:25:13 -0400 Subject: [PATCH 2/2] Fix pointer formatting As titled Co-authored-by: stuartarchibald --- numba/_typeof.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numba/_typeof.cpp b/numba/_typeof.cpp index 5d56c3b2419..8f32363cc3b 100644 --- a/numba/_typeof.cpp +++ b/numba/_typeof.cpp @@ -843,8 +843,8 @@ int typecode_devicendarray(PyObject *dispatcher, PyObject *ary) int ndim; int layout = 0; PyObject *ndim_obj = nullptr; - PyObject* num_obj = nullptr; - PyObject* dtype_obj = nullptr; + PyObject *num_obj = nullptr; + PyObject *dtype_obj = nullptr; int dtype_num = 0; PyObject* flags = PyObject_GetAttrString(ary, "flags");