0

StringIO 変数を生成する Python コードがいくつかあります。stringstream パラメータを使用して、この変数を C++ 関数に渡したいと思います (C++ stringstream が python StringIO に最も近いと仮定して)。swig を使用してこの翻訳を行う簡単な方法はありますか?

swigモジュールには、いくつかのstringstreamコードを含むstd_sstream.iがあることがわかりますが、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 への変換を実行できるものを探しています。

これは、swig の test.i ファイルでの私の最初の掘り下げです。

/* test.i */
%module test

%{
#include "test.h"
%}

%include "std_sstream.i"
%include "test.h"

「std_sstream.i」を test.i に含めました。これを使用する必要があると思います。何かを行うために、このファイルに何かを追加する必要がありますか?

現在、test_test.py を実行したときのエラー レポートは次のとおりです。

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

1 に答える 1

1

PyArg_ParseTuple を呼び出して取得した文字列で呼び出してみません 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 を呼び出す) でしたが、提供された例にはメソッドが 1 つしかなく、クラスがないため、これは制約を満たしませんでした。 .

最終的なインターフェイス ファイルは次のようになります。

/* 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 が上記のインターフェイス ファイルの typemap を無視したことに注意してください。理由は不明です。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;
}   

ストリーム行の文字列は正しく出力されますが、文字列ストリームを StTest 関数に渡すと、文字列ストリームのメモリ内の場所が出力されます。これは、次のStack Overflow Questionの受け入れられた回答のように stringstream がバインドされていないためです。

ブーストのバインドを使用したバージョンに置き換えることができ、必要に応じて機能すると思い StTest(testbuffer);ますが、確認できました。

参考になった参考書を掲載

于 2012-02-17T00:56:15.543 に答える