其他分享
首页 > 其他分享> > c-在共享库的类中调用GSL函数

c-在共享库的类中调用GSL函数

作者:互联网

我正在尝试在用于费米气体的c实现工具中建立一个共享库.我正在使用GSL库以数字方式求解函数,并且我的代码运行时没有问题,而没有作为脚本运行,但是尝试将其转换为共享库和类时遇到了问题.

我看过类似的问题:
Q1
Q2
Q3

我是c编程的新手,似乎无法适应我的问题.可能因为我不太了解答案.

我的代码是:

/* Define structure for the GSL-function: chempot_integrand */
struct chempot_integrand_params { double mu; double T; };

double
ChemicalPotential::chempot_integrand (double x, void * params){
    /* Computes the integrand for the integral used to obtain the chemical potential.
     *
     * This is a GSL-function, which are integrated using gsl_integration_qag.
     */

    // Get input parameters.
    struct chempot_integrand_params * p = (struct chempot_integrand_params *) params;
    double mu = p->mu;
    double T = p->T;

    // Initiate output parameters for GSL-function.
    gsl_sf_result_e10 result;
    int status = gsl_sf_exp_e10_e( ( gsl_pow_2(x) - mu ) / T , &result );

    if (status != GSL_SUCCESS){
        printf ("Fault in calculating exponential function.");
    }

    // Return (double) integrand.
    return (gsl_pow_2(x) / ( 1 + result.val * gsl_sf_pow_int(10,result.e10) ));
}

/* Define structure for the GSL-function: chempot_integration */
struct chempot_integral_params { double T; };

double
ChemicalPotential::chempot_integration (double mu, double T){
    /* Computes the integral used to obtain the chemical potential using the integrand: chempot_integrand.
    */

    // Set input parameters for the integrand: chempot_integrand.
    struct chempot_integrand_params params_integrand = { mu, T };

    // Initiate the numerical integration.
    gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000); // Allocate memory for the numerical integration. Can be made larger if neccessary, REMEMBER to change it in the function call: gsl_integration_qag as well.
    double result, error;
    gsl_function F;
    F.function = &ChemicalPotential::chempot_integrand;
    F.params = &params_integrand;

    // Upper limit for integration
    double TOL = 1e-9;
    double upp_lim = - T * gsl_sf_log(TOL) + 10;

    gsl_integration_qag (&F, 0, upp_lim, 1e-12, 1e-12, 1000, 6, w, &result, &error);

    // Free memory used for the integration.
    gsl_integration_workspace_free (w);

    return result;
}

当编译时出现错误

error: cannot convert ‘double (Fermi_Gas::ChemicalPotential::*)(double, void*)’ to ‘double (*)(double, void*)’ 

排队

F.function = &ChemicalPotential::chempot_integrand;

解决方法:

人们一遍又一遍地问这个问题确实很有趣.原因之一可能是所提出的解决方案不容易理解.我一个人在理解和实施它们时遇到了问题. (如您所料,解决方案对我来说不是开箱即用的.)

tlamadon的帮助下,我刚刚找到了一个可能在这里也很有用的解决方案.让我们看看你们的想法.

综上所述,问题在于您有一个包含成员函数的类,您要在该函数上使用GSL库中的内容进行操作.如果GSL界面需要一个

gsl_function F;

see here for a definition.

所以这是示例类:

class MyClass {

    private:
        gsl_f_pars *p;  // not necessary to have as member

    public: 
        double obj(double x, void * pars);  // objective fun
        double GetSolution( void );  
        void setPars( gsl_f_pars * xp ) { p = xp; };
        double getC( void )  ;  // helper fun

};

该练习的目的是为了能够

>启动MyClass测试,
>为其提供参数结构(或编写相应的构造函数),然后
>在其上调用test.GetSolution(),它将返回用于GSL函数的任何内容(obj,根,整数或任何最小值)

现在的诀窍是在struct gsl_f_pars参数中放置一个元素,该元素是指向MyClass的指针.这是结构:

struct gsl_f_pars {
    double a;
    double b;
    double c;
    MyClass * pt_MyClass;
};

最后一步是提供一个包装器,该包装器将在MyClass :: GetSolution()内部调用(包装器是成员函数MyClass :: obj的代表,我们不能仅在类内部使用& obj指向该包装器).该包装器将采用参数struct,取消引用pt_MyClass并评估pt_MyClass的成员obj:

// Wrapper that points to member function
// Trick: MyClass is an element of the gsl_f_pars struct
// so we can tease the value of the objective function out
// of there.
double gslClassWrapper(double x, void * pp) {
    gsl_f_pars *p = (gsl_f_pars *)pp;
    return p->pt_MyClass->obj(x,p);
}

完整示例太长了,无法在此处发布,因此我提出了要点.它是header filecpp file,无论您使用的是GSL还是应该都能工作.编译并运行

g++ MyClass.cpp -lgsl -o test
./test

标签:gsl,c,class,shared-libraries
来源: https://codeday.me/bug/20191009/1880960.html