- 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/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!