如何在 SWIG 中包装可变参数模板 class 的可变参数模板成员函数?
How can I wrap a variadic template member function of a variadic template class in SWIG?
我有一个 header 文件,其中包含可变模板的定义,其中还包含一些可变模板成员函数。为了简洁起见,下面的代码片段已被大大简化和缩减:
#pragma once
template<typename T, typename ... CtorArgs>
class Foo {
public:
Foo(CtorArgs... args) : _m(args...) {}
template<typename ... Args>
void DoSomething(Args... args) { _m.DoSomething(args...); }
private:
T _m;
};
然后我有另一个 header 定义一个 class 用于模板专业化:
#pragma once
#include <string>
#include <iostream>
class Bar {
public:
Bar(std::string const & a,
std::string const & b) :
m_strA(a),
m_strB(b) {}
void DoSomething(int const one, int const two) {
std::cout << "Str A: " << m_strA << ", Str B: "<< m_strB << ", ints: " << one << ", " << two << std::endl;
}
private:
std::string m_strA;
std::string m_strB;
};
我想使用 SWIG 包装 Foo 专业化,以及它的模板化成员函数,这样我就可以从 Lua 脚本中使用它们。
我遇到的问题是 SWIG 没有像我预期的那样为 DoSomething 模板函数生成包装器。
阅读一些 SWIG 文档后,我知道它无法使用 %template 指令对参数包参数进行 1 个以上的替换,所以我有使用 %rename 代替:
%module FooSwig
%include <std_string.i>
%{
#include "foo.hpp"
#include "bar.hpp"
%}
%include "foo.hpp"
%include "bar.hpp"
%rename(lua_foo) Foo<Bar, std::string const &, std::string const &>;
class Foo<Bar, std::string const &, std::string const &> {
public:
Foo(std::string const &, std::string const &);
template<typename ... Args>
void DoSomething(Args... args);
private:
Bar _m;
};
使用 %template 指令不起作用(正如预期的那样),因为要替换的参数超过 1 个 - 我从 swig 得到以下信息:
Error: Template 'DoSomething' undefined.
我想我需要再次使用 %rename 来解决这个问题,但我不知道该怎么做。我尝试了以下方法:
%extend Foo<Bar, std::string const &, std::string const &>
{
%rename(Do_Something) DoSomething<int const, int const>;
void DoSomething(int const, int const);
}
这确实会生成一些东西,但是包装器包含一个未定义函数的符号:
Foo_Sl_Bar_Sc_std_string_SS_const_SA__Sc_std_string_SS_const_SA__Sg__DoSomething(arg1,arg2,arg3);
而不是对成员函数模板的预期调用,类似于
(arg1)->SWIGTEMPLATEDISAMBIGUATOR DoSomething<int const, int const>(arg2, arg3);
我 运行 没有什么可以尝试的,也许你们中有人可以帮忙?
关于我的环境的一些信息:
我正在使用 g++ 7.4.0、c++ 17 和 SWIG 3.0。
我设法生成了包装器,它按预期工作。
这是旧 SWIG 接口文件的片段:
...
template<typename ... Args>
void DoSomething(Args... args);
...
我将其替换为以下内容:
...
void DoSomething(int const, int const);
...
但是我仍然很想知道是否有更好的方法来做到这一点,所以任何进一步的信息(或阅读 materials/source 代码的指针)将不胜感激。
我想到的最好的解决方法是编写多个模板 class,每个模板参数的数量不同,因为通常模板参数不多。
我有一个 header 文件,其中包含可变模板的定义,其中还包含一些可变模板成员函数。为了简洁起见,下面的代码片段已被大大简化和缩减:
#pragma once
template<typename T, typename ... CtorArgs>
class Foo {
public:
Foo(CtorArgs... args) : _m(args...) {}
template<typename ... Args>
void DoSomething(Args... args) { _m.DoSomething(args...); }
private:
T _m;
};
然后我有另一个 header 定义一个 class 用于模板专业化:
#pragma once
#include <string>
#include <iostream>
class Bar {
public:
Bar(std::string const & a,
std::string const & b) :
m_strA(a),
m_strB(b) {}
void DoSomething(int const one, int const two) {
std::cout << "Str A: " << m_strA << ", Str B: "<< m_strB << ", ints: " << one << ", " << two << std::endl;
}
private:
std::string m_strA;
std::string m_strB;
};
我想使用 SWIG 包装 Foo 专业化,以及它的模板化成员函数,这样我就可以从 Lua 脚本中使用它们。
我遇到的问题是 SWIG 没有像我预期的那样为 DoSomething 模板函数生成包装器。
阅读一些 SWIG 文档后,我知道它无法使用 %template 指令对参数包参数进行 1 个以上的替换,所以我有使用 %rename 代替:
%module FooSwig
%include <std_string.i>
%{
#include "foo.hpp"
#include "bar.hpp"
%}
%include "foo.hpp"
%include "bar.hpp"
%rename(lua_foo) Foo<Bar, std::string const &, std::string const &>;
class Foo<Bar, std::string const &, std::string const &> {
public:
Foo(std::string const &, std::string const &);
template<typename ... Args>
void DoSomething(Args... args);
private:
Bar _m;
};
使用 %template 指令不起作用(正如预期的那样),因为要替换的参数超过 1 个 - 我从 swig 得到以下信息:
Error: Template 'DoSomething' undefined.
我想我需要再次使用 %rename 来解决这个问题,但我不知道该怎么做。我尝试了以下方法:
%extend Foo<Bar, std::string const &, std::string const &>
{
%rename(Do_Something) DoSomething<int const, int const>;
void DoSomething(int const, int const);
}
这确实会生成一些东西,但是包装器包含一个未定义函数的符号:
Foo_Sl_Bar_Sc_std_string_SS_const_SA__Sc_std_string_SS_const_SA__Sg__DoSomething(arg1,arg2,arg3);
而不是对成员函数模板的预期调用,类似于
(arg1)->SWIGTEMPLATEDISAMBIGUATOR DoSomething<int const, int const>(arg2, arg3);
我 运行 没有什么可以尝试的,也许你们中有人可以帮忙?
关于我的环境的一些信息: 我正在使用 g++ 7.4.0、c++ 17 和 SWIG 3.0。
我设法生成了包装器,它按预期工作。
这是旧 SWIG 接口文件的片段:
...
template<typename ... Args>
void DoSomething(Args... args);
...
我将其替换为以下内容:
...
void DoSomething(int const, int const);
...
但是我仍然很想知道是否有更好的方法来做到这一点,所以任何进一步的信息(或阅读 materials/source 代码的指针)将不胜感激。
我想到的最好的解决方法是编写多个模板 class,每个模板参数的数量不同,因为通常模板参数不多。