背景。我有一个API(第三方提供),包括C头文件和共享库。我已经设法为构建环境创建一个shell脚本,以及一个用于swig的简单接口文件。我正在尝试使这个API可以访问IPython环境,这样我就不必一直编译C代码来与利用此API进行I / O的相关硬件进行通信。
问题。我需要做的第一个函数调用创建一个板句柄(一些任意“对象”,用于C端的所有其他函数调用。该函数接受一个void **,假设底层函数可能是malloc-ing memory ,有一些内部结构,并允许通过其他一些函数访问这个内存。无论如何,由于缺乏对void *的支持而接收到一个typeError,我似乎无法从Python正确地与它接口。
从基础头文件中提取的typedef's / definitions的违规C代码段是:
#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接口文件(我一直在尝试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")
如果我能提供任何其他信息,请告诉我,我非常感谢您对解决方案的帮助/指导!我花了几天的时间试图查看发布的其他类似问题。
EDIT。我操纵了一些类似问题的其他帖子的typedef。我现在能够调用函数并在rslt和boardHandle中接收一个值作为对象;然而,似乎rslt值是乱码。这是新的swig界面文件(关于问题的任何想法?):
%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 );
答案 0 :(得分:1)
我解决了自己的问题。上面在我的原始帖子中列出的已编辑的swig界面文件最终证实了我的问题。原来在某处,我在python中将输入修改为我的函数调用,返回的错误代码为&#34; undefined&#34;来自API。
另一方面,在调查其他选项时,我也找到了&#34; ctypes&#34;这让我先解决了问题。而不是处理包装器代码和构建第二个共享库(调用另一个),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"