我正在尝试创建一个很好的接口,通过Python在我的游戏引擎中进行HTTP调用,但是我遇到了一些问题。在
我有一个函数,get_async
,它为指定的URL启动一个curl请求。函数在http_manager
类中定义,如下所示:
struct http_manager
{
typedef function<void(boost::shared_ptr<http_response>)> response_callback_type;
typedef function<void(size_t)> write_callback_type;
void get_async(
const string& url,
const http_headers_type& headers = http_headers_type(),
const http_data_type& data = http_data_type(),
response_callback_type on_response = nullptr,
write_callback_type on_write = nullptr
);
};
我能够在Python中成功地进行此调用:
^{pr2}$不过,我想打个电话:
http.get_async('http://www.google.ca', on_response=f)
这里的关键是,我希望通过名称显式指定参数,并让所有其他参数都是默认值,就像在常规Python中一样。在
不幸的是,当我这样做时,我从Python返回了以下错误:
ArgumentError: Python argument types in
HttpManager.get_async(HttpManager, str)
did not match C++ signature:
get_async(struct naga::http_manager {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > url)
get_async(struct naga::http_manager {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > url, class std::vector<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > headers)
get_async(struct naga::http_manager {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > url, class std::vector<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > headers, class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > data)
get_async(struct naga::http_manager {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > url, class std::vector<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > headers, class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > data, class std::function<void __cdecl(class boost::shared_ptr<struct naga::http_response>)> on_response)
get_async(struct naga::http_manager {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > url, class std::vector<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > headers, class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > > data, class std::function<void __cdecl(class boost::shared_ptr<struct naga::http_response>)> on_response, class std::function<void __cdecl(unsigned int)> on_write)
当我清楚地传递3个参数(self
,url
和{HttpManager.get_async(HttpManager, str)
)。在
以下是我的BOOST_PYTHON_MODULE
块中的相关位:
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(http_manager_get_async_overloads, http_manager::get_async, 1, 5)
class_<http_manager, noncopyable>("HttpManager", no_init)
.def("get_async", &http_manager::get_async, http_manager_get_async_overloads(args("url", "headers", "data", "on_response", "on_write")))
;
感谢您的阅读和任何帮助是非常感谢!在
总体问题是C++只使用缺省参数来计算丢失的尾随参数,以及Boost.Python没有为非尾随缺失参数提供的值。在
错误消息
什么时候Boost.Python在内部无法分派函数,异常消息只捕获位置参数。异常消息试图捕获调用方的意图,但以C++函数调用格式显示。因为C++只支持位置参数,所以没有明显的格式来显示非位置参数。考虑一下这个简单的example:
调用
^{pr2}$example.f(a=0)
将抛出Boost.Python.ArgumentError
,并显示以下消息:尽管Boost.Python完全知道调用者提供了一个参数,异常只捕获了位置参数。在上面的例子中,没有位置参数,所以输出是
example.f()
。在最初的问题中,调用http.get_async('http://www.google.ca', on_response=f)
会导致异常显示HttpManager.get_async(HttpManager, str)
,因为只提供了两个位置参数:类型HttpManager
的隐式自变量和str
对象。在调度失败
<>在C++中,默认参数不是函数类型的一部分。此外,当调用具有默认参数的函数时,默认参数仅在缺少尾部参数的情况下使用。例如,考虑:上述函数的类型为}提供参数。如果希望使用参数
void(int, int, int)
,无法调用函数f
,只能为参数a
和{c
的非默认值来调用f
,那么必须提供所有三个参数。在但是,如果Python中声明了一个类似的函数,那么可以调用}提供一个参数,因为Python支持关键字参数:
f
,只为参数a
和{考虑这个example,其中默认参数的C++函数已被提供为超载Python函数:
在Boost.Python已被告知,C++函数^ {CD9}}具有^ {CD8}}类型,并且可以用最少1个参数调用,最多可调用3个。Boost.Python也不知道默认参数值是什么。因此,Boost.Python创建重载以支持调用:
f(int a)
f(int a, int b)
f(int, a, int b, int c)
因此,当试图在Python中调用
example.f(0, c=42)
时,函数分派将失败,如下所示Boost.Python当为c
提供值时,需要为b
提供一个值,b
的值尚未指定。在这个行为就是
http.get_async('http://www.google.ca', on_response=f)
失败的原因,因为没有办法Boost.Python调用:为Python提供默认参数
为了继续这个例子,如果Python提供了默认参数,那么它可以为非尾随参数提供值。公开函数时,可以通过赋值给^{} 对象来为参数提供默认值。下面的example公开带有默认参数的函数
f
:与Boost.Python知道了默认参数,它可以成功地调用
example.f(0, c=42)
。在相关问题 更多 >
编程相关推荐