簡體   English   中英

使用Swig將python StringIO傳遞給C ++ stringstream

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

我有一些生成StringIO變量的python代碼。 我想使用stringstream參數將此變量傳遞給C ++函數(假設C ++ stringstream是最接近python StringIO的匹配項)。 有沒有使用swig進行翻譯的簡單方法?

我在swig模塊中看到一個std_sstream.i,其中包含一些stringstream代碼,但在swig文檔中找不到任何引用,也沒有在Web搜索中使用它的任何示例。

為了更清楚一點,我將在下面包含一些非常簡單的代碼。 這是固定的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);

這是我可以編輯並調用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)

所以我在上面的注釋行中尋找一種可以完成從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 &'

為什么不只使用通過調用StringIO.getvalue()獲得的字符串來調用StringIO.getvalue()呢?

有這樣的事情嗎?

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

另請參見此處的cStringIO的C API。

在滿足其他要求之后,我嘗試在固定約束范圍內使用SWIG查找解決方案。

第一個可能的解決方案是內聯解決方案或擴展解決方案(擴展StTest以獲取字符串,然后使擴展生成字符串流並調用StTest),但是由於提供的示例僅具有一個方法且沒有類,因此不滿足約束條件。

最終的接口文件如下所示。

/* 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;
}

請注意,SWIG忽略了上面接口文件中的類型映射,不確定為什么。 它設法在Python中創建了stringstream對象,但是不會將它們傳遞給您的StTest,並給出相同的類型錯誤,因為對象的類型不是stringstream的類型&(而且映射的swig類型也沒有匹配std_sstream.i生成的類型,可能是因為它不包含延遲類型映射)。

接下來是我建議的覆蓋SWIG包裝程序的方法的實現,所產生的包裝功能如下。 (由於長度超過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;
}   

流線中的字符串可以正確打印,但是將stringstream傳遞給StTest函數可以打印stringstream在內存中的位置。 這是可以預期的,因為stringstream的綁定方式不像下面的Stack Overflow Question的公認答案那樣。

我假設StTest(testbuffer); 可以使用使用boost's bind的版本替換,並且可以按要求運行,但已經能夠進行驗證。

包括有用的參考

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM