Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CPlusPlus support #321

Merged
merged 7 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,26 @@ on: [pull_request]

jobs:
main_tests:
name: Main tests
name: Main tests ${{ matrix.os }} ${{ matrix.python-version }} ${{ matrix.compiler }}
runs-on: ${{ matrix.os }}
continue-on-error: true
strategy:
# Duplicate changes to this matrix to 'poc_tests'
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.9', '3.10']
# Possible values: ['2.7', '3.6', '3.7', '3.8', '3.9', '3.10.0-rc.2']
# Possible values: ['2.7', '3.6', '3.7', '3.8', '3.9', '3.10.0-rc.2', 'pypy-3.8']
compiler: [""]
include:
- os: ubuntu-latest
python-version: '3.6'
- os: ubuntu-latest
python-version: '3.7'
- os: ubuntu-latest
python-version: '3.8'
- os: ubuntu-latest
python-version: '3.9'
compiler: 'g++'
## Expected failure
# - os: ubuntu-latest
# python-version: '3.10.0-rc.2'
Expand All @@ -46,6 +50,10 @@ jobs:
- name: Build
run: python -m pip install .

- if: ${{ matrix.compiler }}
# Only set the compiler for the tests, not for the build
run: echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV

- name: Run tests
run: |
python -m pip install pytest pytest-xdist
Expand Down
2 changes: 1 addition & 1 deletion c_test/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CC = gcc
CC ?= gcc
INCLUDE=-I.. -I../hpy/devel/include -I../hpy/debug/src/include
CFLAGS = -O0 -UNDEBUG -g -Wall -Werror -Wfatal-errors $(INCLUDE) -DHPY_UNIVERSAL_ABI

Expand Down
5 changes: 4 additions & 1 deletion hpy/debug/src/include/hpy_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,17 @@ void hpy_debug_close_handle(HPyContext *dctx, HPy dh);
// CPython does for its own built-in modules. But we must use the same
// signature as HPy_MODINIT

// Copied from Python's exports.h
// Copied from Python's exports.h, pyport.h
#ifndef Py_EXPORTED_SYMBOL
#if defined(_WIN32) || defined(__CYGWIN__)
#define Py_EXPORTED_SYMBOL __declspec(dllexport)
#else
#define Py_EXPORTED_SYMBOL __attribute__ ((visibility ("default")))
#endif
#endif
#ifdef ___cplusplus
extern "C"
#endif
Py_EXPORTED_SYMBOL
HPy HPyInit__debug(HPyContext *uctx);

Expand Down
9 changes: 7 additions & 2 deletions hpy/devel/include/hpy/hpymodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,20 @@ typedef struct {
} HPyModuleDef;


#if defined(__cplusplus)
# define HPyMODINIT_FUNC extern "C" Py_EXPORTED_SYMBOL HPy
#else /* __cplusplus */
# define HPyMODINIT_FUNC Py_EXPORTED_SYMBOL HPy
#endif /* __cplusplus */

#ifdef HPY_UNIVERSAL_ABI

// module initialization in the universal case
#define HPy_MODINIT(modname) \
_HPy_HIDDEN HPyContext *_ctx_for_trampolines; \
static HPy init_##modname##_impl(HPyContext *ctx); \
Py_EXPORTED_SYMBOL \
HPy HPyInit_##modname(HPyContext *ctx) \
HPyMODINIT_FUNC \
HPyInit_##modname(HPyContext *ctx) \
{ \
_ctx_for_trampolines = ctx; \
return init_##modname##_impl(ctx); \
Expand Down
24 changes: 24 additions & 0 deletions hpy/devel/include/hpy/inline_helpers.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef HPY_INLINE_HELPERS_H
#define HPY_INLINE_HELPERS_H

#if defined(_MSC_VER)
# include <malloc.h> /* for alloca() */
#endif

HPyAPI_FUNC HPy HPyErr_SetFromErrno(HPyContext *ctx, HPy h_type)
{
return HPyErr_SetFromErrnoWithFilenameObjects(ctx, h_type, HPy_NULL, HPy_NULL);
Expand All @@ -11,4 +15,24 @@ HPyAPI_FUNC HPy HPyErr_SetFromErrnoWithFilenameObject(HPyContext *ctx, HPy h_typ
return HPyErr_SetFromErrnoWithFilenameObjects(ctx, h_type, filename, HPy_NULL);
}

HPyAPI_FUNC HPy HPyTuple_Pack(HPyContext *ctx, HPy_ssize_t n, ...) {
va_list vargs;
HPy_ssize_t i;

if (n == 0) {
return HPyTuple_FromArray(ctx, (HPy*)NULL, n);
}
HPy *array = (HPy *)alloca(n * sizeof(HPy));
va_start(vargs, n);
if (array == NULL) {
va_end(vargs);
return HPy_NULL;
}
for (i = 0; i < n; i++) {
array[i] = va_arg(vargs, HPy);
}
va_end(vargs);
return HPyTuple_FromArray(ctx, array, n);
}

#endif //HPY_INLINE_HELPERS_H
9 changes: 0 additions & 9 deletions hpy/devel/include/hpy/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,6 @@
((void**)data) \
))


/* ~~~ HPyTuple_Pack ~~~
this is just syntactic sugar around HPyTuple_FromArray, to help porting the
exising code which uses PyTuple_Pack
*/

#define HPyTuple_Pack(ctx, n, ...) (HPyTuple_FromArray(ctx, (HPy[]){ __VA_ARGS__ }, n))

/* Rich comparison opcodes */
typedef enum {
HPy_LT = 0,
Expand Down
2 changes: 1 addition & 1 deletion hpy/devel/src/runtime/ctx_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ctx_Module_Create(HPyContext *ctx, HPyModuleDef *hpydef)
// we can't free this memory because it is stitched into moduleobject. We
// just make it immortal for now, eventually we should think whether or
// not to free it if/when we unload the module
PyModuleDef *def = PyMem_Malloc(sizeof(PyModuleDef));
PyModuleDef *def = (PyModuleDef*)PyMem_Malloc(sizeof(PyModuleDef));
if (def == NULL) {
PyErr_NoMemory();
return HPy_NULL;
Expand Down
6 changes: 3 additions & 3 deletions hpy/devel/src/runtime/ctx_tracker.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ ctx_Tracker_New(HPyContext *ctx, HPy_ssize_t capacity)
}
capacity++; // always reserve space for an extra handle, see the docs

hp = malloc(sizeof(_HPyTracker_s));
hp = (_HPyTracker_s*)malloc(sizeof(_HPyTracker_s));
if (hp == NULL) {
HPyErr_NoMemory(ctx);
return _hp2ht(0);
}
hp->handles = calloc(capacity, sizeof(HPy));
hp->handles = (HPy*)calloc(capacity, sizeof(HPy));
if (hp->handles == NULL) {
free(hp);
HPyErr_NoMemory(ctx);
Expand Down Expand Up @@ -118,7 +118,7 @@ tracker_resize(HPyContext *ctx, _HPyTracker_s *hp, HPy_ssize_t capacity)
HPyErr_SetString(ctx, ctx->h_ValueError, "HPyTracker resize would lose handles");
return -1;
}
new_handles = realloc(hp->handles, capacity * sizeof(HPy));
new_handles = (HPy*)realloc(hp->handles, capacity * sizeof(HPy));
if (new_handles == NULL) {
HPyErr_NoMemory(ctx);
return -1;
Expand Down
24 changes: 12 additions & 12 deletions hpy/devel/src/runtime/ctx_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static HPyType_Extra_t *_HPyType_Extra_Alloc(const char *name, bool is_pure)
{
size_t name_size = strlen(name) + 1;
size_t size = offsetof(HPyType_Extra_t, name) + name_size;
HPyType_Extra_t *result = PyMem_Calloc(1, size);
HPyType_Extra_t *result = (HPyType_Extra_t*)PyMem_Calloc(1, size);
if (result == NULL) {
PyErr_NoMemory();
return NULL;
Expand Down Expand Up @@ -248,7 +248,7 @@ create_method_defs(HPyDef *hpydefs[], PyMethodDef *legacy_methods)
HPy_ssize_t total_count = hpymeth_count + legacy_count;

// allocate&fill the result
PyMethodDef *result = PyMem_Calloc(total_count+1, sizeof(PyMethodDef));
PyMethodDef *result = (PyMethodDef*)PyMem_Calloc(total_count+1, sizeof(PyMethodDef));
if (result == NULL) {
PyErr_NoMemory();
return NULL;
Expand Down Expand Up @@ -295,7 +295,7 @@ create_member_defs(HPyDef *hpydefs[], PyMemberDef *legacy_members, HPy_ssize_t b
HPy_ssize_t total_count = hpymember_count + legacy_count;

// allocate&fill the result
PyMemberDef *result = PyMem_Calloc(total_count+1, sizeof(PyMemberDef));
PyMemberDef *result = (PyMemberDef*)PyMem_Calloc(total_count+1, sizeof(PyMemberDef));
if (result == NULL) {
PyErr_NoMemory();
return NULL;
Expand Down Expand Up @@ -342,7 +342,7 @@ create_getset_defs(HPyDef *hpydefs[], PyGetSetDef *legacy_getsets)
HPy_ssize_t total_count = hpygetset_count + legacy_count;

// allocate&fill the result
PyGetSetDef *result = PyMem_Calloc(total_count+1, sizeof(PyGetSetDef));
PyGetSetDef *result = (PyGetSetDef*)PyMem_Calloc(total_count+1, sizeof(PyGetSetDef));
if (result == NULL) {
PyErr_NoMemory();
return NULL;
Expand Down Expand Up @@ -383,7 +383,7 @@ create_slot_defs(HPyType_Spec *hpyspec, HPy_ssize_t base_member_offset,
PyMethodDef *legacy_method_defs = NULL;
PyMemberDef *legacy_member_defs = NULL;
PyGetSetDef *legacy_getset_defs = NULL;
legacy_slots_count(hpyspec->legacy_slots, &legacy_slot_count,
legacy_slots_count((PyType_Slot*)hpyspec->legacy_slots, &legacy_slot_count,
&legacy_method_defs, &legacy_member_defs,
&legacy_getset_defs);
bool needs_dealloc = needs_hpytype_dealloc(hpyspec);
Expand All @@ -400,7 +400,7 @@ create_slot_defs(HPyType_Spec *hpyspec, HPy_ssize_t base_member_offset,

// allocate the result PyType_Slot array
HPy_ssize_t total_slot_count = hpyslot_count + legacy_slot_count;
PyType_Slot *result = PyMem_Calloc(total_slot_count+1, sizeof(PyType_Slot));
PyType_Slot *result = (PyType_Slot*)PyMem_Calloc(total_slot_count+1, sizeof(PyType_Slot));
if (result == NULL) {
PyErr_NoMemory();
return NULL;
Expand All @@ -423,7 +423,7 @@ create_slot_defs(HPyType_Spec *hpyspec, HPy_ssize_t base_member_offset,
}
PyType_Slot *dst = &result[dst_idx++];
dst->slot = hpy_slot_to_cpy_slot(src->slot.slot);
dst->pfunc = src->slot.cpy_trampoline;
dst->pfunc = (void*)src->slot.cpy_trampoline;
}
}

Expand Down Expand Up @@ -474,12 +474,12 @@ create_slot_defs(HPyType_Spec *hpyspec, HPy_ssize_t base_member_offset,

// add a dealloc function, if needed
if (needs_dealloc) {
result[dst_idx++] = (PyType_Slot){Py_tp_dealloc, hpytype_dealloc};
result[dst_idx++] = (PyType_Slot){Py_tp_dealloc, (void*)hpytype_dealloc};
}

// add a tp_clear, if the user provided a tp_traverse
if (has_tp_traverse(hpyspec)) {
result[dst_idx++] = (PyType_Slot){Py_tp_clear, hpytype_clear};
result[dst_idx++] = (PyType_Slot){Py_tp_clear, (void*)hpytype_clear};
}

// add the NULL sentinel at the end
Expand All @@ -505,7 +505,7 @@ create_buffer_procs(HPyType_Spec *hpyspec)
switch (src->slot.slot) {
case HPy_bf_getbuffer:
if (buffer_procs == NULL) {
buffer_procs = PyMem_Calloc(1, sizeof(PyBufferProcs));
buffer_procs = (PyBufferProcs*)PyMem_Calloc(1, sizeof(PyBufferProcs));
if (buffer_procs == NULL) {
PyErr_NoMemory();
return NULL;
Expand All @@ -515,7 +515,7 @@ create_buffer_procs(HPyType_Spec *hpyspec)
break;
case HPy_bf_releasebuffer:
if (buffer_procs == NULL) {
buffer_procs = PyMem_Calloc(1, sizeof(PyBufferProcs));
buffer_procs = (PyBufferProcs*)PyMem_Calloc(1, sizeof(PyBufferProcs));
if (buffer_procs == NULL) {
PyErr_NoMemory();
return NULL;
Expand Down Expand Up @@ -706,7 +706,7 @@ ctx_Type_FromSpec(HPyContext *ctx, HPyType_Spec *hpyspec,
return HPy_NULL;
}

PyType_Spec *spec = PyMem_Calloc(1, sizeof(PyType_Spec));
PyType_Spec *spec = (PyType_Spec*)PyMem_Calloc(1, sizeof(PyType_Spec));
if (spec == NULL) {
PyErr_NoMemory();
return HPy_NULL;
Expand Down
2 changes: 1 addition & 1 deletion test/test_00_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def test_unsupported_signature(self):
.kind = HPyDef_Kind_Meth,
.meth = {
.name = "f",
.signature = 1234,
.signature = (HPyFunc_Signature)1234,
}
};
@EXPORT(f)
Expand Down
3 changes: 2 additions & 1 deletion test/test_cpy_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ def test_many_handles(self):
static HPy f_impl(HPyContext *ctx, HPy self)
{
PyObject *o = PyList_New(0);
Py_ssize_t final_refcount;
Py_ssize_t result = -42;
HPy handles[NUM_HANDLES];
Expand All @@ -185,7 +186,7 @@ def test_many_handles(self):
goto error;
for (i = 0; i < NUM_HANDLES; i++)
HPy_Close(ctx, handles[i]);
Py_ssize_t final_refcount = o->ob_refcnt;
final_refcount = o->ob_refcnt;
result = final_refcount - initial_refcount;
error:
Expand Down
2 changes: 1 addition & 1 deletion test/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def test_with_spec_and_params(self):
{
HPyType_SpecParam param[] = {
{ HPyType_SpecParam_Base, ctx->h_LongType },
{ 0 }
{ (HPyType_SpecParam_Kind)0 }
};
if (!HPyHelpers_AddType(ctx, self, "Dummy", &dummy_spec, param))
{
Expand Down
10 changes: 5 additions & 5 deletions test/test_hpytype.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@ def test_doc_string(self):
mod = self.make_module("""
static HPyType_Spec Dummy_spec = {
.name = "mytest.Dummy",
.doc = "A succinct description.",
.itemsize = 0,
.flags = HPy_TPFLAGS_DEFAULT | HPy_TPFLAGS_BASETYPE,
@IS_LEGACY
.doc = "A succinct description.",
};
@EXPORT_TYPE("Dummy", Dummy_spec)
Expand Down Expand Up @@ -154,8 +154,8 @@ def test_HPyDef_SLOT(self):
};
static HPyType_Spec Dummy_spec = {
.name = "mytest.Dummy",
.defines = Dummy_defines,
@IS_LEGACY
.defines = Dummy_defines,
};
@EXPORT_TYPE("Dummy", Dummy_spec)
Expand Down Expand Up @@ -195,8 +195,8 @@ def test_HPyDef_METH(self):
static HPyType_Spec dummy_type_spec = {
.name = "mytest.Dummy",
.defines = dummy_type_defines,
@IS_LEGACY
.defines = dummy_type_defines,
};
@EXPORT_TYPE("Dummy", dummy_type_spec)
Expand Down Expand Up @@ -734,7 +734,7 @@ def test_specparam_base(self):
{
HPyType_SpecParam param[] = {
{ HPyType_SpecParam_Base, ctx->h_LongType },
{ 0 }
{ (HPyType_SpecParam_Kind)0 }
};
HPy h_Dummy = HPyType_FromSpec(ctx, &Dummy_spec, param);
if (HPy_IsNull(h_Dummy))
Expand Down Expand Up @@ -773,7 +773,7 @@ def test_specparam_basestuple(self):
return;
HPyType_SpecParam param[] = {
{ HPyType_SpecParam_BasesTuple, h_bases },
{ 0 }
{ (HPyType_SpecParam_Kind)0 }
};
HPy h_Dummy = HPyType_FromSpec(ctx, &Dummy_spec, param);
HPy_Close(ctx, h_bases);
Expand Down
Loading