EDIT: Documentation for the relevant library methods!
Full disclosure - I know next to nothing about C/C++ and literally nothing about pointers and buffers and all that fun stuff. Apologies if this is a stupid question, but I've been working on this for hours and haven't got very far at all.
So I have an external C library that I'm referencing from a Ruby script. There's a bunch of different functions which I need to access, and I've got some simple ones working, but I'm struggling with a more complicated function that I need to work.
The good part - I have working example code in Python.
The challenge I'm facing is around the whole buffer side of things using FFI - I've not found a lot of relevant examples on how to make this work, and I'm struggling a bit.
Here's the function I want to replicate in Ruby using FFI:
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)
Here's the example code that I have working for the simple functions (eg BeepNow
but not for this more complicated function, getActiveID32
.
Included is the code I've been playing with, but that is clearly too simplified, and doesn't work.
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
Thanks heaps for any help :)
EDIT:
Based on @matt's comment, I've revised the code to the following:
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()
When I scan a card (while the code is looping), the bits_written
value jumps from 0 to 32, which seems good. However the buffer.read_bytes(32)
value is always null.
I've tried some other MemoryPointer methods (like read
, read_string
etc but get the same results.
If I try .inspect
ing the buffer.read_bytes(32)
, I get:
"\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"
...which is interesting? This is the same, whether I scan a card or not.