带有 std::function<double(std::vector<double>) 回调的 cppyy

Posted

技术标签:

【中文标题】带有 std::function<double(std::vector<double>) 回调的 cppyy【英文标题】:cppyy with std::function<double(std::vector<double>) callback 【发布时间】:2020-04-23 11:33:26 【问题描述】:

我正在使用 cppyy。我想将一个函数传递给我的 C++。 C++ 需要签名函数std::function&lt;double(std::vector&lt;double&gt;)&gt;。我不知道该怎么做。这是错误的最小示例:

import cppyy

# To be passed to C
def callback(x):
  return 10.

cppyy.cppdef("double callback_vector(const std::function<double(std::vector<double>)>& callback, std::vector<double> x)  return callback(x); ")
cppyy.cppdef("double callback(const std::function<double(double)>& callback, std::vector<double> x)  return callback(x[0]); ")

cppyy.gbl.callback(callback, [1]) # works
cppyy.gbl.callback_vector(callback, [1]) # fails

但我发现

Traceback (most recent call last):
  File "test.py", line 11, in <module>
    cppyy.gbl.callback_vector(callback, [1])
TypeError: double ::callback_vector(function<double(std::vector<double> >& callback, vector<double> x) =>
    TypeError: could not convert argument 1

换句话说,使用std::function&lt;double(std::vector&lt;double&gt;)&gt; 会失败,但使用更简单的std::function&lt;double(double)&gt; 签名会有效。

【问题讨论】:

是后端深处的一个解析错误。对于我的一生,我无法设计一个简单的解决方法 b/c 它不断遇到相同的错误。 【参考方案1】:

正如所评论的,问题出在后端深处(一个解析错误),它将std::function 名称破坏为无法识别的东西。它这样做是为了我尝试过的一系列解决方法。

我能想到的最接近的解决方案是:

cppyy.cppdef("""
    struct VecDArg : public std::vector<double> 
        VecDArg(const std::vector<double>& v) : std::vector<double>(v) 
    ;
    double wrap_callback_vector(const std::function<double(VecDArg)>& wrap, const std::vector<double>& x) 
        return callback_vector(wrap, x);
    
""")

cppyy.gbl.callback_vector = cppyy.gbl.wrap_callback_vector
cppyy.gbl.callback_vector(callback, [1])

上述工作的原因是它对后端隐藏了类型名称,从而防止了解析问题。通过从std::vector 派生,Python 类几乎没有更聪明的方法。

编辑:现在已在 repo 中修复。将成为 1.7.0 版的一部分。感谢您的报告!

【讨论】:

谢谢!它似乎正在工作。我对std::vector&lt;double&gt;(std::vector&lt;double&gt;)签名使用了类似的技巧

以上是关于带有 std::function<double(std::vector<double>) 回调的 cppyy的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的线程池有时会抛出 `std::bad_function_call` 或 `double free or corruption (!prev)`

带有非 const 字符串的 C++ lambda 到 std::function 错误

带有赋值运算符和调用运算符的 std::function 并发

带有 std::function 参数的重载运算符

模板函数替换仅在一个参数中未使用std :: function时才起作用

std::function