Hi Gilles, I ran into the same problem. ROOT has a solution for this, which I think isn't very elegant (read Object Oriented). This is I think due to historical reasons (As a relative young HEPer I'm impressed to read in the minuit manual that the program is older than I am!). To my opinion the things is now: TVirtualFitter (basically a wrapper around TMinuit) wants to have a pointer to a function to minimize, i.e. the FCN function. Technically this is inplemented in TMinuit by having a datamember: void (*)(Int_t&npar, Double_t*gin, Double_t&f, Double_t*u, Int_t flag)* fFCN i.e. a pointer to a function which has as arguments (Int_t&npar, Double_t*gin, Double_t&f, Double_t*u, Int_t flag) So with the member function ::SetFCN(void (*)(Int_t&, Double_t*, Double_t&f, Double_t*, Int_t) fcn)) you give a function as argument to set the datamamber fFCN, such that TMinuit can use it. An technical complication is that CINT (as far as I understand) doesn't allow pointers to functions. This is circumvented by having a second SetFCN which takes a pointer to void, i.e. which can be anything. This all works fine if your function is also a interpreted function. (It seems not to if from the interpreter you call a compiled version (see my mail earlier this week). I think this is a bug, but it isn't directly important here.). There is a more serious problem, which is partly a limitation by C++ (but which can't be avoided). You can have pointers to member functions (see B. Stroustrup par 15.5) but they have to be invoked on an object. So in your case you have the pointer to member function: void (DPrecAlign::*)(int,double *,double,double *,int) You can even set a variable which is a pointer to this member function: void (DPrecAlign::*)(int,double *,double,double *,int) pntrToMem = &DPrecAlign::fcn; but you have to use it on a DPrecAlign object, i.e., DPrecAlign* tDPAObj = <something>; (tDPAObj->*pntrToMem)(npar, gin, f, par, flag); The syntax is horrible but this is what it boils down to. The upshot is that a pointer to a member function is not the same thing as a pointer to a normal function. This means you can not use it as a pointer to a member function. This together with the fact that ROOT in interactive mode uses TMinuit::SetFCN(void *); explains your error message (I think.) "Argument of type 'void (DPrecAlign::*)(int,double *,double,double *,int)' could not be converted to 'void *'" The solution to not being able to have a pointer to a member function suggested by ROOT is to instead have a normal (i.e. global) fcn function which is called. In this fcn you have to find out for which original object (i.e. the object which is an instance of the class DPrecAlign) it was called. And than retrieve the information you need to implement fcn. To help you with this TMinuit has the members void SetObjectFit(TObject* obj); and TObject* GetObjectFit(); So before you start you call SetObjectFit(...) with your object and in your global FCN you call GetObjectFit() to retrieve it. Concrete in your case I think the solution is: making a global function: GFForwardDPrecAlignFCN(Int_t& npar, Double_t*gin, Double_t&f, Double_t* par, Int_t flag) { DPrecAlign* tDPAObj = dynamic_cast<DPrecAlign*>(gMinuit->GetObjectFit()); tDPAObj->fcn(npar, gin, f, par, flag); } and make sure you do gMinuit->SetObjectFit(tDPAObj); before you call the fit. This should think work with the (current) ROOT. However, to come back to my first line of this email, I don't think this whole approach is very OO. It is also risky e.g. if you would like to fit 2 objects at the same time. I think a better solution to this problem is to use a functor (i.e. function object) in an analogue way STL algorithms work with predicates (see Chapter 18 Stroustrup). In order for this to work we need a templatized member function. If people are interested I could present the idea (not tested yet) Friday on the ROOT workshop. Ciao, Rutger van der Eijk
This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:18 MET