将 python StringIO 传递给 C++使用 swig 的字符串流
我有一些生成 StringIO 变量的 python 代码。我想使用 stringstream 参数将此变量传递给 C++ 函数(假设 C++ stringstream 是与 python StringIO 最接近的匹配)。有没有一种简单的方法使用 swig 来进行这种翻译?
我在 swig 模块中看到一个 std_sstream.i,其中包含一些 stringstream 代码,但我在 swig 文档中找不到任何对它的引用,也找不到它在网络搜索中使用的任何示例。
为了让它更清晰一些,我将在下面添加一些非常简单的代码。 这是 test.cpp,它是固定的,我无法更改:
#include <iostream>
#include <sstream>
#include "test.h"
using namespace std;
void StTest(stringstream &ss)
{
cout << ss << endl;
}
这是 test.h,它也是固定的:
#include <sstream>
using namespace std;
void StTest(stringstream &ss);
的 python 代码,它调用 C++ StTest 函数(我们称之为 test_test.py):
#!/usr/bin/env python
import StringIO
import test
ss = StringIO.StringIO()
ss.write("Hello")
# Maybe some thing here to convert ss from StringIO to stringstream
test.StTest(ss)
这是我可以编辑 我正在寻找可以在上面的注释行中从 StringIO 转换为 stringstream 的东西。
这是我对 test.i 文件的初步挖掘,以便 swig 做它的事情:
/* test.i */
%module test
%{
#include "test.h"
%}
%include "std_sstream.i"
%include "test.h"
我在 test.i 中包含了“std_sstream.i”,因为我认为这是应该使用的。我需要向该文件添加一些内容才能让它执行某些操作吗?
目前运行test_test.py时的错误报告为:
TypeError: in method 'StTest', argument 1 of type 'stringstream &'
I've got some python code that generates a StringIO variable. I'd like to pass this variable to a C++ function using a stringstream parameter (on the assumption C++ stringstream is the closest match to a python StringIO). Is there a simple way using swig to do this translation?
I see in the swig modules there is a std_sstream.i which contains some stringstream code, but I can't find any references to it in the swig documentation, or any examples of its use on a web search.
To try and make it a little clearer, I'll include some very simple code below.
Here's test.cpp which is fixed and I can't change:
#include <iostream>
#include <sstream>
#include "test.h"
using namespace std;
void StTest(stringstream &ss)
{
cout << ss << endl;
}
Here's test.h which is also fixed:
#include <sstream>
using namespace std;
void StTest(stringstream &ss);
Here's the python code which I can edit and which calls the C++ StTest function (we'll call this test_test.py):
#!/usr/bin/env python
import StringIO
import test
ss = StringIO.StringIO()
ss.write("Hello")
# Maybe some thing here to convert ss from StringIO to stringstream
test.StTest(ss)
So I'm looking for something that can do the conversion from StringIO to stringstream in the commented line above.
Here's my initial dig at the test.i file for swig do its stuff:
/* test.i */
%module test
%{
#include "test.h"
%}
%include "std_sstream.i"
%include "test.h"
I've included "std_sstream.i" in test.i as this is what ought to be used, I assume. Do I need to add something to this file to get it to do something?
Currently the error report when running test_test.py is:
TypeError: in method 'StTest', argument 1 of type 'stringstream &'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为什么不直接使用通过调用获得的字符串来调用 PyArg_ParseTuple
StringIO.getvalue() ?
有这样的东西吗?
另请参阅 cStringIO 的 C API 此处 。
在满足附加要求之后,我尝试在固定约束内使用 SWIG 找到解决方案。
第一个可能的解决方案是内联或扩展解决方案(扩展 StTest 以获取字符串,然后让扩展创建字符串流并调用 StTest),但由于提供的示例只有一个方法并且没有类,因此这不满足约束。
最终的界面文件如下所示。
请注意,SWIG 忽略了上面接口文件中的类型映射,不知道为什么。它设法在 Python 中创建 stringstream 对象,但它们不会传递给您的 StTest,从而给出相同的类型错误,因为对象的类型不是 stringstream & 的类型。 (映射的 swig 类型也与 std_sstream.i 生成的类型不匹配,可能是因为它不包含引用类型映射)。
接下来是我建议的覆盖 SWIG 包装器的方法的实现,最终的包装函数如下。 (不会包含整个包装文件,因为它超过 18000 行长)
流行中的字符串可以正确打印,但是将字符串流传递给 StTest 函数会打印字符串流在内存中的位置。这是预期的,因为字符串流不像以下可接受的答案那样绑定堆栈溢出问题。
我假设 StTest(testbuffer); 可以替换为使用 boost 绑定的版本,并且它可以按要求工作,但已经能够验证。
有用的参考文献包括
PyTutorial98
使用 SWIG 在 C++ 中进行 Python 扩展
Why not just call PyArg_ParseTuple with a string, which you get from calling
StringIO.getvalue()
?With something like this ?
Also see the C API for cStringIO here.
After the additional requirements, I attempted to discover a solution using SWIG within the fixed constraints.
The first possible solution was the inline or extends solution (extend StTest to take a string and then have the extension make a stringstream and call StTest), but as the provided example has only one method and no classes, this didn't meet the constraints.
The eventual interface file looked like this.
Note that SWIG ignored the typemap in the interface file above, not sure why. It managed to to create stringstream objects in Python, but they wouldn't be passed to your StTest, giving the same type error because the type of the objects wasn't the type of the stringstream & (also the mapped swig type didn't match the types generated by std_sstream.i, probably because it doesn't contain deferencing typemaps) .
Next was the implementation of the approach I suggested overriding SWIG's wrapper, the resulting wrapped function was as follows. (Not going to include the entire wrapper file as it is over 18000 lines long)
The string in the stream line prints correctly, however passing the stringstream to StTest function prints the location in memory of the stringstream. This is expected because the stringstream isn't bound like in accepted answer of the following Stack Overflow Question .
I assume
StTest(testbuffer);
could be replaced with a version using boost's bind, and it would work as required, but have been able to verify.References that were helpful included
PyTutorial98
Python Extensions In C++ Using SWIG
SWIG1.3a5 Typemap FAQ for Python, Perl5(,Tcl)