2013-11-26 65 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