[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Ruby/DL and functions that modify a pointer

Ben Giddings

2/2/2005 2:15:00 AM

I just started using Ruby/DL and am amazed at what it can do. I've
almost got a really impressive demo to show off to my cow-orkers, but I
have one cow left to ork... er... I have one thing left to figure out.

Given some C code like this:

typdef struct {
int status;
int results[16];
} foo_t;

int get_results(handle_t the_handle, foo_t *results_ptr)
{
results_ptr->status = 0;
results_ptr->results[0] = 0xFF;

return 0;
}

How do I interface to that code in Ruby/DL?

I already have functions that take handles, I just treat it as a pointer
and everything works great:

require 'dl/import'
module LIBMYAPI
extend DL::Importable
dlload "./libmyapi.so.1.0.1"
typealias("size_t", "unsigned int")
typealias("id_t", "int")
extern "void *open_handle(char *)"
extern "char *get_version(void *)"
extern "int close_handle(void *)"
end

if __FILE__ == $0
hostname = 'foo'

handle = LIBMYAPI.open_handle("m4-c0050c")
result = LIBMYAPI.get_version(handle)
puts result
LIBM4API.close_handle(handle)
end

I just don't know how to tell Ruby/DL that get_results takes a pointer,
then changes it.

While I'm at it, what's the proper way to deal with a structure
containing an array, if you want to access things by name?

Something like this works for the 'timeval' struct, but I don't know how
to use it with structs containing arrays.

ptr = DL.malloc(DL.sizeof('LL'))
ptr.struct!('LL', :tv_sec, :tv_usec)
ptr[:tv_sec] = 10
ptr[:tv_usec] = 100
sec = ptr[:tv_sec]
usec = ptr[:tv_usec]

Thanks!

Ben


7 Answers

Takaaki Tateishi

2/3/2005 2:52:00 PM

0

Ben Giddings wrote:
> Something like this works for the 'timeval' struct, but I don't know how
> to use it with structs containing arrays.

Please use the method 'struct' like 'extern', and the following example
shows how to use it.


require 'dl/import'
require 'dl/struct'

module MyLIB
extend DL::Importable

MyStruct = struct [
"int foo[3]",
]
end

ptr = MyLIB::MyStruct.malloc()
ptr.foo = [0,1,2]
p ptr.foo


But I found a bug on 'dl/struct.rb', so please replace it with the following file.
http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/lib/dl/struct.rb?rev=1.8.2.4;content-type=text%2Fplain;only_with_ta...
--
Takaaki Tateishi <ttate@ttsky.net>


Ben Giddings

2/3/2005 4:26:00 PM

0

Takaaki Tateishi wrote:
> Please use the method 'struct' like 'extern', and the following example
> shows how to use it.
>
>
> require 'dl/import'
> require 'dl/struct'
>
> module MyLIB
> extend DL::Importable
>
> MyStruct = struct [
> "int foo[3]",
> ]
> end
>
> ptr = MyLIB::MyStruct.malloc()
> ptr.foo = [0,1,2]
> p ptr.foo
>
>
> But I found a bug on 'dl/struct.rb', so please replace it with the
> following file.
> http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/lib/dl/struct.rb?rev=1.8.2.4;content-type=text%2Fplain;only_with_ta...

Thanks so much for your help Takaaki,

Do you know the answer to the other question? How to wrap a function
that modifies a structure you pass in?

For example:

#define VALID_DATA 1
#define ERROR 0

int get_data(struct mystruct *data_ptr)
{
if (error_happened())
{
return ERROR;
}
else
{
data_ptr->foo[0] = 0;
data_ptr->foo[1] = 0xFF;
}
}


How do I write Ruby/DL code that uses this function to get data out of
data_ptr?

I noticed that when using the Ruby/DL Symbols, calls like atoi["1"]
returns two things, the result and the args. Would these args contain
the modified structure?

The type of function I want to access from Ruby is "scanf" type
functions where the return value isn't the only data returned.

Thanks,

Ben


Asbjørn Reglund Thorsen

2/4/2005 7:31:00 AM

0

Takaaki Tateishi

2/4/2005 9:52:00 AM

0

Ben Giddings wrote:
> Do you know the answer to the other question? How to wrap a function
> that modifies a structure you pass in?

Just use 'extern' as follows:

module MyLIB
extend Importable
dlload "...."
MyStruct = struct [
"int foo[3]",
]
extern "int get_data(void*)"
end

ptr = MyLIB::MyStruct.malloc()
MyLIB.get_data(ptr)
--
Takaaki Tateishi <ttate@ttsky.net>


Lyle Johnson

2/4/2005 1:48:00 PM

0

On Fri, 4 Feb 2005 16:30:32 +0900, Asbjørn Reglund Thorsen
<asbjoert@ifi.uio.no> wrote:

> This is what I tried, but did not work:
>
> %typemap(out) int &{ //C->Ruby, Back to Ruby int object
> long *n = (long *) $1;
> $result = INT2NUM(*n);
> }

This one won't generate a compiler error (well, it didn't for me) but
it's dangerous to cast the return value, which is a pointer-to-int, to
a pointer-to-long. Here's a better version of this typemap:

%typemap(out) int & {
$result = INT2NUM(*$1);
}

> %typemap(in) int &{ //Ruby->C, From Ruby integer to C long
> $1 = NUM2INT($input);
> }

OK, this is the one that generated the compiler error you saw. Here's
a corrected version:

%typemap(in) int & (int tmp) {
tmp = NUM2INT($input);
$1 = &tmp;
}

Hope this helps,

Lyle



Ben Giddings

2/4/2005 8:49:00 PM

0

Takaaki Tateishi wrote:
>> Do you know the answer to the other question? How to wrap a function
>> that modifies a structure you pass in?
>
>
> Just use 'extern' as follows:
>
> module MyLIB
> extend Importable
> dlload "...."
> MyStruct = struct [
> "int foo[3]",
> ]
> extern "int get_data(void*)"
> end
>
> ptr = MyLIB::MyStruct.malloc()
> MyLIB.get_data(ptr)


Thanks so much Takaaki, that works perfectly, I'm now wrapping a library
and doing some pretty impressive things, all in less than 100 lines of
Ruby code!

Ben


Asbjørn Reglund Thorsen

2/5/2005 10:11:00 AM

0