python - swig python 使用 void ** 接口(interface)连接函数

标签 python c swig

背景。我有一个 API(第三方提供),由 C 头文件和共享库组成。我已经成功地为构建环境创建了一个 shell 脚本,以及一个简单的 swig 接口(interface)文件。我试图让这个 API 可以在 IPython 环境中访问,这样我就不必一直编译 C 代码来与利用该 API 进行 I/O 的相关硬件进行通信。

问题。我需要做的第一个函数调用创建一个板句柄(一些任意的“对象”,用于 C 端的所有其他函数调用。该函数接受 void **,假设底层函数可能是 malloc 内存,具有某种内部结构,并允许通过其他一些函数访问该内存。无论如何,由于缺乏对 void * 的支持,我似乎无法从 Python 正确连接到它并收到类型错误。

有问题的 C 代码片段,以及从底层头文件中提取的 typedef/defines 是:

    #define WD_PVOID  void*
    typedef WD_PVOID   WD_BOARD;
    typedef WD_UINT32  WD_RetCode;
    #define WD_EXPORT  extern
    #define WD_CHAR8  char
    #define WD_UINT32  unsigned int
    #---------------------------------------
    //prototype
    WD_EXPORT WD_RetCode wd_CreateBoardHandle( WD_BOARD *pBoardHandle, const WD_CHAR8  *pUrl );

    //interpreted prototype
    //extern unsigned int wd_CreateBoardHandle( void* *pBoardHandle, const char  *pUrl );

第三方提供的示例(用 C 编写)使用该函数(我删除了多余的东西):

  int main(int argc, char *argv [])
  {
     WD_RetCode rc;
     Vhdl_Example_Opts  cmdOpts = VHDL_EXAMPLE_DEFAULTS;
     char urlBoard[VHDL_SHORT_STRING_LENGTH];
     WD_BOARD           BoardHandle;
     sprintf(urlBoard, "/%s/%s/wildstar7/board%d", cmdOpts.hostVal, cmdOpts.boardDomain, cmdOpts.boardSlot);

     rc = wd_CreateBoardHandle(&BoardHandle,urlBoard);
  }

最后,我的淡化 swig 接口(interface)文件(我一直在尝试 swig typedef 和 *OUTPUT 但没有成功):

    %module wdapi
    %{
    #include "wd_linux_pci.h"
    #include "wd_types.h"
    #include "wd_errors.h"
    %}
    %import "wd_linux_pci.h"
    %import "wd_types.h"
    %import "wd_errors.h"
    %include <typemaps.i>

    WD_EXPORT WD_RetCode wd_CreateBoardHandle( WD_BOARD *pBoardHandle, const WD_CHAR8 *pUrl );

    WD_EXPORT WD_RetCode wd_OpenBoard( WD_BOARD  BoardHandle );

我想要做的是在 python 中调用该函数,如下所示:

    rslt,boardHandle = wdapi.wd_CreateBoardHandle("/foo/bar/etc")

如果我可以提供任何其他信息,请告诉我,我非常感谢您对解决方案的帮助/指导!我花了几天时间尝试查看发布的其他类似问题。

编辑。我操纵了其他具有类似问题的帖子中的一些 typedef。我现在可以调用函数并接收 rslt 和 boardHandle 中的值作为对象;然而,rslt 值似乎是乱码。这是新的 swig 接口(interface)文件(对这个问题有什么想法吗?):

      %module wdapi 
      %{
      #include "wd_linux_pci.h"
      #include "wd_types.h"
      #include "wd_errors.h"
      %}

      %import "wd_linux_pci.h"
      %import "wd_types.h"
      %import "wd_errors.h"
      %include <python/typemaps.i>


      %typemap(argout) WD_BOARD *pBoardHandle 
      {
        PyObject *obj = PyCObject_FromVoidPtr( *$1, NULL );
        $result = PyTuple_Pack(2, $result, obj);
      }

      %typemap(in,numinputs=0) WD_BOARD *pBoardHandle (WD_BOARD temp) 
      {
        $1 = &temp;
      }

      %typemap(in) WD_BOARD {
        $1 = PyCObject_AsVoidPtr($input);
      }


      WD_EXPORT WD_RetCode wd_CreateBoardHandle( WD_BOARD *pBoardHandle, const WD_CHAR8 *pUrl );

      WD_EXPORT WD_RetCode wd_OpenBoard( WD_BOARD  BoardHandle );

      WD_EXPORT WD_RetCode wd_DeleteBoardHandle( WD_BOARD  BoardHandle );

      WD_EXPORT WD_RetCode wd_IsBoardPresent( const WD_CHAR8 *pUrl, WD_BOOL *OUTPUT );

最佳答案

我解决了我自己的问题。编辑后的 ​​swig 接口(interface)文件(在我的原始帖子中列出)最终解决了我的问题。事实证明,在这个过程中,我破坏了 python 中函数调用的输入,并且 API 返回的错误代码是“未定义”。

另一方面,在研究其他选项时,我还发现了“ctypes”,它首先给我带来了解决方案。 ctypes 允许我直接访问它并且更容易,而不是处理包装器代码并构建第二个共享库(调用另一个)。我仍然会评估我将继续前进。下面列出了 ctypes python 代码以进行比较(查看我在原始帖子中列出的 c 代码示例):

    from ctypes import cdll
    from ctypes import CDLL
    from ctypes import c_void_p
    from ctypes import addressof
    from ctypes import byref

    import sys

    #Update Library Path for shared API library
    sys.path.append('/usr/local/lib');

    #Load the API and make accessible to Python
    cdll.LoadLibrary("libwdapi.so")
    wdapi = CDLL("libwdapi.so")

    #Create the url for the board
    urlBoard='/<server>/<boardType>/<FGPAType>/<processingElement>'

    #Lets create a void pointer for boardHandle object
    pBoardHandle=c_void_p()


    #now create & open the board
    rtn = wdapi.wd_CreateBoardHandle(byref(pBoardHandle),urlBoard)
    if (rtn) :
      print "Error"
    else :
      print "Success"

关于python - swig python 使用 void ** 接口(interface)连接函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32331470/

相关文章:

c# - 使用 SWIG 从 C++ 回调到 C#

python - 从 YAML 加载序列化对象并用它替换当前对象

python - 地理 Pandas : sort a sample of points like a cycle graph

python - 通过不在主脚本中的方法更新 Qt 界面中的文本

c - 第一次循环运行后,我卡在了开关内的默认情况下

使用 SWIG 的 C++ 的 Python 包装器

python - 构建引用 .PYD 的 Python 包/模块的正确方法是什么?

python - 将简单 Python 脚本转换为 Windows 可执行文件的过程

malloc 在 struct 上的 C 用法

c - C 中的循环不会中断