Ruby-ffi problem


#1

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 :frowning:

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§ # 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 

#2

You probably want to take this to the ruby-ffi project here:

http://kenai.com/projects/ruby-ffi


#3

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 A.