编辑:Documentation for the relevant library methods!
完全公开-我对C/C++几乎一无所知,对指针、缓冲区和所有有趣的东西也一无所知。如果这是一个愚蠢的问题,我深表歉意,但我已经为此工作了几个小时,根本没有走多远
所以我有一个外部C库,我从Ruby脚本中引用它。我需要访问一系列不同的函数,我有一些简单的函数可以使用,但我正在努力处理一个更复杂的函数
好的方面是,我有Python的工作示例代码
我面临的挑战是关于使用FFI的整个缓冲区方面——我还没有找到很多相关的例子来说明如何实现这一点,我有点挣扎
下面是我想用FFI在Ruby中复制的函数:
def getActiveID32():
"""
Will return a tuple consisting number of bits
read and actual data. Minimum 8 byte of data will
be returned.
"""
rawData = ""
buffer_size = ctypes.c_short(32);
pcproxlib.GetActiveID32.restype = ctypes.c_short
# create a buffer of given size to pass it
# to get the raw data.
raw_data_tmp = (ctypes.c_ubyte * buffer_size.value)()
#as per documentation 250 millisecond sleep is required
# to get the raw data.
time.sleep(250/1000.0)
nbBits = pcproxlib.GetActiveID32(raw_data_tmp , buffer_size)
bytes_to_read = int((nbBits + 7) / 8) ;
# will read at least 8 bytes
if bytes_to_read < 8:
bytes_to_read = 8
for i in range(0 , bytes_to_read):
temp_buf = "%02X " % raw_data_tmp[i]
rawData = temp_buf + rawData
return (nbBits , rawData)
下面是我为简单函数(例如BeepNow
)编写的示例代码,但不是为这个更复杂的函数getActiveID32
编写的
其中包含了我一直在使用的代码,但这显然过于简化,不起作用
require 'ffi'
module PCProxLib
extend FFI::Library
ffi_lib File.expand_path('lib/32/libhidapi-hidraw.so.0')
ffi_lib File.expand_path('lib/32/libpcProxAPI.so')
attach_function :usbConnect, [], :short
attach_function :getPartNumberString, [], :string
attach_function :getActiveID32, [:string, :int], :int
attach_function :getActiveID, [], :int
attach_function :BeepNow, [:int, :bool], :bool
end
puts PCProxLib.usbConnect()
puts PCProxLib.BeepNow(3, false)
sleep 0.25
buffer = ""
puts PCProxLib.getActiveID32(buffer, 64)
puts buffer
感谢您的帮助:)
编辑:
根据@matt的评论,我将代码修改为:
require 'ffi'
module PCProxLib
extend FFI::Library
ffi_lib File.expand_path('lib/32/libhidapi-hidraw.so.0')
ffi_lib File.expand_path('lib/32/libpcProxAPI.so')
attach_function :usbConnect, [], :short
attach_function :USBDisconnect, [], :short
attach_function :getActiveID32, [:pointer, :int], :int
end
PCProxLib.usbConnect()
puts PCProxLib.getPartNumberString() // verifying connection to reader
def read_card
sleep 0.5
buffer = FFI::MemoryPointer.new(:uint8, 32)
bits_written = PCProxLib.getActiveID32(buffer, 32)
puts bits_written
puts buffer.read_bytes(32)
end
20.times { read_card }
PCProxLib.USBDisconnect()
当我扫描一张卡(代码循环时,bits_written
值从0跳到32,这看起来不错。但是buffer.read_bytes(32)
值始终为空
我尝试过其他一些MemoryPointer方法(如read
,read_string
等),但得到了相同的结果
如果我尝试.inspect
使用buffer.read_bytes(32)
,我会得到:
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
…哪个有趣?这是一样的,无论我是否扫描一张卡
函数
getActiveID32
的签名看起来像您可以使用它,首先创建一个要写入的缓冲区,然后在调用它时将指向该缓冲区的指针及其大小作为参数传递,类似于:
使用Ruby的FFI,您可以使用Pointer实现这一点。首先声明函数以接受指针(字符串类似于指针,但在本例中,我们需要直接使用指针):
现在,当您想要调用它时,首先需要创建一个所需大小的
MemoryPointer
,并将其作为参数传递给函数。然后,FFI将在调用C函数时将其转换为指向已分配内存的指针现在} 访问该数据,例如,要将该数据复制到可以使用
buffer
将包含函数写入的数据。您可以使用methods on ^{buffer.read_bytes(32)
的Ruby(二进制)字符串中MemoryPointer
还将处理在垃圾收集时释放分配的内存相关问题 更多 >
编程相关推荐