C++中的Python回调 class EventHandler { virtual long readFromDaemon(void *buf, size_t count) = 0; };

C++中的Python回调 class EventHandler { virtual long readFromDaemon(void *buf, size_t count) = 0; };,python,c++,swig,Python,C++,Swig,以及使用它的Python程序 class Handler(EventHandler): def readFromDaemon(self, buf, count): ... C++代码调用EventHandler::readFromDaemon。 SWIG转换参数并调用Python的readFromDaemon: long SwigDirector_EventHandler::readFromDaemon(void *buf, size_t count) { ... sw

以及使用它的Python程序

class Handler(EventHandler):
    def readFromDaemon(self, buf, count):
    ...
C++代码调用EventHandler::readFromDaemon。 SWIG转换参数并调用Python的readFromDaemon:

long SwigDirector_EventHandler::readFromDaemon(void *buf, size_t count) {
  ...
  swig::SwigVar_PyObject obj0;
  obj0 = SWIG_NewPointerObj(SWIG_as_voidptr(buf), SWIGTYPE_p_void,  0 );

  swig::SwigVar_PyObject obj1;
  obj1 = SWIG_From_size_t(static_cast< size_t >(count));
  ...
  swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar((char *)"readFromDaemon");
  swig::SwigVar_PyObject result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name ,(PyObject *)obj0,(PyObject *)obj1, NULL);
但我没有找到一个方法来实现它

%typemap(in) (void *buf, size_t count) { ... } does not help.

这是一个C++数据缓冲区的读写例子。我的例子中的C++函数是:

void read(void* buf, size_t count);
void write(const void* buf, size_t count);
SWIG接口文件:

%module x

%include <exception.i>

// Handle an input-only (const) buffer.
// A single Python input is translated into a buffer and a size.
%typemap(in) (const void *buf, size_t count) (Py_ssize_t tmp) %{
    if(PyBytes_AsStringAndSize($input,(char**)&$1,&tmp) == -1)
        return NULL;
    $2 = tmp;
%}

// Handle an output-only (non-const) buffer.
// The single integer Python input is allocated in a temporary
// buffer and the pointer and its size are created as C++ parameters.
%typemap(in,numinputs=1) (void *buf, size_t count) (long tmp) %{
    if(!PyLong_Check($input))
        SWIG_exception(SWIG_TypeError,"expected integer");
    tmp = PyLong_AsLong($input);
    if(tmp < 1 || tmp > 65535)
        SWIG_exception(SWIG_ValueError,"expected value 1-65535");
    $2 = tmp;
    $1 = new char[$2];
%}

// The pair of output arguments are translated into a single
// Python bytes object and appended to any existing return value.
%typemap(argout) (void *buf, size_t count) (PyObject* po) %{
    po = PyBytes_FromStringAndSize((char*)$1,$2);
    $result = SWIG_Python_AppendOutput($result,po);
%}

// Free the temporary buffer created in the "in" typemap.
%typemap(freearg) (void* buf, size_t count) %{
    delete $1;
%}

// SWIG will wrap these two functions prototypes.
void read(void* buf, size_t count);
void write(const void* buf, size_t count);

// Implementation
%{
#include <iostream>
void write(const void* buf, size_t count)
{
    char* tmp = (char*)buf;
    for(size_t i = 0; i < count; i++)
        std::cout << i << ": " << (int)tmp[i] << std::endl;
}

void read(const void* buf, size_t count)
{
    char* tmp = (char*)buf;
    for(size_t i = 0; i < count; i++)
        tmp[i] = (char)i;
}
%}
演示:


我在另一个主题中找到了一个决定

%typemap(directorin) (void *buf, size_t count) {
    $input = PyBytes_FromStringAndSize(static_cast<char*>($1), $2);
}
但还有另一个问题。内存缓冲区从C++复制到Python对象。如何将字节从Python对象复制到C++?从python 2.7开始就有memoryview,但是如何处理2.6和更旧的版本呢

这是调用EvEthANDL::Read Daveon的C++代码,为了清晰< /P>

std::vector<char> buf(maxlen);
long cnt = m_evt_handler->readFromDaemon(&buf[0], buf.size());
下面是包装器代码

long SwigDirector_EventHandler::readFromDaemon(void *buf, size_t count) {
  long c_result;
  swig::SwigVar_PyObject obj0;
  {
    obj0 = PyBytes_FromStringAndSize(static_cast<char*>(buf), count);
  }
  ...

非常感谢。我尝试了%typemapin和%typemapin来计算void*buf,size\u t count,它们对于独立函数来说工作得很好。但问题是swig并没有将这个类型映射应用于director类,我也没有找到方法强制它这样做。请注意SwigDirector\u EventHandler::readFromDaemonvoid*buf,size\u t count您能将您的问题简化为一个小的工作示例来说明问题吗?我不知道您尝试了什么,也没有。我将您的问题归档。谢谢您的帮助,我找到了问题的答案,但出现了新问题。请读我的新帖子。
std::vector<char> buf(maxlen);
long cnt = m_evt_handler->readFromDaemon(&buf[0], buf.size());
long SwigDirector_EventHandler::readFromDaemon(void *buf, size_t count) {
  long c_result;
  swig::SwigVar_PyObject obj0;
  {
    obj0 = PyBytes_FromStringAndSize(static_cast<char*>(buf), count);
  }
  ...