Forum: Ruby ruby-ffi problem

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
C306d9e1df9a8b3c65830547618cc7fb?d=identicon&s=25 Aston (Guest)
on 2009-05-09 11:50
(Received via mailing list)
Hello,

I am trying to learn ruby-ffi now (after sadly leaving dl library), I
have some trouble here too

I will present a simple example where I want to pass a struct between
ruby and C
I am facing problems while setting fields of struct if that field is of
type string(char*, not char[])
I understand we have to allocate the char* field of struct first than
assign some literal srting

consider the C file

********************** C FILE**********************
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct
{
    char *name;
    double val;
} INFO, *INFO_PTR;

INFO_PTR create( char* name, double val)
{
    INFO_PTR p = (INFO_PTR)malloc( sizeof(INFO));
    p->val = val;
    p->name = (char*)malloc( strlen(name) + 1);
    strcpy( p->name, name);
    return p;
}

int show( INFO_PTR pInfo)
{
    return printf( "%s - %f\n", pInfo->name, pInfo->val);
}

********************** END C FILE**********************

********************** RUBY FILE**********************
require 'ffi'

module LibTest
  class Info < FFI::Struct
    layout :name, :string,
           :val, :double
  end

  extend FFI::Library
  ffi_lib "./libtest.so"
  attach_function :create, [:string, :double], :pointer
  attach_function :show, [:pointer], :int
end

include FFI

ptr = LibTest.create( "test string", 11.27)
obj = LibTest::Info.new(ptr)
LibTest.show(ptr)
obj[:val] = 27.11 # this works
# obj[:name] = "new string" # this gives error, `[]=': Cannot set
:string fields (ArgumentError)
LibTest.show(ptr)
********************** END RUBY FILE**********************

how can I set string values from ruby ?
If I refuse to declare name field as type char[] from char* then I have
to allocate before I can assign
then my approach below core dumps :(

1 str = "test string"
2 p = MemoryPointer.new( str.size)
3 p.write_string(str)
4 puts p.read_string # "test string"
5 obj[:name].write_pointer(p) # core dumps here!

line # 5 core dumps everytime one tries to write anything there, since
pointer is invalid I guess
how do I allocate memory there ? once allocated can i treat that
allocated memory as ruby string ?

Goal I want to achieve is I shall allocate in ruby, assign in ruby and
pass in to C code only for modification or read only purpose
how do I go from here ? can you comment on this ?

Aston


      Cricket on your mind? Visit the ultimate cricket website. Enter
http://beta.cricket.yahoo.com
Ede2aa10c6462f1d825143879be59e38?d=identicon&s=25 Charles Oliver Nutter (Guest)
on 2009-05-09 20:19
(Received via mailing list)
You probably want to take this to the ruby-ffi project here:

http://kenai.com/projects/ruby-ffi
40e5e9fe36a1f85166493faac2c17499?d=identicon&s=25 Hirotsugu Asari (Guest)
on 2009-05-10 01:56
(Received via mailing list)
If you want to change the string value of a field in a struct through
FFI, I suggest using the ":pointer" rather than ":string".

=cut

require 'rubygems'
require 'ffi'

module LibTest
   class Info < FFI::Struct
     layout :name, :pointer,
            :val, :double
   end

   extend FFI::Library
   ffi_lib './libtest.dylib'
   attach_function :create, [:string, :double], :pointer
   attach_function :show, [:pointer], :int
end

include FFI

ptr = LibTest.create( "test string", 11.27)
obj = LibTest::Info.new(ptr)
LibTest.show(ptr)
obj[:val] = 27.11
obj[:name].put_bytes(0,'new string')
LibTest.show(ptr)

=end


In the long run, as Charlie suggested, your question will be better
answered by ruby-ffi project.

--
Hirotsugu Asari
This topic is locked and can not be replied to.