gpt4 book ai didi

c++ - boost .Python 'too few template arguments to class_'

转载 作者:太空狗 更新时间:2023-10-29 23:05:14 25 4
gpt4 key购买 nike

我已经用 C++ 编写了一个类的一部分,我希望能够将它与 Python GUI 结合使用,所以我使用 Boost.Python 来尝试让它变得简单。我遇到的问题是,按照他们的指南 ( http://www.boost.org/doc/libs/1_55_0/libs/python/doc/tutorial/doc/html/python/exposing.html ),每当我运行 bjam 时,我都会收到以下异常:

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

最佳答案

简而言之,包括:

  • boost/python.hpp:Boost.Python 方便的头文件。
  • boost/python/class.hpp:定义 boost::python::class_ 的 header 。

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


此外,尝试直接公开 PacketEngine::getAvailableDevices() 可能会出现问题:

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

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

这是一个基于原始代码的完整示例:

#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

关于c++ - boost .Python 'too few template arguments to class_',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20229591/

25 4 0