【问题标题】:Getting a char* output from C++ to Python in SWIG在 SWIG 中获取从 C++ 到 Python 的 char* 输出
【发布时间】:2020-07-20 00:25:47
【问题描述】:

我正在尝试创建一个 Python 蓝牙包装器来包装 C++ 类。这是我的 SWIG 接口文件:

%module blsdk


%include "pyabc.i"
%include "std_vector.i"
%include "cstring.i"
%include "cpointer.i"
%include "typemaps.i"

%include serialport.i
%include exploresearch.i

这是我的serialport.i

%module  serialport

%{
#include <string>

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <termios.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <assert.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>

#include "BTSerialPortBinding.h"
%}

%include "BTSerialPortBinding.h"

我的 BTSerialPortBinding.h 有这些功能:

static BTSerialPortBinding *Create(std::string address, int channelID);

int Connect();

void Close();

int Read(char *buffer, int length);

void Write(const char *write_buffer, int length);

bool IsDataAvailable();

如何包装 int Read(char* buffer, int length) 函数?我想将 char* 缓冲区作为输出,将长度作为输入。我试图将读取函数定义为 int Read(char* OUTPUT, int length) 但这会产生错误:TypeError: a bytes-like object is required, not 'str' 在我的程序中,因为我需要 Python 中的字节对象。任何帮助将不胜感激。

【问题讨论】:

    标签: python c++ bluetooth swig


    【解决方案1】:

    这不是一个完整的答案,但它可能会帮助您开始破解。与 SWIG 一样,关键是查看生成的代码并对其进行修改。再次写下我的头顶,只是一个起点。

    您可以做的一件事是有点老套,但如果您对读取的数据量有一定的理论限制,则可能会奏效。一种方便的方法是使用这样的一对“吞下”输入和返回值:

    %typemap(in,numinputs=0) char *buffer
    {
        $1 = malloc(some_arbitrary_large_amount);
        // or 'cheat' by looking at swig output and using the value you just happen
        // to know is the length (like arg1 or something)
    }
    
    %typemap(argout) char *buffer
    {
        PyObject *tmp = $result;
        int len = 0;
        int res = SWIG_AsVal_long(tmp, &len);
        if(!SWIG_IsOK(res)) {
            free($1);
            SWIG_fail;
        }
        $result = SWIG_From_CharPtrAndSize( $1, len );
        PyDecRef(tmp); //probably?
        free($1);
    }
    

    这会改变 python 端的接口,只接受长度参数并返回一个可能不是你想要的 python 字符串。请注意,你可以返回任何你喜欢的东西,所以你可以创建一些其他的 python 对象,而不是 SWIG_From_CharPtr。

    另一种方法是使用多参数类型映射。这里的细节更加模糊,但你会做类似的事情:

    %typemap(in) (char *buffer, int length)
    {
    /*
    $input is a python object of your choice - bytearray?
    Use the various Python/Swig APIs to decode the input object.
    Set $1 and $2 to the data pointer and length decoded from
    your input object and they will be passed to the C function.
    */
    }
    

    现在你在 python 端有了一个 Read() 函数,它接受一个参数,由你来创建和设置它的大小。只要您能弄清楚如何访问内部数组和大小,就可以是任何东西。 Numpy 是一个非常好的候选者,但如果你使用 Numpy,他们已经为 SWIG 提供了一组非常好的类型映射。然后你就这样做:

    %include "numpy.i"
    %apply( char *IN_ARRAY1, int DIM1 )
    

    并给它一个 numpy 数组。

    【讨论】:

      猜你喜欢
      • 2013-05-15
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      • 1970-01-01
      • 2016-11-26
      • 1970-01-01
      • 1970-01-01
      • 2020-01-12
      相关资源
      最近更新 更多