Skip to content

Commit

Permalink
add offset calculations for accessing fields in a C++ struct from num…
Browse files Browse the repository at this point in the history
…ba lowering
  • Loading branch information
wlav committed Jun 26, 2022
1 parent 936f019 commit d05db88
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 13 deletions.
15 changes: 8 additions & 7 deletions python/cppyy/numba_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ def _init_extension():
pass


ir_voidptr = irType.pointer(irType.int(8)) # by convention
ir_voidptr = irType.pointer(irType.int(8)) # by convention
ir_charptr = ir_voidptr
ir_intptr_t = irType.int(cppyy.sizeof('void*')*8)

cppyy_addressof_ptr = None


_numba2cpp = {
nb_types.void : 'void',
nb_types.voidptr : 'void*',
Expand Down Expand Up @@ -269,15 +270,15 @@ def unbox_instance(typ, obj, c):

pobj = c.context.call_function_pointer(c.builder, fp, [obj])

# TODO: the use of create_struct_proxy is (too) slow and probably unnecessary:w
# TODO: the use of create_struct_proxy is (too) slow and probably unnecessary
d = nb_cgu.create_struct_proxy(typ)(c.context, c.builder)
basep = c.builder.bitcast(pobj, ir_charptr)
for f, o in offsets:
pf = c.builder.bitcast(pobj, irType.pointer(ir_ftypes[f]))
pfc = c.builder.gep(basep, [ir.Constant(ir_intptr_t, o)])
pf = c.builder.bitcast(pfc, irType.pointer(ir_ftypes[f]))
setattr(d, f, c.builder.load(pf))

# TODO: after typing, cppyy_addressof_ptr can not fail, so error checking is
# only done b/c of create_struct_proxy(typ), which should go
return nb_ext.NativeValue(d._getvalue(), is_error=c.pyapi.c_api_error())
return nb_ext.NativeValue(d._getvalue(), is_error=None, cleanup=None)

return cnt

Expand Down
13 changes: 7 additions & 6 deletions test/test_numba.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,29 +147,30 @@ def test03_proxy_argument_for_field(self):

cppyy.cppdef(r"""\
struct MyNumbaData1 {
MyNumbaData1(int64_t i) : fField(i) {}
int64_t fField;
MyNumbaData1(int64_t i1, int64_t i2) : fField1(i1), fField2(i2) {}
int64_t fField1;
int64_t fField2;
};""")

def go_slow(a, d):
trace = 0.0
for i in range(a.shape[0]):
trace += d.fField
trace += d.fField1 + d.fField2
return a + trace

@numba.jit(nopython=True)
def go_fast(a, d):
trace = 0.0
for i in range(a.shape[0]):
trace += d.fField
trace += d.fField1 + d.fField2
return a + trace

# note: need a sizable array to outperform given the unboxing overhead
x = np.arange(10000, dtype=np.float64).reshape(100, 100)
d = cppyy.gbl.MyNumbaData1(42)
d = cppyy.gbl.MyNumbaData1(42, 27)

assert((go_fast(x, d) == go_slow(x, d)).all())
#assert self.compare(go_slow, go_fast, 10000, x, d)
assert self.compare(go_slow, go_fast, 10000, x, d)

def test04_proxy_argument_for_method(self):
"""Numba-JITing of a free function taking a proxy argument for method access"""
Expand Down

0 comments on commit d05db88

Please sign in to comment.