V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zhouzhou113
V2EX  ›  C

C++调用 gsl gsl_integration.h 积分

  •  
  •   zhouzhou113 · 2018-02-05 09:33:25 +08:00 · 2638 次点击
    这是一个创建于 2502 天前的主题,其中的信息可能已经有所发展或是发生改变。

    ubuntu 下使用 C++编程,调用 gsl 积分库,被积函数作为成员函数,定义如下:

    double planning::f(double x, void * params) {

    double alpha = *(double *)params;
    
    double f = pow(x, 4)*sin(0.3*x + 0.12194239*pow(x, 2));
    
    return f;
    

    }

    在另一个成员函数中拷贝该函数指针以调用积分计算函数,如下:

    void planning::GpsCallback(const GpsImu7661::ivsensorgps::ConstPtr& in) {

    gsl_set_error_handler_off();
    gsl_integration_workspace * w= gsl_integration_workspace_alloc(1000);
    
    double result, error;
    double expected = -4.0;
    double alpha = 1.0;
    
    gsl_function F;
    //*****************************//
    F.function = &f;
    //F.function = &planning::f;
    
    F.params = α
    int fanhui = gsl_integration_qags(&F, 0, 82.16478, 0, 1e-7, 1000, w, &result,&error);
    if (0 == gsl_integration_qags(&F, 0, 82.16478, 0, 1e-7, 1000,w, &result, &error)){
        printf("result          = % .18f\n", result);
        printf("estimated error = % .18f\n", error);
        printf("intervals       = %zu\n", w->size);
    }
    gsl_integration_workspace_free(w);
    

    }

    *下语句报错如下: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.

    百度错误之后修改为 F.function = &planning::f;
    报错变成了:error: cannot convert ‘ double (planning::)(double, void)’ to ‘ double ()(double, void)’ in assignment

    有没有在成员函数中调用过 gsl 函数库的大神,,有什么解决方法吗?

    第 1 条附言  ·  2018-02-05 10:57:37 +08:00
    补充一下下
    planning 是类

    调用的 gsl-2.4 版本库

    gsl_function 来自 gsl_math.h 头文件:
    typedef struct gsl_function_struct gsl_function ;

    包含了以下头文件:
    #include <gsl/gsl_integration.h>
    #include <gsl/gsl_errno.h>
    #include "gsl/gsl_sf_gamma.h"

    不好意思,问题方式不够谨慎,造成困扰。。
    19 条回复    2018-02-06 12:25:17 +08:00
    MeteorCat
        1
    MeteorCat  
       2018-02-05 09:48:38 +08:00 via Android
    planning 是类?如果是的话 F.function = &this->f 作为传递一个内部函数指针是会提示非静态,建议试下直接使用用函数方式,或者把 f 设为静态成员
    MeteorCat
        2
    MeteorCat  
       2018-02-05 09:53:08 +08:00 via Android
    稍等下,我本地测试一下使用方式,看下是否我的方式是否可用
    GeruzoniAnsasu
        3
    GeruzoniAnsasu  
       2018-02-05 10:29:48 +08:00
    F.function = [this](double x,void *param){return f(x,param);};
    或者
    F.function = std::bind(f,this,std::placeholders::_1,std::placeholders::_2);
    GeruzoniAnsasu
        4
    GeruzoniAnsasu  
       2018-02-05 10:43:20 +08:00
    看报错 F.function 应该是个 callable,比如 std::function<double(double,void*)>之类的东西,构造这种东西要么就用 lambda,要么就 functor (重载了()运算符的类),bind 就是用模板构造一个 functor 的方法,但其实现原理相当相当复杂,特别是,如何使 functor 绑定到类成员函数上。用 lambda 就容易理解得多,闭包捕获是世界上所有能进行 functional programing 的语言都通用的语义,把 this 指针捕获进闭包中,然后返回这个闭包。虽说会多出一层显式的调用 wrapping,不过这个 lambda 几乎一定会被优化掉,所以也不用担心这个问题
    MeteorCat
        5
    MeteorCat  
       2018-02-05 10:45:28 +08:00
    3 楼正确,请楼主下次代码能否贴全?我在编写测试时代的时候一堆报错,我以为是我库链接问题,排查了一遍库文件;又以为是我库版本太老了,更新一遍链接库;而且`gsl_function`到底是函数指针还是`std::function`,我认为楼主在提问上面还需要审慎一下
    innoink
        6
    innoink  
       2018-02-05 11:06:16 +08:00 via Android
    非静态成员函数需要一个 this 指针参数,所以实际的函数指针类型要么是 ret classname::func(args)要么是 ret func(this, args),你这么转当然会出错
    解决方法:构造一个严格的 double ()(double, void*)(非成员函数,或者静态成员函数),把你的 f 包装进去。
    justou
        7
    justou  
       2018-02-05 11:15:44 +08:00
    gsl_function 里 function 的签名必须是 double(double, void*)这样的一个纯 C 函数, 不是任何 C++特有的对象.

    struct gsl_function_struct
    {
    double (* function) (double x, void * params);
    void * params;
    };

    typedef struct gsl_function_struct gsl_function ;

    毕竟 gsl 是个 C 库
    innoink
        8
    innoink  
       2018-02-05 11:18:49 +08:00 via Android
    还有,很好奇 double alpha = *(double *)params;这是在干嘛
    justou
        9
    justou  
       2018-02-05 11:24:26 +08:00
    @innoink 把 void* cast 成 double*, 再解引用
    innoink
        10
    innoink  
       2018-02-05 11:25:57 +08:00 via Android
    @justou 但是后面也没用到啊
    justou
        11
    justou  
       2018-02-05 11:28:49 +08:00
    @innoink 他代码问题, 我猜测是 0.12194239 这个参数 →_→
    MeteorCat
        12
    MeteorCat  
       2018-02-05 11:39:15 +08:00
    @innoink 我也感觉,我 llvm 编译的开启`-Wunused-variable`的时候也是爆出这个局部 unused,可能是为了隐私而删除掉代码;说实话,我很讨厌这种提问风格,排查问题还需要我们一起来猜某个变量或者某个函数的作用和功能
    lanry
        13
    lanry  
       2018-02-05 11:41:59 +08:00
    planning::f 定义成 static 方法就 ok 了,看上去也没必要定义成 non-static
    zhouzhou113
        14
    zhouzhou113  
    OP
       2018-02-05 12:04:16 +08:00
    double alpha = *(double *)params;
    double alpha = 1.0;
    F.params = &alpha;
    上三句没有具体用到,
    源码是 c 编写,想运用到 C++的成员函数中,

    除了类 planning,以及这两个成员函数是我自己定义的:
    double planning::f(double x, void * params)
    void planning::GpsCallback(const GpsImu7661::ivsensorgps::ConstPtr& in)

    函数体中的变量函数都对应 gsl 库
    gnaggnoyil
        15
    gnaggnoyil  
       2018-02-05 12:57:49 +08:00
    要是 LZ 对如何把一个 invocable object 给塞进一个函数中这个问题想不明白的话,可以想想标准库中的 std::thread 是怎么实现的……
    innoink
        16
    innoink  
       2018-02-05 21:01:35 +08:00
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    class base{
    public:
    void test()
    {
    printf("void test();\n");
    }
    };
    int main(int argc,char **argv)
    {
    base b;
    typedef void (*cfp)(base *);
    auto x = &base::test;

    cfp c;
    memcpy(&c, &x, sizeof(c));
    c(&b);
    }

    在标准 c++中将非静态成员函数转成 c 风格(即,不是 b.*x 这种形式)的函数指针的唯一方式(如果有其他方式请告诉我)
    innoink
        17
    innoink  
       2018-02-05 21:08:02 +08:00
    @innoink 当然,memcpy 可以改成*((long*)&c) = *((long*)&x);
    Jerrymouse1
        18
    Jerrymouse1  
       2018-02-05 22:08:21 +08:00
    将那个 f 方法定义为 static,应该能行
    hackpro
        19
    hackpro  
       2018-02-06 12:25:17 +08:00
    建议按照
    @GeruzoniAnsasu #3 的做法
    否则你需要解决函数指针和类成员变量的签名问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3858 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 05:30 · PVG 13:30 · LAX 21:30 · JFK 00:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.