- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 C++ 类,它的构造函数中需要一个函数指针 ( float(*myfunction)(vector<float>*)
)
我已经向 Python 公开了一些函数指针。
使用此类的理想方法是这样的:
import mymodule
mymodule.some_class(mymodule.some_function)
所以我像这样告诉 Boost 这个类:
class_<SomeClass>("some_class", init<float(*)(vector<float>*)>);
但我得到:
error: no matching function for call to 'register_shared_ptr1(Sample (*)(std::vector<double, std::allocator<double> >*))'
当我尝试编译它时。
那么,有谁知道如何在不失去函数指针所获得的灵 active 的情况下修复错误(即不回退到指示要调用哪个函数的字符串)?
此外,用 C++ 编写此代码的主要目的是为了速度。因此,如果我仍然能够保留这个好处(函数指针在初始化期间被分配给成员变量,并且稍后将被调用超过一百万次),那就太好了。
最佳答案
好的,所以总的来说,这是一个相当难以回答的问题。问题的根本原因是确实没有与 C 函数指针完全相同的 python 类型。 Python 函数有点接近,但由于某些原因它们的接口(interface)不匹配。
首先,我想提一下从这里包装构造函数的技术: http://wiki.python.org/moin/boost.python/HowTo#namedconstructors.2BAC8factories.28asPythoninitializers.29 。这使您可以为对象编写一个不直接对应于实际 C++ 构造函数的 __init__
函数。另请注意,您可能必须在 boost::python::class_
构造中指定 boost::python::no_init
,然后指定 def
如果您的对象不可默认构造,则稍后会使用真正的 __init__
函数。
回到问题:您通常只想传递一小部分函数吗?在这种情况下,您可以声明一个特殊的枚举(或专用类),对接受枚举的构造函数进行重载,然后使用它来查找真正的函数指针。使用这种方法,您无法直接从 python 中自己调用函数,但它并没有那么糟糕,并且性能与使用真正的函数指针相同。
如果您想提供一种适用于任何 python 可调用的通用方法,事情会变得更加复杂。您必须向 C++ 对象添加一个接受通用仿函数的构造函数,例如使用 boost::function
或 std::tr1::function
。如果需要,您可以替换现有的构造函数,因为函数指针将正确转换为该类型。
因此,假设您已向 SomeClass
添加了 boost::function
构造函数,则应将这些函数添加到 Python 包装代码中:
struct WrapPythonCallable
{
typedef float * result_type;
explicit WrapPythonCallable(const boost::python::object & wrapped)
: wrapped_(wrapped)
{ }
float * operator()(vector<float>* arg) const
{
//Do whatever you need to do to convert into a
//boost::python::object here
boost::python::object arg_as_python_object = /* ... */;
//Call out to python with the object - note that wrapped_
//is callable using an operator() overload, and returns
//a boost::python::object.
//Also, the call can throw boost::python::error_already_set -
//you might want to handle that here.
boost::python::object result_object = wrapped_(arg_as_python_object);
//Do whatever you need to do to extract a float * from result_object,
//maybe using boost::python::extract
float * result = /* ... */;
return result;
}
boost::python::object wrapped_;
};
//This function is the "constructor wrapper" that you'll add to SomeClass.
//Change the return type to match the holder type for SomeClass, like if it's
//held using a shared_ptr.
std::auto_ptr<SomeClass> CreateSomeClassFromPython(
const boost::python::object & callable)
{
return std::auto_ptr<SomeClass>(
new SomeClass(WrapPythonCallable(callable)));
}
//Later, when telling Boost.Python about SomeClass:
class_<SomeClass>("some_class", no_init)
.def("__init__", make_constructor(&CreateSomeClassFromPython));
我省略了有关如何在 Python 之间转换指针的详细信息 - 这显然是您必须解决的问题,因为那里存在对象生命周期问题。
如果您需要调用从 Python 传递给此函数的函数指针,那么您需要在某个时候使用 Boost.Python def
这些函数。第二种方法可以很好地处理这些定义的函数,但调用它们会很慢,因为每次调用对象时都会不必要地在 Python 和 Python 之间进行转换。
要解决此问题,您可以修改 CreateSomeClassFromPython
以识别已知或常见的函数对象,并将它们替换为真正的函数指针。您可以在 C++ 中使用 object1.ptr() == object2.ptr()
比较 Python 对象的身份,相当于 id(object1) == id(object2)
python 。
最后,您当然可以将通用方法与枚举方法结合起来。执行此操作时请注意,boost::python 的重载规则与 C++ 不同,这在处理像 CreateSomeClassFromPython
这样的函数时可能会很麻烦。 Boost.Python 按照定义的顺序测试函数,以查看运行时参数是否可以转换为 C++ 参数类型。因此,CreateSomeClassFromPython 将阻止使用晚于它定义的单参数构造函数,因为它的参数与任何 python 对象匹配。请务必将其放在其他单参数 __init__
函数之后。
如果您发现自己经常做这种事情,那么您可能想看看一般的 boost::function 包装技术(与命名构造函数技术在同一页上提到):http://wiki.python.org/moin/boost.python/HowTo?action=AttachFile&do=view&target=py_boost_function.hpp .
关于python - Boost.Python 函数指针作为类构造函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3641334/
谁能解释一下原因: (define a (lambda() (cons a #f))) (car (a)) ==> procedure ((car (a))) ==> (procedure . #f)
这是 PyBrain 网站的摘录。我了解大部分正在发生的事情,但是一行让我完全难住了。我以前从未在 python 代码中看到过这样的东西。这是整个循环,对于上下文: for c in [0,
我是gradle / groovy的新手。我想创建将做一些事情的自定义任务。我的第一个问题是任务完成时该如何做?我可以覆盖doFirst / doLast闭包吗?也许我可以重写某些在开始和结束时都会执
我刚刚开始评估 MS 企业库。他们使用以下指令来获取实例: var customerDb = EnterpriseLibraryContainer.Current.GetInstance("C
这是我的 if else Ansible 逻辑.. - name: Check certs exist stat: path=/etc/letsencrypt/live/{{ rootDomain
我正在使用construct 2.8 对一些失传已久的 Pascal 程序创建的一些文件的 header 进行逆向工程。 header 由许多不同的记录组成,其中一些是可选的,我不确定顺序是否固定。
我在将 getchar() 的输入放入 char *arr[] 数组时遇到问题。我这样做的原因是因为输入数据(将是一个带有命令行参数的文件)将存储在一个 char 指针数组中以传递给 execvp 函
通常我们不能约束类型参数 T派生自密封类型(例如 struct 类型)。这将毫无意义,因为只有一种类型适合,因此不需要泛型。所以约束如下: where T : string 或: where T :
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
#include using namespace std; class A { private: int m_i; friend int main(int argc, char cons
这个问题在这里已经有了答案: Are there legitimate uses for JavaScript's "with" statement? (33 个答案) 关闭 9 年前。 我有这个代
在this answer我看到了下一个 Bash 结构。 yes "$(< file.txt)" 什么意思 "$(< file.txt)" ? 我明白了 命令替换 - $(command)用命令的结
if (a == 1) //do something else if (a == 2) //do something else if (a == 3) //do somethi
关于构造的快速简单的问题。 我有以下用于将项目添加到 ListView 的代码。 ListViewItem item = new ListViewItem(); item.Text = file; i
我想使用 std::vector 来控制给定的内存。首先,我很确定这不是好的做法,但好奇心占了上风,无论如何我都想知道如何做到这一点。 我遇到的问题是这样的方法: vector getRow(unsi
下面显示了一段简单的javascript: var mystring = ("random","ignored","text","h") + ("ello world") 这个字符串会生成 hello
在 Java 中,创建对象的标准方法是使用 MyClass name = new MyClass(); 我也经常看到构造 new MyClass() { /*stuff goes in here*/
我正在编写 C++ ndarray 类。我需要动态大小和编译时大小已知的数组(分别分配自由存储和分配堆栈)。我想支持从嵌套的 std::initializer_list 进行初始化。 动态大小的没问题
我正在将一个项目从 Visual Studio 2005 转换为 Visual Studio 2008,并提出了上述结构。 using Castle.Core.Resource; using Cast
我想知道我在这里的想法是否正确,我主要针对接口(interface)进行编程,所以我想知道下面的类是否应该通过 DI 注入(inject),或者我应该自己实例化一个类... 注意:这些服务保存在我的核
我是一名优秀的程序员,十分优秀!