我正在尝试使用SWIG将c项目包装到pythonapi中,遇到了以下格式的代码问题。
class A
{
//constructors and such.
};
class B
{
//constructors and such.
};
class C
{
//constructors and such.
};
typedef boost::variant<A,B,C> VariantType;
typedef std::vector<boost::variant<A,B,C>> VariantTypeList;
A、B类
%template(VariantType) boost::variant<A,B,C>;
%template(VariantTypeList) std::vector<boost::variant<A,B,C>>;
我得到一个错误,上面写着
Boost\x64\include\booost\Variant\variant.hpp(148): error:输入(3)中的语法错误。
所以我去看看这个错误和它的一行,其中有一个宏是在另一个头文件中定义的,特别是“boost/mpl/aux\uvalue\u wknd.hpp”,所以我用%include将它添加到接口文件中,现在看起来是SWIG。exe崩溃,并出现一个错误
访问违规
长话短说,有没有办法包装boost::variant模板类型?不幸的是,这个模板定义被嵌入了我们库的核心,我现在无法更改它。如果有关系的话,我也在MSVC 2013编译器上。
如果无法直接包装模板类型,是否可以解决此问题?我正在阅读SWIG文档,看看是否有一些可以应用的类型映射魔法,但我对SWIG总体上还是比较陌生的。
如果你决定使用SWIG(正如你在帖子中所说,这对我来说并不清楚,所以我认为这是一个新项目),那么停止阅读,忽略这个答案。
但是,如果要使用的绑定技术还没有固定下来,您只需要绑定Python,而不需要绑定其他语言,那么另一种选择就是使用cppyy(http://cppyy.org完整免责声明:我是主要作者)。这样,boost::variant类型就可以直接在Python中使用,然后您可以通过编写Python代码而不是SWIG来让它看起来/行为更像Python。我需要密码。
示例(请注意,cppyy在PyPI上有Windows控制盘,但是用MSVC2017而不是MSVC2013构建的,所以我将保留关于MSVC2013是否足够现代,可以像我没有尝试过的那样构建代码的警告):
import cppyy
cppyy.include("boost/variant/variant.hpp")
cppyy.include("boost/variant/get.hpp")
cpp = cppyy.gbl
std = cpp.std
boost = cpp.boost
cppyy.cppdef("""
class A
{
//constructors and such.
};
class B
{
//constructors and such.
};
class C
{
//constructors and such.
};
""")
VariantType = boost.variant['A, B, C']
VariantTypeList = std.vector[VariantType]
v = VariantTypeList()
v.push_back(VariantType(cpp.A()))
print(v.back().which())
v.push_back(VariantType(cpp.B()))
print(v.back().which())
v.push_back(VariantType(cpp.C()))
print(v.back().which())
print(boost.get['A'](v[0]))
try:
print(boost.get['B'](v[0]))
except Exception as e:
print(e) # b/c of type-index mismatch above
print(boost.get['B'](v[1])) # now corrected
print(boost.get['C'](v[2]))
产生以下预期输出:
$ python variant.py
0
1
2
<cppyy.gbl.A object at 0x5053704>
Could not instantiate get<B>:
B& boost::get(boost::variant<A,B,C>& operand) =>
Exception: boost::bad_get: failed value get using boost::get (C++ exception)
<cppyy.gbl.B object at 0x505370c>
<cppyy.gbl.C object at 0x5053714>
你可以做到。我花了很长时间思考了boost::variant
最简洁的Python接口到底是什么。我的结论是,99%的Python用户甚至不应该意识到有一种变体类型正在被使用——联合和变体基本上只是在某种程度上限制了C的duck类型。
所以我的目标是:
std::string
,int
,类型映射
在不向事物中添加一些机械的情况下完成所有这些是相当繁琐的。我将所有内容都包装在一个可重复使用的文件中,这是我的boost_variant. i的最终工作版本:
%{
#include <boost/variant.hpp>
static PyObject *this_module = NULL;
%}
%init %{
// We need to "borrow" a reference to this for our typemaps to be able to look up the right functions
this_module = m; // borrow should be fine since we can only get called when our module is loaded right?
// Wouldn't it be nice if $module worked *anywhere*
%}
#define FE_0(...)
#define FE_1(action,a1) action(0,a1)
#define FE_2(action,a1,a2) action(0,a1); action(1,a2)
#define FE_3(action,a1,a2,a3) action(0,a1); action(1,a2); action(2,a3)
#define FE_4(action,a1,a2,a3,a4) action(0,a1); action(1,a2); action(2,a3); action(3,a4)
#define FE_5(action,a1,a2,a3,a4,a5) action(0,a1); action(1,a2); action(2,a3); action(3,a4); action(4,a5)
#define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
%define FOR_EACH(action,...)
GET_MACRO(__VA_ARGS__, FE_5, FE_4, FE_3, FE_2, FE_1, FE_0)(action,__VA_ARGS__)
%enddef
#define in_helper(num,type) const type & convert_type ## num () { return boost::get<type>(*$self); }
#define constructor_helper(num,type) variant(const type&)
%define %boost_variant(Name, ...)
%rename(Name) boost::variant<__VA_ARGS__>;
namespace boost {
struct variant<__VA_ARGS__> {
variant();
variant(const boost::variant<__VA_ARGS__>&);
FOR_EACH(constructor_helper, __VA_ARGS__);
int which();
bool empty();
%extend {
FOR_EACH(in_helper, __VA_ARGS__);
}
};
}
%typemap(out) boost::variant<__VA_ARGS__> {
// Make our function output into a PyObject
PyObject *tmp = SWIG_NewPointerObj(&$1, $&1_descriptor, 0); // Python does not own this object...
// Pass that temporary PyObject into the helper function and get another PyObject back in exchange
const std::string func_name = "convert_type" + std::to_string($1.which());
$result = PyObject_CallMethod(tmp, func_name.c_str(), "");
Py_DECREF(tmp);
}
%typemap(in) const boost::variant<__VA_ARGS__>& (PyObject *tmp=NULL) {
// I don't much like having to "guess" the name of the make_variant we want to use here like this...
// But it's hard to support both -builtin and regular modes and generically find the right code.
PyObject *helper_func = PyObject_GetAttrString(this_module, "new_" #Name );
assert(helper_func);
// TODO: is O right, or should it be N?
tmp = PyObject_CallFunction(helper_func, "O", $input);
Py_DECREF(helper_func);
if (!tmp) SWIG_fail; // An exception is already pending
// TODO: if we cared, we chould short-circuit things a lot for the case where our input really was a variant object
const int res = SWIG_ConvertPtr(tmp, (void**)&$1, $1_descriptor, 0);
if (!SWIG_IsOK(res)) {
SWIG_exception_fail(SWIG_ArgError(res), "Variant typemap failed, not sure if this can actually happen");
}
}
%typemap(freearg) const boost::variant<__VA_ARGS__>& %{
Py_DECREF(tmp$argnum);
%}
%enddef
这为我们提供了一个可以在SWIG中使用的宏,%boost\u variant
。然后,您可以在界面文件中使用以下内容:
%module test
%include "boost_variant.i"
%inline %{
struct A {};
struct B {};
%}
%include <std_string.i>
%boost_variant(TestVariant, A, B, std::string);
%inline %{
void idea(const boost::variant<A, B, std::string>&) {
}
boost::variant<A,B,std::string> make_me_a_thing() {
struct A a;
return a;
}
boost::variant<A,B,std::string> make_me_a_string() {
return "HELLO";
}
%}
其中,%boost_variant
宏将第一个参数作为类型的名称(很像%template
那样),其余参数作为变量中所有类型的列表。
这足以让我们运行以下Python:
import test
a = test.A();
b = test.B();
test.idea(a)
test.idea(b)
print(test.make_me_a_thing())
print(test.make_me_a_string())
那这到底是怎么回事?
%模板
支持。(它在这里作为一个选项记录)FOR_EACH
可变宏完成的。很大程度上这与我之前在std::function
上的回答相同,它本身源自几个较旧的Stack Overflow答案,并适用于与SWIG的预处理器一起工作。FOR_EACH
宏我们告诉SWIG为变体可以容纳的每种类型包装一个构造函数。这使我们可以从Python代码显式构造变体,并添加了两个额外的构造函数基本上只是通过稍微复杂的路线委托给构造函数,因为以编程方式在同一模块中查找其他函数出奇地困难。一旦委托发生,我们使用函数参数的正常转换将临时变体传递给函数,就好像它是我们被赋予的一样。
- 我们还合成了一组额外的成员函数,
convert_typeN
内部只调用提升::get
我想使用SWIG将暴露到Tcl层。但目前我不知道我可以暴露这个。我发现SWIG/Lib文件夹包含的接口文件。但在内容中我发现我不能直接使用它。它必须包含在“”之后。但在“”文件夹中没有像这样的东西但我们有类似的界面,我可以包含在Java中。
SWIG是个帮助使用C或者C++编写的软件能与其它各种高级编程语言进行嵌入联接的开发工具。SWIG能应用于各种不同类型的语言包括常用脚本编译语言例如Perl, PHP, Python, Tcl, Ruby and PHP。支持语言列表中 也包括非脚本编译语言,例如C#, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), Java, Modula-3, OCA
问题内容: boost.python如何处理Python 3?仅限Python 2吗? 问题答案: 较新版本的Boost应该可以在Python V3.x上正常工作。早在2009年成功完成Google Summer of Code项目后,我相信很早以前就已经添加了此支持。 将Python V3与Boost结合使用的方法是,通过添加以下示例来正确配置构建系统: 到您的user-config.jam文件
根据http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/cpp2011/futures.html,我们可以将boost::asio与一起使用。但是我找不到任何有关使用的信息,它具有更多的功能,例如。我怎么用?
Boost 库是一个经过千锤百炼、可移植、提供源代码的 C++ 库,作为标准库的后备,是 C++ 标准化进程的发动机之一。 Boost 库由 C++ 标准委员会库工作组成员发起,在 C++ 社区中影响甚大,其成员已近 2000 人。 Boost 库为我们带来了最新、最酷、最实用的技术,是不折不扣的“准”标准库。
swig 是node端的一个优秀简洁的模板引擎,类似Python模板引擎Jinja,目前不仅在node端较为通用,相对于jade、ejs优秀,而且在浏览器端也可以很好地运行。 特性: 支持大多数主流浏览器。 表达式兼容性好。 面向对象的模板继承。 将过滤器和转换应用到模板中的输出。 可根据路劲渲染页面。 支持页面复用。 支持动态页面。 可扩展、可定制。 使用示例: 模板代码 <h1>{{ page