From: Aston Date: 2009-05-09T18:48:33+09:00 Subject: [ruby-core:23407] ruby-ffi problem --0-874654018-1241862508=:97420 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hello,=0A=0AI am trying to learn ruby-ffi now (after sadly leaving dl libra= ry), I have some trouble here too=0A=0AI will present a simple example wher= e I want to pass a struct between ruby and C=0AI am facing problems while s= etting fields of struct if that field is of type string(char*, not char[])= =0AI understand we have to allocate the char* field of struct first than as= sign some literal srting=0A=0Aconsider the C file=0A=0A********************= ** C FILE**********************=0A#include =0A#include = =0A#include =0A=0Atypedef struct=0A{=0A char *name;=0A doub= le val;=0A} INFO, *INFO_PTR;=0A=0AINFO_PTR create( char* name, double val)= =0A{=0A INFO_PTR p =3D (INFO_PTR)malloc( sizeof(INFO));=0A p->val =3D= val;=0A p->name =3D (char*)malloc( strlen(name) + 1);=0A strcpy( p->= name, name);=0A return p;=0A}=0A=0Aint show( INFO_PTR pInfo)=0A{=0A r= eturn printf( "%s - %f\n", pInfo->name, pInfo->val);=0A}=0A=0A*************= ********* END C FILE**********************=0A=0A********************** RUBY= FILE**********************=0Arequire 'ffi'=0A=0Amodule LibTest=0A class I= nfo < FFI::Struct=0A layout :name, :string,=0A :val, :double= =0A end=0A=0A extend FFI::Library=0A ffi_lib "./libtest.so"=0A attach_f= unction :create, [:string, :double], :pointer=0A attach_function :show, [:= pointer], :int=0Aend=0A=0Ainclude FFI=0A=0Aptr =3D LibTest.create( "test st= ring", 11.27)=0Aobj =3D LibTest::Info.new(ptr)=0ALibTest.show(ptr)=0Aobj[:v= al] =3D 27.11 # this works=0A# obj[:name] =3D "new string" # this gives err= or, `[]=3D': Cannot set :string fields (ArgumentError)=0ALibTest.show(ptr)= =0A********************** END RUBY FILE**********************=0A=0Ahow can = I set string values from ruby ?=0AIf I refuse to declare name field as type= char[] from char* then I have to allocate before I can assign=0Athen my ap= proach below core dumps :(=0A=0A1 str =3D "test string"=0A2 p =3D MemoryPoi= nter.new( str.size)=0A3 p.write_string(str)=0A4 puts p.read_string # "test = string"=0A5 obj[:name].write_pointer(p) # core dumps here!=0A=0Aline # 5 co= re dumps everytime one tries to write anything there, since pointer is inva= lid I guess=0Ahow do I allocate memory there ? once allocated can i treat t= hat allocated memory as ruby string ?=0A=0AGoal I want to achieve is I shal= l allocate in ruby, assign in ruby and pass in to C code only for modificat= ion or read only purpose=0Ahow do I go from here ? can you comment on this = ?=0A=0AAston=0A=0A=0A Cricket on your mind? Visit the ultimate cricket= website. Enter http://beta.cricket.yahoo.com --0-874654018-1241862508=:97420 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable
Hello,

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

I wil= l 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 cha= r* field of struct first than assign some literal srting

consider th= e C file

********************** C FILE**********************
#inc= lude <stdlib.h>
#include <stdio.h>
#include <string.h&= gt;

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

INFO_PTR create( char* name, double val)
{
    INFO_PTR p =3D (INFO_PT= R)malloc( sizeof(INFO));
    p->val =3D val;
 =    p->name =3D (char*)malloc( strlen(name) + 1);
 &nbs= p;  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
  cla= ss Info < FFI::Struct
    layout :name, :string,
&n= bsp;          :val, :double  end

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

include FFI

ptr =3D LibTest.create( "test string", 11.27)
obj =3D LibTes= t::Info.new(ptr)
LibTest.show(ptr)
obj[:val] =3D 27.11 # this works# obj[:name] =3D "new string" # this gives error, `[]=3D': Cannot set :st= ring 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 dump= s :(

1 str =3D "test string"
2 p =3D 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 every= time one tries to write anything there, since pointer is invalid I guesshow 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 o= nly purpose
how do I go from here ? can you comment on this ?

Ast= on


=0A=0A=0A
N= ow surf faster and smarter ! Check out the new Firefox 3 - Yahoo! Edition *= Click here! --0-874654018-1241862508=:97420--