一个函数指针问题。如何有效地与来自C ++类的C API(即GSL)接口? [英] A function pointer issue. How to efficiently interface with C API (ie. GSL) from C++ class?

查看:124
本文介绍了一个函数指针问题。如何有效地与来自C ++类的C API(即GSL)接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题似乎曾经被问过很多次,例如 here1 here2 here3

This question seems to have been asked numerous times before, for example here1, here2 and here3.

我想做的是设置成员<$ C-struct gsl_function 函数

What I am trying to do is, set the member function of the C-Struct gsl_function to a member function of my class.

class MyClass{

    double foo(double x)
    {
        return ...;
    }

    double bar(double x)
    {
        ...
        gsl_function F;
        // Problem I cant do this (compiler error)
        F.function = &(this->foo);
    }
};

第三个 link 上面提供了一个解决方案,我认为它是基于包装器方法描述的 here4

The third link above provides a solution, I think it is based on the wrapper approach described here4.

所以我的问题是我能做得更好。有更容易的方法吗?例如,可能通过使用Boost的函数和绑定对象。

So my question is can I do better. Is there an easier way? For example, possibly by using Boost's function and Bind objects.

我正在考虑使用gsl包装选项,如o2scl。但是有点不相称,因为我可能支付价格后,如果包装不能很好地维护。有什么建议么?

I am weighing up the option of using a gsl wrapper, such as o2scl. But am a bit releuctant as I may pay the price later if the wrapper is not well maintained. Any suggestions?

推荐答案

由于GSL允许您传入任意参数,因此您可以滥用此选项来保存指向所讨论实例的指针。然后使用静态成员函数转发成员函数:

Since GSL allows you to pass in arbitrary parameters, you can abuse this to hold the pointer to the instance under question. Then use a static member function to forward to the member function:

class MyClass
{
    double foo(double x)
    {
       ...
    }
    static double foo_wrapper(double x, void *params)
    {
        return static_cast<MyClass*>(params)->foo(x);
    }

    double bar(double x)
    {
        ...
        gsl_function F;
        F.function=&MyClass::foo_wrapper;
        F.params=this;

        // invoke GSL function passing in F
        ...
    }
};

你能做得更好吗?有更容易的方法吗?不是真的。

Can you do better? Is there an easier way? Not really. Any approach you take will be doing this under the covers somewhere.

但你可以写一个简单的包装器隐藏一些:

But you can write a simple wrapper which hides some of this:

class gsl_function_pp : public gsl_function
{
public:
    gsl_function_pp(boost::function<double(double)> const& func) : _func(func)
    {
        function=&gsl_function_pp::invoke;
        params=this;
    }
private:
    boost::function<double(double)> _func;

    static double invoke(double x, void *params)
    {
        return static_cast<gsl_function_pp*>(params)->_func(x);
    }
};

这应该会给你(可能由于涉及多个延迟而造成中度的性能损失)您将需要:

This should give you (possibly at a moderate performance penalty due to multiple indirections involved) the type of functionality you'd want:

class MyClass
{
    double foo(double x)
    {
        ...
    }

    double bar(double x)
    {
        gsl_function_pp F(boost::bind(&MyClass::foo, this, _1));
        // invoke GSL function passing in F
        ...
    }
};


$ b 对象在GSL可能调用它的整个时间内保持在作用域中。所以,不要尝试在一个函数中设置根查找器/ etc(使用本地gsl_function_pp),返回,然后在另一个执行根查找迭代 - 你会得到崩溃或更糟。

The caveat is that you'll have to ensure that any gsl_function_pp object stays in scope for the entire time that the GSL might invoke it. So, don't try to set up a root finder/etc in one function (using a local gsl_function_pp), return, and then perform root finding iterations in another -- you'll get a crash or worse.

这篇关于一个函数指针问题。如何有效地与来自C ++类的C API(即GSL)接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆