Re: TMinuit.SetFCN() casting in a class

From: Patrick Decowski (decowski@mit.edu)
Date: Sun Dec 13 1998 - 17:37:54 MET


hi stephen,

you are stumbling into the problem that C++ treats functions to
members (a pointer-to-member) differently than functions to real (C)
functions. there is a way around it, in your code you need to wrap the
code in a "real" function pointer.

you could do the following as an example:

------------TMyClass.cxx---- 
// a global; will point to the object that wants to do the fitting
TMyClass* gThisIsWrappedThis = NULL; 

extern "C" CWrapFit(Double*x, Double_t *par); // the "real" funtion

Double_t CWrapFit(Double_t *x, Double_t *par)
{
  Double_t FitResult;
  // use the global variable to access the object.
  FitResult = gThisIsWrappedThis->Fit(x, par);
  // free global, so that other objects
  //can use it.
  gThisIsWrappedThis = NULL;     

  return FitResult;
}

Double_t TPhMyClass::Fit(....) { .... }

void TPhMyClass:SetupFit()
{
  // assign pointer to this object to the global variable
  // first make sure that no other instant of the same class is trying
  // to fit - that is the price you pay for using globals.
  if(gThisIsWrappedThis == NULL)
    gThisIsWrappedThis = this;
  else
    printf("Can't assign 'this' - other object trying to fit\n");

}


you will have to call SetupFit() before fitting and you will have
to call CWrapFit as the fit function instead of TPhMyClass::Fit. note 
that you will need to add this line to your LinkDef.h:

#pragma link C function CWrapFit;     

so that if you can assign CWrapFit to SetFCN in a macro (if that is 
where you assign it).

hope this helps somewhat,

patrick.


On Sat, 12 Dec 1998, Stephen Bailey wrote:

> 
> Hi.
> 
> I'm trying to use TMinuit and am having problems with the
> casting of my minimization function for SetFCN().  A snippet
> of my code is:
> 
>   void (*pf)(Int_t&, Double_t*, Double_t&, Double_t*, Int_t);
>   pf = MinusLogLikelihood;
>   gMinuit->SetFCN(pf);
> 
> MinusLogLikelihood is a member function of the class DataSet
> which contains the fitting routine from which this code comes.
> My compiler (KAI KCC 3.3e) complains
> 
> KCC -g +K0 -O0 --no_exceptions -fPIC
> -I/usr/products/root/v2_00_13b/include   -c DataSet.cc -o DataSet.o
> "DataSet.cc", line 67: error: a value of type "void (DataSet::*)(Int_t &,
>           Double_t *, Double_t &, Double_t *, Int_t)" cannot be assigned 
> to an
>           entity of type
>           "void (*)(Int_t &, Double_t *, Double_t &, Double_t *, Int_t)"
>     pf = MinusLogLikelihood;
>        ^
> 
> If I make MinusLogLikelihood a regular function not belonging to
> any class, these statements compile fine, but then MinusLogLikelihood
> no longer has any access to the data in my DataSet object.  Even if
> I provided public access functions, it still wouldn't know which DataSet
> object to use.  The example in the tutorial relies upon the data to be
> fit being global.  Can this be avoided?  Does anyone have experience using
> TMinuit from within the context of a class structure with data belonging
> to objects?  I also tried using SetFCN(void *) and the compiler was
> similarly unhappy about my casting.
> 
> Thanks.
> 
> Stephen
> 
> 
> 
> 
> 

-------------------------------------------o-------------------------------
Patrick Decowski                           |
24-504                                     |    Home:      (617)625-9352
Massachusetts Institute of Technology      |    Office:    (617)253-9735
77 Massachusetts Ave                       |    Fax:       (617)253-1755
Cambridge, MA 02139-4307                   |
-------------------------------------------o-------------------------------
http://web.mit.edu/decowski/www/home.html  |    e-mail: decowski@mit.edu
-------------------------------------------o-------------------------------



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:34:41 MET