如何在python3中使用ctypes导入ostringstream?

迪马·日尔科(Dima Zhylko)

我正在为自然语言编写分析器,并且用python 3创建了C ++代码包装swig我想使用一个函数,它是某种流编写器,并且将其std::ostream & os作为参数。因此,我想如果我以某种方式在我的python代码中导入ostringstreamlib.so应该在我的阅读中使用ctypes.CDLL),然后将其传递给此函数,以免调用它create_stream_writer(stream),然后使用stream.str()来获取字符串,那将是可行的。是否可以使用ctypes或任何其他库来执行此操作?我正在使用运行Ubuntu 18.04,python3.6的Docker容器

我猜代码应该像这样:

def analyse(text, config):
    reader = PlainTextReader.create_string_reader(text, config)
    stream = ctypes.ostringstream() # some magic hear
    writer = TokenWriter.create_stream_writer('plain', stream, reader.tagset())

    for sentence in sentences(reader):
        writer.write_sentence(sentence)
    return stream.str()
柔印

您可以执行此操作(也使它对Python开发人员也很好)。这个答案本质上是我对包装iostream的较早答案的Python 3版本

为了简化本文,我使用了boost的iostreams库。如果您不能/不使用boost,那么您可以通过标准C ++库组件编写所有内容,只是冗长得多。

我也比映射旨在提高io.StringIOstd::stringstream,而是走了映射Python对象给的任何“像文件” iostream也就是说,我们使用的目标是使用Python对象只需拨打鸭打字read()write()理智的,需要我们的C ++流对象时。

%module test

%{
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/categories.hpp> 

// This is just a helper that we can use with boost iostreams to proxy everything to a Python object    
struct python_stream_device {
  typedef char char_type;
  typedef boost::iostreams::bidirectional_device_tag category;

  std::streamsize read(char* s, std::streamsize n) {
    PyObject *p = PyObject_CallMethod(o, "read", "l", static_cast<long int>(n));
    if (PyErr_Occurred()) {
      // TODO: throw a C++ exception to back out of wherever we are and then re-throw the Python one...
      assert(false);
    }
    assert(p);
    char *ptr = nullptr;
    Py_ssize_t len = 0;
    PyObject *str = PyUnicode_AsUTF8String(p);
    PyBytes_AsStringAndSize(str, &ptr, &len);
    if (PyErr_Occurred()) {
      assert(false); // Let's just pretend this is error handlng...
    }

    memcpy(s, ptr, len);
    Py_DECREF(str);
    Py_DECREF(p);
    return len;
  }

  std::streamsize write(const char* s, std::streamsize n) {
    PyObject *ret = PyObject_CallMethod(o, "write", "s#", s, static_cast<Py_ssize_t>(n));
    if (PyErr_Occurred()) {
      // See above
      assert(false);
    }
    std::streamsize r = PyLong_AsSsize_t(ret);
    Py_DECREF(ret);
    return r;
  }

  // Using this means we can rely on the default synthesised operator= + copy ctor etc. and saves us some code.
  swig::SwigPtr_PyObject o;

  python_stream_device(PyObject *o) : o(o) {}
};

typedef boost::iostreams::stream<python_stream_device> python_stream;

%}

// Here is the stuff that wraps it neatly
%typemap(in) std::iostream& (python_stream tmp) {
  // Writing the typemap this way lets us get RAII semantics despite the goto in the SWIG macros in the simplest way
  tmp.open(python_stream_device($input));  
  $1 = &tmp;
}

// We can just use the same typemaps for other cases too:
%apply std::iostream& { std::istream&, std::ostream& }; 


// Below is just for testing:    
%{
#include <iostream>
%}

%inline %{
  // This is the function you want to call
  void fun1(std::ostream& out) {
    assert(out.good());
    out << "Hello world, from C++";
    assert(out.good());
  }

  // This one is here for completeness because once you've got this far you may as well support this too.
  void fun2(std::istream& in) {
    std::string tmp;
    //in >> tmp;
    std::getline(in, tmp);
    assert(in.good());
    std::cout << "fun2 got: " << tmp << std::endl;
  }
%}

这样就足够了,然后您就可以使用这样的Python:

import io
import test

i=io.StringIO()
test.fun1(i)
print('After fun1: %s' % i.getvalue())

i=io.StringIO('hello world, from Python!\n')
test.fun2(i)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Python 3中使用绝对导入来导入位于其父目录中的包?

如何在python3中导入mysqlclient

如何在python 3.6中使用绝对导入和相对导入?

如何在python3中使用数组join()方法添加数字?

Pandas:如何在python3中的混合类型多索引中使用切片?

在python3中使用importlib进行动态导入时出错

如何在Python3中使用opencv从文件缓冲区读取文件

如何在带有if __name __ ='__ main__'块的Python3中使用相对导入?

如何在Python3中使用App Engine安排Cloud Datastore导出

如何使用ctypes从Python3访问C中的某些常量值

如何在python3中使用正则表达式获取值

如何在python3中使用AST递归简化数学表达式?

当管道到ffmpeg时如何在python3中使用stdout.write?

如何在python3中使用Asterisk AGI?

如何在Windows中的python3中导入文件/模块?

如何在python3中使用pyclbr搜索__main__模块?

如何在python中使用ctypes.windll.Wininet.InternetQueryOptionW

如何在python3中使用GtkSource.FileLoader

如何在python ctypes中使用UTF-16?

如何在Python3中的MatLab的imshow()中使用'xdata'

如何在 Python3 中使用 *args

如何在python3中使用子进程编写命令

如何在python3中使用psycopg2从postgres获取数据,包括列名

如何在python3中使用python2 input()函数?

如何在python3中使用selenium在javascrip站点中选择下拉列表?

如何在Python3中使用变量创建json文件路径?

如何在 Python3 中使用 /n?

如何在Python3中使用beautifulsoup查找配對內容

如何在 Python3 中使用 Mindee API?