Author: Wim Lavrijsen <[email protected]>
Branch: reflex-support
Changeset: r67021:f5894d23c106
Date: 2013-09-19 22:55 -0700
http://bitbucket.org/pypy/pypy/changeset/f5894d23c106/
Log: o) rewrite of TF1 callbacks, now using _cffi_backend o) release gil
on calls into CINT, but lock CINT itself globally
diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py
--- a/pypy/module/cppyy/__init__.py
+++ b/pypy/module/cppyy/__init__.py
@@ -12,6 +12,7 @@
'_template_byname' : 'interp_cppyy.template_byname',
'_std_string_name' : 'interp_cppyy.std_string_name',
'_set_class_generator' : 'interp_cppyy.set_class_generator',
+ '_set_function_generator': 'interp_cppyy.set_function_generator',
'_register_class' : 'interp_cppyy.register_class',
'_is_static' : 'interp_cppyy.is_static',
'CPPInstance' : 'interp_cppyy.W_CPPInstance',
diff --git a/pypy/module/cppyy/capi/cint_capi.py
b/pypy/module/cppyy/capi/cint_capi.py
--- a/pypy/module/cppyy/capi/cint_capi.py
+++ b/pypy/module/cppyy/capi/cint_capi.py
@@ -34,8 +34,8 @@
def identify():
return 'CINT'
-ts_reflect = False
-ts_call = False
+ts_reflect = True
+ts_call = True
ts_memory = False
ts_helper = False
@@ -49,13 +49,15 @@
_cintdll = rdynload.dlopen(ll_libname, rdynload.RTLD_GLOBAL |
rdynload.RTLD_NOW)
with rffi.scoped_str2charp('libCore.so') as ll_libname:
_coredll = rdynload.dlopen(ll_libname, rdynload.RTLD_GLOBAL |
rdynload.RTLD_NOW)
+with rffi.scoped_str2charp('libHist.so') as ll_libname:
+ _coredll = rdynload.dlopen(ll_libname, rdynload.RTLD_GLOBAL |
rdynload.RTLD_NOW)
eci = ExternalCompilationInfo(
separate_module_files=[srcpath.join("cintcwrapper.cxx")],
include_dirs=[incpath] + rootincpath,
includes=["cintcwrapper.h"],
library_dirs=rootlibpath,
- libraries=["Core", "Cint"],
+ libraries=["Hist", "Core", "Cint"],
use_cpp_linker=True,
)
@@ -102,11 +104,12 @@
### TF1 ----------------------------------------------------------------------
class State(object):
def __init__(self, space):
- self.tfn_pyfuncs = {}
+ self.tfn_pyfuncs = []
+ self.tfn_callbacks = []
-_tfn_install = rffi.llexternal(
- "cppyy_tfn_install",
- [rffi.CCHARP, rffi.INT], rffi.LONG,
+_create_tf1 = rffi.llexternal(
+ "cppyy_create_tf1",
+ [rffi.CCHARP, rffi.ULONG, rffi.DOUBLE, rffi.DOUBLE, rffi.INT], C_OBJECT,
releasegil=False,
compilation_info=eci)
@@ -135,15 +138,38 @@
if argc == 6: npar = space.int_w(args_w[5])
# third argument must be a callable python object
- pyfunc = args_w[2]
- if not space.is_true(space.callable(pyfunc)):
+ w_callable = args_w[2]
+ if not space.is_true(space.callable(w_callable)):
raise TypeError("2nd argument is not a valid python callable")
- fid = _tfn_install(funcname, npar)
- state = space.fromcache(State)
- state.tfn_pyfuncs[fid] = pyfunc
- newargs_w = [args_w[1], space.wrap(fid), args_w[3], args_w[4],
space.wrap(npar)]
- except (OperationError, TypeError, IndexError):
+ # generate a pointer to function
+ from pypy.module._cffi_backend import newtype, ctypefunc, func
+
+ c_double = newtype.new_primitive_type(space, 'double')
+ c_doublep = newtype.new_pointer_type(space, c_double)
+
+ # wrap the callable as the signature needs modifying
+ w_ifunc = interp_cppyy.get_interface_func(space, w_callable, npar)
+
+ w_cfunc = ctypefunc.W_CTypeFunc(space, [c_doublep, c_doublep],
c_double, False)
+ w_callback = func.callback(space, w_cfunc, w_ifunc, None)
+ funcaddr = rffi.cast(rffi.ULONG, w_callback.get_closure())
+
+ # so far, so good; leaves on issue: CINT is expecting a wrapper, but
+ # we need the overload that takes a function pointer, which is not in
+ # the dictionary, hence this helper:
+ newinst = _create_tf1(space.str_w(args_w[1]), funcaddr,
+ space.float_w(args_w[3]), space.float_w(args_w[4]), npar)
+
+ from pypy.module.cppyy import interp_cppyy
+ w_instance = interp_cppyy.wrap_cppobject(space, newinst, tf1_class,
+ do_cast=False, python_owns=True,
fresh=True)
+
+ # tie all the life times to the TF1 instance
+ space.setattr(w_instance, space.wrap('_callback'), w_callback)
+
+ return w_instance
+ except (OperationError, TypeError, IndexError), e:
newargs_w = args_w[1:] # drop class
# return control back to the original, unpythonized overload
@@ -404,28 +430,3 @@
if obj is not None:
memory_regulator.unregister(obj)
obj._rawobject = C_NULL_OBJECT
-
-# TFn callback (as above: needs better solution, but this is for CINT only)
-# TODO: it actually can fail ...
-@cpython_api([rffi.LONG, rffi.INT, rffi.DOUBLEP, rffi.DOUBLEP], rffi.DOUBLE,
error=CANNOT_FAIL)
-def cppyy_tfn_callback(space, idx, npar, a0, a1):
- state = space.fromcache(State)
- pyfunc = state.tfn_pyfuncs[idx]
- npar = int(npar)
-
- from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
- from pypy.module._rawffi.array import W_Array
- arr = space.interp_w(W_Array, unpack_simple_shape(space, space.wrap('d')))
- address = rffi.cast(rffi.ULONG, a0)
- arg0 = arr.fromaddress(space, address, 4)
- try:
- if npar != 0:
- address = rffi.cast(rffi.ULONG, a1)
- arg1 = arr.fromaddress(space, address, npar)
- result = space.call_function(pyfunc, arg0, arg1)
- else:
- result = space.call_function(pyfunc, arg0)
- dresult = space.float_w(result)
- except Exception:
- dresult = -1.; # TODO: error handling here ..
- return dresult
diff --git a/pypy/module/cppyy/include/cintcwrapper.h
b/pypy/module/cppyy/include/cintcwrapper.h
--- a/pypy/module/cppyy/include/cintcwrapper.h
+++ b/pypy/module/cppyy/include/cintcwrapper.h
@@ -11,7 +11,8 @@
void* cppyy_load_dictionary(const char* lib_name);
/* pythonization helpers */
- long cppyy_tfn_install(const char* funcname, int npar);
+ cppyy_object_t cppyy_create_tf1(const char* funcname, unsigned long
address,
+ double xmin, double xmax, int npar);
cppyy_object_t cppyy_ttree_Branch(
void* vtree, const char* branchname, const char* classname,
diff --git a/pypy/module/cppyy/interp_cppyy.py
b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -101,6 +101,11 @@
state = space.fromcache(State)
state.w_clgen_callback = w_callback
+@unwrap_spec(w_callback=W_Root)
+def set_function_generator(space, w_callback):
+ state = space.fromcache(State)
+ state.w_fngen_callback = w_callback
+
def register_class(space, w_pycppclass):
w_cppclass = space.findattr(w_pycppclass, space.wrap("_cpp_proxy"))
cppclass = space.interp_w(W_CPPClass, w_cppclass, can_be_None=False)
@@ -1137,6 +1142,10 @@
w_pycppclass = space.call_function(state.w_clgen_callback,
space.wrap(final_name))
return w_pycppclass
+def get_interface_func(space, w_callable, npar):
+ state = space.fromcache(State)
+ return space.call_function(state.w_fngen_callback, w_callable,
space.wrap(npar))
+
def wrap_cppobject(space, rawobject, cppclass,
do_cast=True, python_owns=False, is_ref=False, fresh=False):
rawobject = rffi.cast(capi.C_OBJECT, rawobject)
diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py
--- a/pypy/module/cppyy/pythonify.py
+++ b/pypy/module/cppyy/pythonify.py
@@ -55,6 +55,19 @@
def clgen_callback(name):
return get_pycppclass(name)
+def fngen_callback(func, npar): # todo, some kind of arg transform spec
+ if npar == 0:
+ def wrapper(a0, a1):
+ la0 = [a0[0], a0[1], a0[2], a0[3]]
+ return func(la0)
+ return wrapper
+ else:
+ def wrapper(a0, a1):
+ la0 = [a0[0], a0[1], a0[2], a0[3]]
+ la1 = [a1[i] for i in range(npar)]
+ return func(la0, la1)
+ return wrapper
+
def make_static_function(func_name, cppol):
def function(*args):
@@ -416,6 +429,9 @@
# class generator callback
cppyy._set_class_generator(clgen_callback)
+ # function generator callback
+ cppyy._set_function_generator(fngen_callback)
+
# user interface objects (note the two-step of not calling scope_byname
here:
# creation of global functions may cause the creation of classes in the
global
# namespace, so gbl must exist at that point to cache them)
diff --git a/pypy/module/cppyy/src/cintcwrapper.cxx
b/pypy/module/cppyy/src/cintcwrapper.cxx
--- a/pypy/module/cppyy/src/cintcwrapper.cxx
+++ b/pypy/module/cppyy/src/cintcwrapper.cxx
@@ -25,6 +25,7 @@
// for pythonization
#include "TTree.h"
#include "TBranch.h"
+#include "TF1.h"
#include "TString.h"
#include "Api.h"
@@ -59,12 +60,9 @@
TList* fAllPubMethod; //all public methods (including from
base classes)
};
-// memory regulation (cppyy_recursive_remove is generated a la cpyext capi
calls)
+// memory regulation (cppyy_recursive_remove is generated as a cpyext capi
call)
extern "C" void cppyy_recursive_remove(void*);
-// TFN callback helper (generated a la cpyext capi calls)
-extern "C" double cppyy_tfn_callback(long, int, double*, double*);
-
class Cppyy_MemoryRegulator : public TObject {
public:
virtual void RecursiveRemove(TObject* object) {
@@ -240,6 +238,7 @@
/* name to opaque C++ scope representation -------------------------------- */
int cppyy_num_scopes(cppyy_scope_t handle) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass()) {
/* not supported as CINT does not store classes hierarchically */
@@ -249,6 +248,7 @@
}
char* cppyy_scope_name(cppyy_scope_t handle, int iscope) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass()) {
/* not supported as CINT does not store classes hierarchically */
@@ -262,6 +262,7 @@
}
char* cppyy_resolve_name(const char* cppitem_name) {
+ R__LOCKGUARD2(gCINTMutex);
std::string tname = cppitem_name;
// global namespace?
@@ -294,6 +295,8 @@
}
cppyy_scope_t cppyy_get_scope(const char* scope_name) {
+ R__LOCKGUARD2(gCINTMutex);
+
// CINT still has trouble with std:: sometimes ...
if (strncmp(scope_name, "std::", 5) == 0)
scope_name = &scope_name[5];
@@ -323,6 +326,8 @@
}
cppyy_type_t cppyy_get_template(const char* template_name) {
+ R__LOCKGUARD2(gCINTMutex);
+
ClassRefIndices_t::iterator icr = g_classref_indices.find(template_name);
if (icr != g_classref_indices.end())
return (cppyy_type_t)icr->second;
@@ -342,6 +347,7 @@
}
cppyy_type_t cppyy_actual_class(cppyy_type_t klass, cppyy_object_t obj) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(klass);
TClass* clActual = cr->GetActualClass( (void*)obj );
if (clActual && clActual != cr.GetClass()) {
@@ -354,6 +360,7 @@
/* memory management ------------------------------------------------------ */
cppyy_object_t cppyy_allocate(cppyy_type_t handle) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
return (cppyy_object_t)malloc(cr->Size());
}
@@ -363,6 +370,7 @@
}
void cppyy_destruct(cppyy_type_t handle, cppyy_object_t self) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
cr->Destructor((void*)self, true);
}
@@ -372,6 +380,8 @@
static inline G__value cppyy_call_T(cppyy_method_t method,
cppyy_object_t self, int nargs, void* args) {
+ R__LOCKGUARD2(gCINTMutex);
+
G__param* libp = (G__param*)((char*)args - offsetof(G__param, para));
assert(libp->paran == nargs);
fixup_args(libp);
@@ -469,6 +479,7 @@
}
char* cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs,
void* args) {
+ R__LOCKGUARD2(gCINTMutex);
G__value result = cppyy_call_T(method, self, nargs, args);
G__pop_tempobject_nodel();
if (result.ref && *(long*)result.ref) {
@@ -480,6 +491,7 @@
}
cppyy_object_t cppyy_constructor(cppyy_method_t method, cppyy_type_t handle,
int nargs, void* args) {
+ R__LOCKGUARD2(gCINTMutex);
cppyy_object_t self = (cppyy_object_t)NULL;
if ((InterpretedFuncs_t::size_type)method >= g_interpreted.size()) {
G__setgvp((long)G__PVOID);
@@ -496,6 +508,7 @@
cppyy_object_t cppyy_call_o(cppyy_type_t method, cppyy_object_t self, int
nargs, void* args,
cppyy_type_t /*result_type*/ ) {
+ R__LOCKGUARD2(gCINTMutex);
G__value result = cppyy_call_T(method, self, nargs, args);
G__pop_tempobject_nodel();
return G__int(result);
@@ -532,6 +545,7 @@
/* scope reflection information ------------------------------------------- */
int cppyy_is_namespace(cppyy_scope_t handle) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass() && cr->GetClassInfo())
return cr->Property() & G__BIT_ISNAMESPACE;
@@ -541,6 +555,7 @@
}
int cppyy_is_enum(const char* type_name) {
+ R__LOCKGUARD2(gCINTMutex);
G__TypeInfo ti(type_name);
return (ti.Property() & G__BIT_ISENUM);
}
@@ -548,6 +563,7 @@
/* type/class reflection information -------------------------------------- */
char* cppyy_final_name(cppyy_type_t handle) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass() && cr->GetClassInfo()) {
std::string true_name = G__TypeInfo(cr->GetName()).TrueName();
@@ -560,6 +576,7 @@
}
char* cppyy_scoped_final_name(cppyy_type_t handle) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass() && cr->GetClassInfo()) {
std::string true_name = G__TypeInfo(cr->GetName()).TrueName();
@@ -575,6 +592,7 @@
}
int cppyy_num_bases(cppyy_type_t handle) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass() && cr->GetListOfBases() != 0)
return cr->GetListOfBases()->GetSize();
@@ -582,12 +600,14 @@
}
char* cppyy_base_name(cppyy_type_t handle, int base_index) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
TBaseClass* b = (TBaseClass*)cr->GetListOfBases()->At(base_index);
return type_cppstring_to_cstring(b->GetName());
}
int cppyy_is_subtype(cppyy_type_t derived_handle, cppyy_type_t base_handle) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& derived_type = type_from_handle(derived_handle);
TClassRef& base_type = type_from_handle(base_handle);
return derived_type->GetBaseClass(base_type) != 0;
@@ -595,6 +615,8 @@
size_t cppyy_base_offset(cppyy_type_t derived_handle, cppyy_type_t base_handle,
cppyy_object_t address, int /* direction */) {
+ R__LOCKGUARD2(gCINTMutex);
+
// WARNING: CINT can not handle actual dynamic casts!
TClassRef& derived_type = type_from_handle(derived_handle);
TClassRef& base_type = type_from_handle(base_handle);
@@ -626,6 +648,7 @@
/* method/function reflection information --------------------------------- */
int cppyy_num_methods(cppyy_scope_t handle) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass() && cr->GetListOfMethods())
return cr->GetListOfMethods()->GetSize();
@@ -648,6 +671,7 @@
}
cppyy_index_t cppyy_method_index_at(cppyy_scope_t handle, int imeth) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass())
return (cppyy_index_t)imeth;
@@ -655,6 +679,8 @@
}
cppyy_index_t* cppyy_method_indices_from_name(cppyy_scope_t handle, const
char* name) {
+ R__LOCKGUARD2(gCINTMutex);
+
std::vector<cppyy_index_t> result;
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass()) {
@@ -694,6 +720,7 @@
char* cppyy_method_name(cppyy_scope_t handle, cppyy_index_t idx) {
+ R__LOCKGUARD2(gCINTMutex);
TFunction* f = type_get_method(handle, idx);
std::string name = f->GetName();
TClassRef& cr = type_from_handle(handle);
@@ -705,6 +732,7 @@
}
char* cppyy_method_result_type(cppyy_scope_t handle, cppyy_index_t idx) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass() && cppyy_is_constructor(handle, idx))
return cppstring_to_cstring("constructor");
@@ -713,16 +741,19 @@
}
int cppyy_method_num_args(cppyy_scope_t handle, cppyy_index_t idx) {
+ R__LOCKGUARD2(gCINTMutex);
TFunction* f = type_get_method(handle, idx);
return f->GetNargs();
}
int cppyy_method_req_args(cppyy_scope_t handle, cppyy_index_t idx) {
+ R__LOCKGUARD2(gCINTMutex);
TFunction* f = type_get_method(handle, idx);
return f->GetNargs() - f->GetNargsOpt();
}
char* cppyy_method_arg_type(cppyy_scope_t handle, cppyy_index_t idx, int
arg_index) {
+ R__LOCKGUARD2(gCINTMutex);
TFunction* f = type_get_method(handle, idx);
TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At(arg_index);
return type_cppstring_to_cstring(arg->GetFullTypeName());
@@ -734,6 +765,7 @@
}
char* cppyy_method_signature(cppyy_scope_t handle, cppyy_index_t idx) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
TFunction* f = type_get_method(handle, idx);
std::ostringstream sig;
@@ -753,6 +785,7 @@
int cppyy_method_is_template(cppyy_scope_t handle, cppyy_index_t idx) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
TFunction* f = type_get_method(handle, idx);
std::string name = f->GetName();
@@ -766,6 +799,7 @@
char* cppyy_method_template_arg_name(
cppyy_scope_t handle, cppyy_index_t idx, cppyy_index_t /*iarg*/) {
+ R__LOCKGUARD2(gCINTMutex);
// TODO: return only the name for the requested arg
TClassRef& cr = type_from_handle(handle);
TFunction* f = type_get_method(handle, idx);
@@ -776,6 +810,8 @@
cppyy_method_t cppyy_get_method(cppyy_scope_t handle, cppyy_index_t idx) {
+ R__LOCKGUARD2(gCINTMutex);
+
TClassRef& cr = type_from_handle(handle);
TFunction* f = type_get_method(handle, idx);
if (cr && cr.GetClass() && !cr->IsLoaded()) {
@@ -800,6 +836,8 @@
}
cppyy_index_t cppyy_get_global_operator(cppyy_scope_t scope, cppyy_scope_t lc,
cppyy_scope_t rc, const char* op) {
+ R__LOCKGUARD2(gCINTMutex);
+
TClassRef& lccr = type_from_handle(lc);
TClassRef& rccr = type_from_handle(rc);
@@ -831,12 +869,14 @@
/* method properties ----------------------------------------------------- */
int cppyy_is_constructor(cppyy_type_t handle, cppyy_index_t idx) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
TMethod* m = (TMethod*)cr->GetListOfMethods()->At(idx);
return strcmp(m->GetName(), ((G__ClassInfo*)cr->GetClassInfo())->Name())
== 0;
}
int cppyy_is_staticmethod(cppyy_type_t handle, cppyy_index_t idx) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
TMethod* m = (TMethod*)cr->GetListOfMethods()->At(idx);
return m->Property() & G__BIT_ISSTATIC;
@@ -845,6 +885,8 @@
/* data member reflection information ------------------------------------- */
int cppyy_num_datamembers(cppyy_scope_t handle) {
+ R__LOCKGUARD2(gCINTMutex);
+
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass() && cr->GetListOfDataMembers())
return cr->GetListOfDataMembers()->GetSize();
@@ -867,6 +909,8 @@
}
char* cppyy_datamember_name(cppyy_scope_t handle, int datamember_index) {
+ R__LOCKGUARD2(gCINTMutex);
+
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass()) {
TDataMember* m =
(TDataMember*)cr->GetListOfDataMembers()->At(datamember_index);
@@ -877,6 +921,8 @@
}
char* cppyy_datamember_type(cppyy_scope_t handle, int datamember_index) {
+ R__LOCKGUARD2(gCINTMutex);
+
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass()) {
TDataMember* m =
(TDataMember*)cr->GetListOfDataMembers()->At(datamember_index);
@@ -895,6 +941,7 @@
}
size_t cppyy_datamember_offset(cppyy_scope_t handle, int datamember_index) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass()) {
TDataMember* m =
(TDataMember*)cr->GetListOfDataMembers()->At(datamember_index);
@@ -905,6 +952,8 @@
}
int cppyy_datamember_index(cppyy_scope_t handle, const char* name) {
+ R__LOCKGUARD2(gCINTMutex);
+
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass()) {
// called from updates; add a hard reset as the code itself caches in
@@ -940,6 +989,7 @@
/* data member properties ------------------------------------------------ */
int cppyy_is_publicdata(cppyy_scope_t handle, int datamember_index) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass()) {
TDataMember* m =
(TDataMember*)cr->GetListOfDataMembers()->At(datamember_index);
@@ -949,6 +999,7 @@
}
int cppyy_is_staticdata(cppyy_scope_t handle, int datamember_index) {
+ R__LOCKGUARD2(gCINTMutex);
TClassRef& cr = type_from_handle(handle);
if (cr.GetClass()) {
TDataMember* m =
(TDataMember*)cr->GetListOfDataMembers()->At(datamember_index);
@@ -981,6 +1032,7 @@
void* cppyy_load_dictionary(const char* lib_name) {
+ R__LOCKGUARD2(gCINTMutex);
if (0 <= gSystem->Load(lib_name))
return (void*)1;
return (void*)0;
@@ -988,66 +1040,11 @@
/* pythonization helpers -------------------------------------------------- */
-static std::map<long, std::pair<long, int> > s_tagnum2fid;
+typedef double (*tfn_callback)(double*, double*);
-static int TFNPyCallback(G__value* res, G__CONST char*, struct G__param* libp,
int hash) {
- // This is a generic CINT-installable TFN (with N=1,2,3) callback (used to
factor
- // out some common code), to allow TFN to call back into python.
-
- std::map<long, std::pair<long, int> >::iterator it =
s_tagnum2fid.find(G__value_get_tagnum(res));
- if (it == s_tagnum2fid.end()) {
- // TODO: report error here
- return 0;
- }
-
- const std::pair<long, int>& fid_and_npar = it->second;
-
- // callback (defined in cint_capi.py)
- double* a0 = (double*)G__int(libp->para[0]);
- double* a1 = (double*)(fid_and_npar.second ? G__int(libp->para[1]) : 0);
- double d = cppyy_tfn_callback(fid_and_npar.first, fid_and_npar.second, a0,
a1);
-
- // translate result (TODO: error checking)
- G__letdouble(res, 100, d);
- return (1 || hash || res || libp);
-}
-
-long cppyy_tfn_install(const char* funcname, int npar) {
- // make a new function placeholder known to CINT
- static Long_t s_fid = (Long_t)cppyy_tfn_install; // ensures no user
function lives there
- ++s_fid;
-
- const char* signature = "D - - 0 - - D - - 0 - -";
-
- // create a return type (typically masked/wrapped by a TPyReturn) for the
method
- G__linked_taginfo pti;
- pti.tagnum = -1;
- pti.tagtype = 'c';
- std::string tagname("::py_"); // used as a buffer
- tagname += funcname;
- pti.tagname = tagname.c_str();
- int tagnum = G__get_linked_tagnum(&pti); // creates entry for new
names
-
- // for free functions, add to global scope and add lookup through tp2f
- // setup a connection between the pointer and the name
- Long_t hash = 0, len = 0;
- G__hash(funcname, hash, len);
- G__lastifuncposition();
- G__memfunc_setup(funcname, hash, (G__InterfaceMethod)&TFNPyCallback,
- tagnum, tagnum, tagnum, 0, 2, 0, 1, 0, signature,
- (char*)0, (void*)s_fid, 0);
- G__resetifuncposition();
-
- // setup a name in the global namespace (does not result in calls, so the
signature
- // does not matter; but it makes subsequent GetMethod() calls work)
- G__MethodInfo meth = G__ClassInfo().AddMethod(
- funcname, funcname, signature, 1, 0, (void*)&TFNPyCallback);
-
- // store mapping so that the callback can find it
- s_tagnum2fid[tagnum] = std::make_pair(s_fid, npar);
-
- // hard to check result ... assume ok
- return s_fid;
+cppyy_object_t cppyy_create_tf1(const char* funcname, unsigned long address,
+ double xmin, double xmax, int npar) {
+ return (cppyy_object_t)new TF1(funcname, (tfn_callback)address, xmin,
xmax, npar);
}
cppyy_object_t cppyy_ttree_Branch(void* vtree, const char* branchname, const
char* classname,
diff --git a/pypy/module/cppyy/test/test_cint.py
b/pypy/module/cppyy/test/test_cint.py
--- a/pypy/module/cppyy/test/test_cint.py
+++ b/pypy/module/cppyy/test/test_cint.py
@@ -456,6 +456,8 @@
assert f.Eval(0.5) == 0.5
+ del f # force here, to prevent leak-check complaints
+
def test02_callable_object_callback(self):
"""Test callback of a python callable object"""
@@ -472,6 +474,8 @@
assert f.Eval(-0.1) == 4.8
assert f.Eval(1.3) == 7.6
+ del f # force here, to prevent leak-check complaints
+
def test03_fit_with_python_gaussian(self):
"""Test fitting with a python global function"""
@@ -507,6 +511,8 @@
assert round(result[1] - 0., 1) == 0 # mean
assert round(result[2] - 1., 1) == 0 # s.d.
+ del f # force here, to prevent leak-check complaints
+
class AppTestSURPLUS:
spaceconfig = dict(usemodules=['cppyy', '_rawffi', '_ffi', 'itertools'])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit