help-gsl
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-gsl] setting function of gsl_odeiv_system structure to a C++


From: Luke
Subject: Re: [Help-gsl] setting function of gsl_odeiv_system structure to a C++ class member function
Date: Tue, 20 Apr 2010 12:17:20 -0700

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 <address@hidden>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 <address@hidden
>> <mailto:address@hidden>> 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
>>        <address@hidden <mailto:address@hidden>
>>        <mailto:address@hidden <mailto:address@hidden>>> 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
>>        address@hidden <mailto:address@hidden>
>>        <mailto:address@hidden <mailto:address@hidden>>
>>
>>
>>        http://lists.gnu.org/mailman/listinfo/help-gsl
>>
>>
>>
>>
>>
>>
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]