函数指针问题.如何有效地与C API接口(即.GSL)来自C++类

A function pointer issue. How to efficiently interface with C API (ie. GSL) from C++ class?

本文关键字:GSL 来自 C++ 接口 API 问题 指针 有效地 函数      更新时间:2023-10-16

这个问题似乎以前被问过很多次,例如这里1,这里2和这里3。

我正在尝试做的是,将 C-Struct gsl_function的成员function设置为我的类的成员函数。

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);
    }
};

上面的第三个链接提供了一个解决方案,我认为它基于这里描述的包装方法4。

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

我正在权衡使用 gsl 包装器的选项,例如 o2scl。但是我有点不情愿,因为如果包装器维护不好,我可能会稍后付出代价。有什么建议吗?

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

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
        ...
    }
};

你能做得更好吗? 有没有更简单的方法? 没有。 您采取的任何方法都将在某个地方的掩护下执行此操作。

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

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);
    }
};

这应该会给你(由于涉及多个间接寻址,可能会有适度的性能损失)你想要的功能类型:

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
        ...
    }
};

需要注意的是,您必须确保任何gsl_function_pp对象在 GSL 可能调用它的整个时间内都保持在范围内。 因此,不要尝试在一个函数中设置根查找器/等(使用本地gsl_function_pp),返回,然后在另一个函数中执行根查找迭代 - 你会崩溃或更糟。