DomRibaut | 2 Aug 02:23 2011
Picon

mapping of unsigned char encoded_data[178][143] in a struct

Hello
I need to read a field defined as shown above in a struct.
I used :encoded_data, [[:uchar, 178], 143] but when I try to access it
I get an error message ArgumentError: get not supported for
FFI::ArrayType
the type of the array is FFI::Struct::InlineArray.
I would greatly apreciate any advice for this mapping or any pointer
to the relevant documentation.

BR.
Dominique

Wayne Meissner | 2 Aug 05:18 2011
Picon

Re: mapping of unsigned char encoded_data[178][143] in a struct

2D arrays in structs are not supported by FFI - there's an issue for it (issue #18), but its not exactly a high priority, since only 2 people have asked for it in the last 2 years.


You can work around it by declaring a struct type for the array width, then declaring an array of that struct type.
e.g.

#require 'rubygems'
require 'ffi'

class DataArray < FFI::Struct
  layout :array, [ :uchar, 178 ]

  def [](idx)
    if idx.is_a?(Integer)
      self[:array][idx]
    else
      super(idx)
    end
  end

  def []=(idx, val)
    if idx.is_a?(Integer)
      self[:array][idx] = val
    else
      super(idx, val)
    end
  end
end

class Array2D < FFI::Struct
  layout :encoded_data, [ DataArray, 143 ]
end

ary = Array2D.new
ary[:encoded_data][0][0] = 0x1
ary[:encoded_data][0][1] = 0x2
ary[:encoded_data][0][2] = 0x3
ary[:encoded_data][1][0] = 0x4
ary[:encoded_data][2][0] = 0x5
ary[:encoded_data][3][0] = 0x6


puts "ary[:encoded_data][0][0]=#{ary[:encoded_data][0][0]}"
puts "ary[:encoded_data][0][1]=#{ary[:encoded_data][0][1]}" 
puts "ary[:encoded_data][1][0]=#{ary[:encoded_data][1][0]}"
# idx=178 should correspond to ary[:encoded_data][1][0]
puts "ary.pointer.get_char(178)=#{ary.pointer.get_char(178)}"
# idx=356 should correspond to ary[:encoded_data][2][0]
puts "ary.pointer.get_char(356)=#{ary.pointer.get_char(356)}"


Dominique Ribaut | 2 Aug 07:27 2011
Picon

Re: Re: mapping of unsigned char encoded_data[178][143] in a struct

Tanks a lot for a detailed answer :-)
Dominique

Den 2. aug. 2011 05.18 skrev "Wayne Meissner" <wmeissner-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> følgende:
> 2D arrays in structs are not supported by FFI - there's an issue for it
> (issue #18), but its not exactly a high priority, since only 2 people have
> asked for it in the last 2 years.
>
> You can work around it by declaring a struct type for the array width, then
> declaring an array of that struct type.
> e.g.
>
> #require 'rubygems'
> require 'ffi'
>
> class DataArray < FFI::Struct
> layout :array, [ :uchar, 178 ]
>
> def [](idx)
> if idx.is_a?(Integer)
> self[:array][idx]
> else
> super(idx)
> end
> end
>
> def []=(idx, val)
> if idx.is_a?(Integer)
> self[:array][idx] = val
> else
> super(idx, val)
> end
> end
> end
>
> class Array2D < FFI::Struct
> layout :encoded_data, [ DataArray, 143 ]
> end
>
> ary = Array2D.new
> ary[:encoded_data][0][0] = 0x1
> ary[:encoded_data][0][1] = 0x2
> ary[:encoded_data][0][2] = 0x3
> ary[:encoded_data][1][0] = 0x4
> ary[:encoded_data][2][0] = 0x5
> ary[:encoded_data][3][0] = 0x6
>
>
> puts "ary[:encoded_data][0][0]=#{ary[:encoded_data][0][0]}"
> puts "ary[:encoded_data][0][1]=#{ary[:encoded_data][0][1]}"
> puts "ary[:encoded_data][1][0]=#{ary[:encoded_data][1][0]}"
> # idx=178 should correspond to ary[:encoded_data][1][0]
> puts "ary.pointer.get_char(178)=#{ary.pointer.get_char(178)}"
> # idx=356 should correspond to ary[:encoded_data][2][0]
> puts "ary.pointer.get_char(356)=#{ary.pointer.get_char(356)}"
>
>

przemo_li | 19 Aug 11:02 2011
Picon

Callback support in FFI?

I'm trying to implement freeGLUT bindings. Is it possible? I need to
declare function that takes callback function without any parameters.
Any luck with FFI?

PS add info about callback in wiki!

Wayne Meissner | 19 Aug 12:46 2011
Picon

Re: Callback support in FFI?


There is a qsort example which takes callbacks at
https://github.com/ffi/ffi/blob/master/samples/qsort.rb and some more
examples in https://github.com/ffi/ffi/wiki/Examples

On Aug 19, 7:02 pm, przemo_li <an.prze...@...> wrote:
> I'm trying to implement freeGLUT bindings. Is it possible? I need to
> declare function that takes callback function without any parameters.
> Any luck with FFI?
>
> PS add info about callback in wiki!

przemo_li | 19 Aug 13:48 2011
Picon

Re: Callback support in FFI?

Aghhh!
Do not know how I could missed it. BIG thx!

BTW will it also work
method(ruby_method_name).to_proc
for suppling call back to C-function?

On Aug 19, 12:46 pm, Wayne Meissner <wmeiss...@...> wrote:
> There is a qsort example which takes callbacks
athttps://github.com/ffi/ffi/blob/master/samples/qsort.rband some more
> examples inhttps://github.com/ffi/ffi/wiki/Examples
>
> On Aug 19, 7:02 pm, przemo_li <an.prze...@...> wrote:
>
>
>
>
>
>
>
> > I'm trying to implement freeGLUT bindings. Is it possible? I need to
> > declare function that takes callback function without any parameters.
> > Any luck with FFI?
>
> > PS add info about callback in wiki!

przemo_li | 19 Aug 15:36 2011
Picon

How to declare (int *argc, char *argv)?

I'm trying to do my own bindings for freeGLUT, but fail at:

FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv )

how to declare it with ruby ffi?
Then how to pass argc, argv? (ruby seam to have no such thing)

przemo_li | 19 Aug 15:38 2011
Picon

Re: How to declare (int *argc, char *argv)?

Oh
FGAPI and FGAPIENTRY have no meaning on Linux and I care only about
Linux support.

/* Non-Windows definition of FGAPI and FGAPIENTRY */
# define FGAPI
# define FGAPIENTRY

On Aug 19, 3:36 pm, przemo_li <an.prze...@...> wrote:
> I'm trying to do my own bindings for freeGLUT, but fail at:
>
> FGAPI void FGAPIENTRY glutInit( int* pargc, char** argv )
>
> how to declare it with ruby ffi?
> Then how to pass argc, argv? (ruby seam to have no such thing)

cfis | 20 Aug 06:57 2011

How to specify size for returned buffer?

I'm trying to wrap FreeImage (http://freeimage.sourceforge.net/) and
it has this function:

DLL_API BOOL DLL_CALLCONV FreeImage_AcquireMemory(FIMEMORY *stream,
BYTE **data, DWORD *size_in_bytes);

The way this works is you hand FreeImage a pointer (data) which it
then allocates memory for and returns the size in the size_in_bytes
out parameter.  I've attached example C code from the FreeImage docs
in case it helps.

So I'm not sure how to wrap this function.  So far I have this:

FreeImage.attach_function('FreeImage_AcquireMemory',
[:pointer, :pointer, :uint], :bool)

buffer = MemoryPointer.new(:pointer)
size_ptr = MemoryPointer.new(:uint)
FreeImage.FreeImage_AcquireMemory(self, buffer, size);

What I would then like to do is something like:

buffer.size = size_ptr.read_pointer()

But buffer doesn't have any such API.

Any help appreciated.

Thanks,

Charlie
------------
void testAcquireMemIO(const char *lpszPathName) {
  FIMEMORY *hmem = NULL;
  // load a regular file
  FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName);
  FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, 0);

  // open and allocate a memory stream
  hmem = FreeImage_OpenMemory();

  // save the image to a memory stream
  FreeImage_SaveToMemory(FIF_PNG, dib, hmem, PNG_DEFAULT);
  FreeImage_Unload(dib);

  // get the buffer from the memory stream
  BYTE *mem_buffer = NULL;
  DWORD size_in_bytes = 0;
  FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes);

  // save the buffer to a file stream
  FILE *stream = fopen("buffer.png", "wb");
  if(stream) {
    fwrite(mem_buffer, sizeof(BYTE), size_in_bytes, stream);
    fclose(stream);
  }
  // close and free the memory stream
  FreeImage_CloseMemory(hmem);
}

przemo_li | 20 Aug 09:59 2011
Picon

Re: How to specify size for returned buffer?

Why do you need "buffer" having ".size". Cant you pack both variables
into class instance that do "anything" you want buffer to do?
You know Ruby FFI to extract data, Ruby Class to encapsulate it and
add
custom behavior.

On 20 Sie, 06:57, cfis <c...@...> wrote:
> I'm trying to wrap FreeImage (http://freeimage.sourceforge.net/) and
> it has this function:
>
> DLL_API BOOL DLL_CALLCONV FreeImage_AcquireMemory(FIMEMORY *stream,
> BYTE **data, DWORD *size_in_bytes);
>
> The way this works is you hand FreeImage a pointer (data) which it
> then allocates memory for and returns the size in the size_in_bytes
> out parameter.  I've attached example C code from the FreeImage docs
> in case it helps.
>
> So I'm not sure how to wrap this function.  So far I have this:
>
> FreeImage.attach_function('FreeImage_AcquireMemory',
> [:pointer, :pointer, :uint], :bool)
>
> buffer = MemoryPointer.new(:pointer)
> size_ptr = MemoryPointer.new(:uint)
> FreeImage.FreeImage_AcquireMemory(self, buffer, size);
>
> What I would then like to do is something like:
>
> buffer.size = size_ptr.read_pointer()
>
> But buffer doesn't have any such API.
>
> Any help appreciated.
>
> Thanks,
>
> Charlie
> ------------
> void testAcquireMemIO(const char *lpszPathName) {
>   FIMEMORY *hmem = NULL;
>   // load a regular file
>   FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName);
>   FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, 0);
>
>   // open and allocate a memory stream
>   hmem = FreeImage_OpenMemory();
>
>   // save the image to a memory stream
>   FreeImage_SaveToMemory(FIF_PNG, dib, hmem, PNG_DEFAULT);
>   FreeImage_Unload(dib);
>
>   // get the buffer from the memory stream
>   BYTE *mem_buffer = NULL;
>   DWORD size_in_bytes = 0;
>   FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes);
>
>   // save the buffer to a file stream
>   FILE *stream = fopen("buffer.png", "wb");
>   if(stream) {
>     fwrite(mem_buffer, sizeof(BYTE), size_in_bytes, stream);
>     fclose(stream);
>   }
>   // close and free the memory stream
>   FreeImage_CloseMemory(hmem);
>
>
>
>
>
>
>
> }


Gmane