Aha. Thanks! I'm coming from the Python world where segfaults are few and far between :)
So, doing it this way doesn't let me have access to class member it seems. I have all the equations of motion (the odes) setup in such a way that the parameters and states are class members (so passing their address wouldn't actually be needed in the function signature if eoms could be a member function). Maybe I could make a friend function or something to handle this aspect of things? ~Luke On Tue, Apr 20, 2010 at 12:06 PM, Daniel Neilson <[email protected]>wrote: > > Luke, > I'd recommend against doing it that way. At the least, the code as you've > written it should segfault; you haven't assigned any value to TorusPtr, so > the dereference "TorusPtr->" will do who knows what. > > Instead, it's cleaner (and, technically faster 'cause there's one less > function call) to just do: > > extern "C" static int eoms(double t, const double x[8], double f[8], void > *params) > { > ... > return GSL_SUCCESS; > } > > Torus::Torus() > { > sys.function = eoms; > } > > -Daniel > > > On 10-04-20 01:01 PM, Luke wrote: > >> Daniel, >> I got it to work doing this, which is sort of what you suggested: >> >> torus.cpp >> // Begin ugly hack >> Torus * TorusPtr; >> >> int TorusEomsWrapper(double t, const double x[8], double f[8], void >> *params) >> { >> return TorusPtr->eoms(t, x, f, params); >> } >> // End ugly hack >> >> Torus::Torus() >> { >> ... >> // can't assign Torus::eoms to sys.function because of C++ calling >> convention for class member functions >> sys.function = TorusEomsWrapper; >> ... >> } >> >> int Torus::eoms(double t, const double x[8], double f[8], void *params) >> { >> ... >> return GSL_SUCCESS; >> } >> >> So this way the code for eoms is part of the class, but isn't used >> directly by GSL, instead it uses the wrapper function... It works, but >> isn't pretty. >> >> Anybody else know of a cleaner way to do it? >> >> ~Luke >> >> On Tue, Apr 20, 2010 at 11:54 AM, Daniel Neilson <[email protected] >> <mailto:[email protected]>> wrote: >> >> >> Luke, >> I actually don't use GSL enough to even know if there are >> developer preferred ways of doing things with it. But, one thing you >> could do is to make your eoms() function a static extern "C" >> function defined only in the source file for your Torus class; that >> is, don't make it a member function of Torus. Then, in the >> constructor for Torus you can set up the function pointer to point >> to that statically defined function. >> >> It'd work, and would still be somewhat encapsulated. >> >> -Daniel >> >> >> On 10-04-20 11:25 AM, Luke wrote: >> >> Daniel, >> Thanks for the link, at least now I understand why the error is >> occurring. I think I can figure out how to use the article's >> suggestions to make things work, but do you (or anybody else) have >> a >> preferred way of doing this sort of thing in GSL? >> Thanks, >> ~Luke >> >> >> On Tue, Apr 20, 2010 at 10:16 AM, Daniel Neilson >> <[email protected] <mailto:[email protected]> >> <mailto:[email protected] <mailto:[email protected]>>> wrote: >> >> >> Hi Luke, >> C++ class member functions have a hidden parameter -- the >> object >> that they're being called on. >> >> So, your function: >> >> int eoms(double t, const double x[8], double f[8], void >> *params); >> >> is actually more like (if it were in C): >> int eoms(Torus *this, double t, const double x[8], double >> f[8], void >> *params); >> >> This might help: >> http://www.parashift.com/c++-faq-lite/pointers-to-members.html >> >> -Daniel >> >> >> On 10-04-20 11:09 AM, Luke wrote: >> >> I am trying to create a C++ class to organize the various >> functions I have >> generated for my system. Here is my class definition: >> >> class >> Torus >> >> { >> >> >> private: >> >> >> const gsl_odeiv_step_type * >> T; >> >> gsl_odeiv_step * >> s; >> >> gsl_odeiv_control * >> c; >> >> gsl_odeiv_evolve * >> e; >> >> gsl_odeiv_system sys; >> public: >> >> >> >> Torus(); >> >> >> ~Torus(); >> >> int eoms(double t, const double x[8], double f[8], >> void >> *params); >> }; >> >> >> Then, in the constructor, I have: >> >> Torus::Torus() >> >> { >> >> t = >> 0.0; >> >> T = >> gsl_odeiv_step_rk8pd; >> >> s = gsl_odeiv_step_alloc(T, >> 8); >> >> c = gsl_odeiv_control_y_new(1e-6, >> 0.0); >> >> e = gsl_odeiv_evolve_alloc(8); >> // Can't get the following to work: >> >> >> //sys = {eoms, NULL, 8, NULL}; // doesn't work >> sys.function =&eoms; // doesn't work >> sys.function = eoms; // doesn't work >> sys.function = this.eoms; // doesn't work >> sys.function = Torus::eoms; // doesn't work >> sys.jacobian = NULL; // works >> sys.dimension = 8; // works >> >> >> sys.params= NULL; // works >> >> >> } >> >> right now, I just have a stub for my eoms function: >> >> int Torus::eoms(double t, const double x[8], double >> f[8], void >> *params) >> { >> return GSL_SUCCESS; >> } >> >> Here are the errors I have receive when I try to compile >> (g++ >> -Wall -lgsl -c >> torus.cpp): >> With sys.function =&eoms; : >> torus.cpp: In constructor ‘Torus::Torus()’: >> torus.cpp:12: error: ISO C++ forbids taking the address >> of an >> unqualified or >> parenthesized non-static member function to form a >> pointer to member >> function. Say ‘&Torus::eoms’ >> torus.cpp:12: error: cannot convert ‘int (Torus::*)(double, >> const double*, >> double*, void*)’ to ‘int (*)(double, const double*, >> double*, >> void*)’ in >> assignment >> >> With sys.function = eoms; : >> torus.cpp: In constructor ‘Torus::Torus()’: >> torus.cpp:12: error: argument of type ‘int >> (Torus::)(double, >> const double*, >> double*, void*)’ does not match ‘int (*)(double, const >> double*, >> double*, >> void*)’ >> >> With sys.function = this.eoms; >> torus.cpp: In constructor ‘Torus::Torus()’: >> torus.cpp:12: error: request for member ‘eoms’ in >> ‘this’, which >> is of >> non-class type ‘Torus* const’ >> >> With sys.function = this->eoms; >> torus.cpp: In constructor ‘Torus::Torus()’: >> torus.cpp:12: error: argument of type ‘int >> (Torus::)(double, >> const double*, >> double*, void*)’ does not match ‘int (*)(double, const >> double*, >> double*, >> void*)’ >> >> With sys.function =&Torus::eoms; >> torus.cpp: In constructor ‘Torus::Torus()’: >> torus.cpp:12: error: cannot convert ‘int (Torus::*)(double, >> const double*, >> double*, void*)’ to ‘int (*)(double, const double*, >> double*, >> void*)’ in >> assignment >> >> Is there something simple that I haven't tried to get this >> assignment to >> work? Or is there a different way I should be doing it? >> >> Thanks, >> ~Luke Peterson >> _______________________________________________ >> Help-gsl mailing list >> [email protected] <mailto:[email protected]> >> <mailto:[email protected] <mailto:[email protected]>> >> >> >> http://lists.gnu.org/mailman/listinfo/help-gsl >> >> >> >> >> >> > _______________________________________________ Help-gsl mailing list [email protected] http://lists.gnu.org/mailman/listinfo/help-gsl
