Page 1 of 1

any alternative to ffi.string for reading from ByteData ?

Posted: Thu Dec 02, 2021 6:39 pm
by yal2du
Is there any way to read from an allocated love ByteData object besides using ffi.string ( or a trivial c library imported with ffi.load )?
e.g.

Code: Select all

local mem = love.data.newByteData(2 ^ 31)              -- 2 GB
local ptr = ffi.cast('uint8_t*', mem:getFFIPointer())  -- PVOID

local testkey = '0123456789ABCDE'
local length  = #testkey

ffi.copy(ptr,testkey,length)
ffi.copy(ptr + length,testkey,length)

local whole = ffi.string(ptr,length*2)
print(whole)

local index = 3
local out = ffi.string(ptr+index,1)
print(out)

Motivated by three things: 1) avoiding string interning of millions of temporary strings, 2) avoiding the garbage collector, 3) working with very large, contiguous arrays of (32-bit unsigned) integers.

Re: any alternative to ffi.string for reading from ByteData ?

Posted: Thu Dec 02, 2021 7:24 pm
by grump
You have a pointer to the data, of type uint8_t* in this case, which means it's a pointer to byte values. You can access that memory like a 0-based sequential Lua table that contains byte values.

Code: Select all

local byte100 = ptr[99] -- get the 100th byte out of the allocated data
You can cast the pointer to any ctype you want and access the memory accordingly. If you want to access the memory in units of uint32_t, then just cast it to uint32_t*

Code: Select all

local uint32array = ffi.cast('uint32_t*', mem:getFFIPointer())
uint32array[0] = 0xdeadbeef -- tada
There's no way around ffi.string if you want to use the data as a string.

Re: any alternative to ffi.string for reading from ByteData ?

Posted: Thu Dec 02, 2021 7:38 pm
by yal2du
Well that makes too much sense. :ultrahappy: Thank you very much for the clear explanation!