简体   繁体   English

使用Swig将python StringIO传递给C ++ stringstream

[英]Passing python StringIO to C++ stringstream using swig

I've got some python code that generates a StringIO variable. 我有一些生成StringIO变量的python代码。 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). 我想使用stringstream参数将此变量传递给C ++函数(假设C ++ stringstream是最接近python StringIO的匹配项)。 Is there a simple way using swig to do this translation? 有没有使用swig进行翻译的简单方法?

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. 我在swig模块中看到一个std_sstream.i,其中包含一些stringstream代码,但在swig文档中找不到任何引用,也没有在Web搜索中使用它的任何示例。

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: 这是固定的test.cpp,我无法更改:

#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: 这是固定的test.h:

#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): 这是我可以编辑并调用C ++ StTest函数的python代码(我们将其称为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. 所以我在上面的注释行中寻找一种可以完成从StringIO到stringstream的转换的东西。

Here's my initial dig at the test.i file for swig do its stuff: 这是我对test.i文件的初步了解,以便swig做它的工作:

/* 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. 我假设在test.i中包括了“ std_sstream.i”,因为这是应该使用的。 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: 当前,运行test_test.py时的错误报告为:

TypeError: in method 'StTest', argument 1 of type 'stringstream &'

Why not just call PyArg_ParseTuple with a string, which you get from calling StringIO.getvalue() ? 为什么不只使用通过调用StringIO.getvalue()获得的字符串来调用StringIO.getvalue()呢?

With something like this ? 有这样的事情吗?

const char* cstring;
if (!PyArg_ParseTuple(args,"s", &cstring)) //Note the &
        return NULL;
std::string stdstring = cstring;
std::stringstream buffer(stdstring);

Also see the C API for cStringIO here . 另请参见此处的cStringIO的C API。

After the additional requirements, I attempted to discover a solution using SWIG within the fixed constraints. 在满足其他要求之后,我尝试在固定约束范围内使用SWIG查找解决方案。

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. 第一个可能的解决方案是内联解决方案或扩展解决方案(扩展StTest以获取字符串,然后使扩展生成字符串流并调用StTest),但是由于提供的示例仅具有一个方法且没有类,因此不满足约束条件。

The eventual interface file looked like this. 最终的接口文件如下所示。

/* test.i */
%module test

%{
#include "test.h"
#include <sstream>
#include <iostream>
%}
using namespace std;
%include "std_sstream.i"
%include "test.h"

%include <typemaps.i>

%typemap(in) std::stringstream & (char *buf = 0, size_t size = 0, int alloc = 0, std::stringstream stream)
{
  if (SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc) != SWIG_OK)
  {
    %argument_fail(SWIG_TypeError, "(TYPEMAP, SIZE)", $symname, $argnum);
  }

  stream.write(buf, size - 1);

  $1 = &stream;
}

Note that SWIG ignored the typemap in the interface file above, not sure why. 请注意,SWIG忽略了上面接口文件中的类型映射,不确定为什么。 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) . 它设法在Python中创建了stringstream对象,但是不会将它们传递给您的StTest,并给出相同的类型错误,因为对象的类型不是stringstream的类型&(而且映射的swig类型也没有匹配std_sstream.i生成的类型,可能是因为它不包含延迟类型映射)。

Next was the implementation of the approach I suggested overriding SWIG's wrapper, the resulting wrapped function was as follows. 接下来是我建议的覆盖SWIG包装程序的方法的实现,所产生的包装功能如下。 (Not going to include the entire wrapper file as it is over 18000 lines long) (由于长度超过18000行,因此将不包括整个包装器文件)

SWIGINTERN PyObject *_wrap_StTest(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
  PyObject *resultobj = 0;
  void *argp1 = 0 ;
  int res1 = 0 ;
  PyObject * obj0 = 0 ;
  int argc;
  PyObject *argv[3];
  int ii;
  char *cstring;
  std::stringstream testbuffer;
  if (!PyTuple_Check(args)) SWIG_fail;
  argc = args ? (int)PyObject_Length(args) : 0;
  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
    argv[ii] = PyTuple_GET_ITEM(args,ii);
  }
  if (argc == 1) {

  if (!PyArg_ParseTuple(args,"s",&cstring)) 
SWIG_fail;
  std::string teststring = cstring;
  testbuffer.str(cstring);
  std::cout << "the string in the stream: " << testbuffer.str() << std::endl;
  }  

  StTest(testbuffer);
  resultobj = SWIG_Py_Void();
  return resultobj;
fail:
  return NULL;
}   

The string in the stream line prints correctly, however passing the stringstream to StTest function prints the location in memory of the stringstream. 流线中的字符串可以正确打印,但是将stringstream传递给StTest函数可以打印stringstream在内存中的位置。 This is expected because the stringstream isn't bound like in accepted answer of the following Stack Overflow Question . 这是可以预期的,因为stringstream的绑定方式不像下面的Stack Overflow Question的公认答案那样。

I assume StTest(testbuffer); 我假设StTest(testbuffer); could be replaced with a version using boost's bind, and it would work as required, but have been able to verify. 可以使用使用boost's bind的版本替换,并且可以按要求运行,但已经能够进行验证。

References that were helpful included 包括有用的参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM