2013-11-26 97 views
3

我已经写了C++类的一部分,我希望能够将它与Python GUI结合使用,所以我使用Boost.Python来尝试并让它变得容易。我遇到的问题是,在下面的指南(http://www.boost.org/doc/libs/1_55_0/libs/python/doc/tutorial/doc/html/python/exposing.html),我不断收到以下异常,每当我运行的bjamBoost.Python'太少模板参数class_'

PacketWarrior/pcap_ext.cc:21:5: error: too few template arguments for class template 'class_' 

显然它的抱怨,在我要省略什么他们要求是可选的参数到'class_'模板函数,但我不明白为什么。我假设这是一个编译器问题,但我不知道如何解决它。我正在运行OS X 10.9并将darwin用作默认工具集,但是GCC引发了相同的错误。如果有帮助的话,我的Boost版本是1_55_0。

类的头文件(标题警卫忽略):

#include <queue> 
#include "pcap.h" 

#include "Packet.h" 

class PacketEngine { 

public: 
    PacketEngine(); 
    ~PacketEngine(); 

    const char** getAvailableDevices(char *error_buf); 
    bool selectDevice(const char* dev); 
    Packet getNextPacket(); 

private: 
    char *selected_device; 
    char **devices; 
    int num_devices; 
    std::queue<Packet> packet_queue; 
}; 

含有至Boost.Python的和引用我的类CC文件:

#include <boost/python/module.hpp> 
#include <boost/python/def.hpp> 
#include "PacketEngine.h" 

BOOST_PYTHON_MODULE(pcap_ext) { 
    using namespace boost::python; 

    class_<PacketEngine>("PacketEngine") 
     .def("getAvailableDevices", &PacketEngine::getAvailableDevices); 
} 

和我的bjam文件(不相关部分和注释省略):

use-project boost : ../../../Downloads/boost_1_55_0 ; 

project 
    : requirements <library>/boost/python//boost_python 
       <implicit-dependency>/boost//headers 
    : usage-requirements <implicit-dependency>/boost//headers 
    ; 

python-extension pcap_ext : PacketWarrior/pcap_ext.cc ; 

install convenient_copy 
    : pcap_ext 
    : <install-dependencies>on <install-type>SHARED_LIB <install-type>PYTHON_EXTENSION 
    <location>. 
    ; 

local rule run-test (test-name : sources +) 
{ 
    import testing ; 
    testing.make-test run-pyd : $(sources) : : $(test-name) ; 
} 

run-test pcap : pcap_ext pcap.py ; 

有关如何规避此例外的任何想法都很棒我很感谢!我研究了添加可选参数的显而易见的途径,但我认为它们与我的项目无关。该class_的定义可以在这里找到:

http://www.boost.org/doc/libs/1_37_0/libs/python/doc/v2/class.html

+0

如果你标记你的问题[标签:升压蟒蛇],你会最大化有机会得到图书馆的一些专家来帮助你。我对此知之甚少,但一个快速的谷歌搜索引导我[this](http://lists.boost.org/boost-users/2008/07/37787.php),它似乎很有前途。 – llonesmiz

+0

会做,谢谢你的提示 – drodman

回答

1

总之,无论是包括:

  • boost/python.hpp:Boost.Python的便捷头文件。
  • boost/python/class.hpp:标题定义为boost::python::class_

当前包含的头文件声明class_,其中def_visitor.hpp没有默认模板参数。


此外,试图直接暴露PacketEngine::getAvailableDevices()可能会出现一个问题:

  • 它接受一个char*说法,但字符串是在Python是不可改变的。
  • 没有类型自动转换为Boost.Python中的const char**

这可能是合理的一个Python用户期望PacketEngine.getAvailableDevices()返回包含的Python str秒的迭代式,或者在错误抛出异常。这可以通过编写一个辅助函数或辅助函数以非侵入性的方式完成,该辅助函数或辅助函数委托给原始函数,但暴露给Python,如PacketEngine.getAvailableDevices()

这是在原有基础上的代码一个完整的例子:

#include <exception> // std::runtime_error 
#include <boost/python.hpp> 

namespace { 
const char* devices_str[] = { 
    "device A", 
    "device B", 
    "device C", 
    NULL 
}; 
} // namespace 

class PacketEngine 
{ 
public: 
    PacketEngine() : devices(devices_str) {} 

    const char** getAvailableDevices(char *error_buf) 
    { 
    // Mockup example to force an error on second call. 
    static bool do_error = false; 
    if (do_error) 
    { 
     strcpy(error_buf, "engine not responding"); 
    } 
    do_error = true; 
    return devices; 
    } 

private: 
    const char **devices; 
}; 

/// @brief Auxiliary function for PacketEngine::getAvailableDevices that 
///  provides a more Pythonic API. The original function accepts a 
///  char* and returns a const char**. Both of these types are 
///  difficult to use within Boost.Python, as strings are immutable 
///  in Python, and Boost.Python is focused to providing 
///  interoperability to C++, so the const char** type has no direct 
///  support. 
boost::python::list PacketEngine_getAvailableDevices(PacketEngine& self) 
{ 
    // Get device list and error from PacketEngine. 
    char error_buffer[256] = { 0 }; 
    const char** devices = self.getAvailableDevices(error_buffer); 

    // On error, throw an exception. Boost.Python will catch it and 
    // convert it to a Python's exceptions.RuntimeError. 
    if (error_buffer[0]) 
    { 
    throw std::runtime_error(error_buffer); 
    } 

    // Convert the c-string array to a list of Python strings. 
    namespace python = boost::python; 
    python::list device_list; 
    for (unsigned int i = 0; devices[i]; ++i) 
    { 
    const char* device = devices[i]; 
    device_list.append(python::str(device, strlen(device))); 
    } 
    return device_list; 
} 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 

    python::class_<PacketEngine>("PacketEngine") 
    .def("getAvailableDevices", &PacketEngine_getAvailableDevices); 
} 

互动用法:

>>> import example 
>>> engine = example.PacketEngine() 
>>> for device in engine.getAvailableDevices(): 
...  print device 
... 
device A 
device B 
device C 
>>> devices = engine.getAvailableDevices() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
RuntimeError: engine not responding 
+0

非常感谢你!我想知道暴露char **,我将不得不更多地阅读Python支持的C++类型 – drodman