[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Stack, Struct and DL

lucsky

3/23/2005 4:48:00 PM

Greetings,

Suppose that I have the following C code:

typedef struct FOO
{
int bar;
int baz;
};

FOO make_a_foo( void )
{
FOO foo;
foo.bar = 42;
foo.baz = 1;

return foo;
}

I'm struggling to find the correct way (if it's even possible) to get my
hands on the struct returned by 'make_a_foo', using ruby/dl.

I smell some troubles.

--
Luc Heinrich - lucsky@mac.com
8 Answers

Eric Hodel

3/23/2005 7:48:00 PM

0

On 23 Mar 2005, at 08:49, Luc Heinrich wrote:

> Greetings,
>
> Suppose that I have the following C code:
>
> typedef struct FOO
> {
> int bar;
> int baz;
> };
>
> FOO make_a_foo( void )
> {
> FOO foo;
> foo.bar = 42;
> foo.baz = 1;
>
> return foo;
> }
>
> I'm struggling to find the correct way (if it's even possible) to get
> my
> hands on the struct returned by 'make_a_foo', using ruby/dl.
>
> I smell some troubles.

I had just this problem a few days ago [ruby-talk:134052].

Takaaki Tateishi had the solution in [ruby-talk:134057].

module Stuff
FOO = struct [
"int bar",
"int baz"
]

extern "FOO make_a_foo(void)"

def my_make_a_foo
return FOO.new(make_a_foo)
end

end

I think.

--
Eric Hodel - drbrain@segment7.net - http://se...
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

lucsky

3/23/2005 8:47:00 PM

0

Eric Hodel <drbrain@segment7.net> wrote:

> module Stuff
> FOO = struct [
> "int bar",
> "int baz"
> ]
>
> extern "FOO make_a_foo(void)"
>
> def my_make_a_foo
> return FOO.new(make_a_foo)
> end
>
> end

Interesting, but that didn't work for me:

/usr/local/lib/ruby/1.8/dl/import.rb:125:in `symbol': can't find the
symbol `make_a_foo' (RuntimeError)

--
Luc Heinrich - lucsky@mac.com

lucsky

3/23/2005 8:59:00 PM

0

Luc Heinrich <lucsky@mac.com> wrote:

> /usr/local/lib/ruby/1.8/dl/import.rb:125:in `symbol': can't find the
> symbol `make_a_foo' (RuntimeError)

And to make sure we're on the same page, here's exactly what I do (this,
of course, is just a test case to reproduce a problem that I have in a
bigger project ;) ):

[ ------- foo.c ------ ]

typedef struct
{
int bar;
int baz;
} FOO;

FOO make_a_foo( void )
{
FOO foo;
foo.bar = 42;
foo.baz = 1;

return foo;
}

[ -------------------- ]


[ ------ foo.rb ------ ]

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

module Foo
extend DL::Importable
dlload 'foo.dylib'

FOO = struct [ "int bar", "int baz" ]
extern 'FOO make_a_foo(void)' # this fails
extern 'FOO make_a_foo()' # this fails too

def my_make_a_foo
return FOO.new( make_a_foo )
end

end

[ -------------------- ]

The library is compiled as a dylib (I'm on OSX) using:
$ cc -c foo.c
$ libtool -dynamic -o foo.dylib foo.o

If I then do:
$ ruby foo.rb

I get:

/usr/local/lib/ruby/1.8/dl/import.rb:125:in `symbol': can't find the
symbol `make_a_foo' (RuntimeError)
from /usr/local/lib/ruby/1.8/dl/import.rb:144:in `import'
from /usr/local/lib/ruby/1.8/dl/import.rb:61:in `extern'
from foo.rb:9

--
Luc Heinrich - lucsky@mac.com

Eric Hodel

3/23/2005 9:10:00 PM

0

On 23 Mar 2005, at 12:59, Luc Heinrich wrote:

> Luc Heinrich <lucsky@mac.com> wrote:
>
>> /usr/local/lib/ruby/1.8/dl/import.rb:125:in `symbol': can't find the
>> symbol `make_a_foo' (RuntimeError)
>
> And to make sure we're on the same page, here's exactly what I do
> (this,
> of course, is just a test case to reproduce a problem that I have in a
> bigger project ;) ):

You'll have to teach DL what type FOO is. Unfortunately, DL doesn't
barf on you in a friendly way when it can't recognize a type.

> [ ------ foo.rb ------ ]
>
> require 'dl/import'
> require 'dl/struct'
>
> module Foo
> extend DL::Importable
> dlload 'foo.dylib'

typealias "FOO", "void *"

Something like this should do it. (Yeah, void * is probably the wrong
type, see dl/types for what types dl knows about.)

> FOO = struct [ "int bar", "int baz" ]
> extern 'FOO make_a_foo(void)' # this fails
> extern 'FOO make_a_foo()' # this fails too
>
> def my_make_a_foo
> return FOO.new( make_a_foo )
> end
>
> end
>
> [ -------------------- ]
>
> The library is compiled as a dylib (I'm on OSX) using:
> $ cc -c foo.c
> $ libtool -dynamic -o foo.dylib foo.o
>
> If I then do:
> $ ruby foo.rb
>
> I get:
>
> /usr/local/lib/ruby/1.8/dl/import.rb:125:in `symbol': can't find the
> symbol `make_a_foo' (RuntimeError)
> from /usr/local/lib/ruby/1.8/dl/import.rb:144:in `import'
> from /usr/local/lib/ruby/1.8/dl/import.rb:61:in `extern'
> from foo.rb:9
>
> --
> Luc Heinrich - lucsky@mac.com
>

--
Eric Hodel - drbrain@segment7.net - http://se...
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Ben Giddings

3/23/2005 9:26:00 PM

0

Eric Hodel wrote:
> You'll have to teach DL what type FOO is. Unfortunately, DL doesn't
> barf on you in a friendly way when it can't recognize a type.

Nicely phrased. ;)

>> [ ------ foo.rb ------ ]
>>
>> require 'dl/import'
>> require 'dl/struct'
>>
>> module Foo
>> extend DL::Importable
>> dlload 'foo.dylib'
>
>
> typealias "FOO", "void *"
>
> Something like this should do it. (Yeah, void * is probably the wrong
> type, see dl/types for what types dl knows about.)

Actually, "void *" is probably right. When I wrapped my DLL using
Ruby/DL I just used "void *" whenever I came across a type that I hadn't
taught DL about. That seemed to do the trick for me.

Also (I'm no DLL expert or anything) but with GCC I think you have to
specify position independent code (-fPIC) and some other nifty things.
Make sure the problem is a DL problem, not a problem with the original DLL.

Ben



lucsky

3/23/2005 9:49:00 PM

0

Eric Hodel <drbrain@segment7.net> wrote:

> typealias "FOO", "void *"
>
> Something like this should do it. (Yeah, void * is probably the wrong
> type, see dl/types for what types dl knows about.)

Right, typealias-ing to 'void*' seems to do the trick for this case,
although I'm not sure if it's really the correct way or just a
coincidence. dl/types (mostly) knows about primitive types and pointers
to primitive types, and I'm not sure how structs passed on the stack can
relate to these.

Because if we now consider this:

Adding this function to foo.c:

void dump_foo( FOO foo )
{
printf( "foo.bar = %d\n", foo.bar );
printf( "foo.baz = %d\n", foo.baz );
}

And then adding this to foo.rb:

extern 'void dump_foo(FOO)'

And then doing:

foo = Foo.my_make_a_foo
Foo.dump_foo( foo )

Gives:

foo.bar = -1073791088
foo.baz = 891578649

Instead of:

foo.bar = 42
foo.baz = 1

That's why I'm a bit suspicious about the 'void*' thing ;)

--
Luc Heinrich - lucsky@mac.com

ES

3/23/2005 10:28:00 PM

0


In data 3/23/2005, "(Luc Heinrich)" <lucsky@mac.com> ha scritto:

>Eric Hodel <drbrain@segment7.net> wrote:
>
>> typealias "FOO", "void *"
>>
>> Something like this should do it. (Yeah, void * is probably the wrong
>> type, see dl/types for what types dl knows about.)
>
>Right, typealias-ing to 'void*' seems to do the trick for this case,
>although I'm not sure if it's really the correct way or just a
>coincidence. dl/types (mostly) knows about primitive types and pointers
>to primitive types, and I'm not sure how structs passed on the stack can
>relate to these.
>
>Because if we now consider this:
>
>Adding this function to foo.c:
>
> void dump_foo( FOO foo )
> {
> printf( "foo.bar = %d\n", foo.bar );
> printf( "foo.baz = %d\n", foo.baz );
> }
>
>And then adding this to foo.rb:
>
> extern 'void dump_foo(FOO)'
>
>And then doing:
>
> foo = Foo.my_make_a_foo
> Foo.dump_foo( foo )
>
>Gives:
>
> foo.bar = -1073791088
> foo.baz = 891578649
>
>Instead of:
>
> foo.bar = 42
> foo.baz = 1
>
>That's why I'm a bit suspicious about the 'void*' thing ;)

Normally you'd cast from void*, of course, but I don't know
if it's possible in DL. Maybe pass around a struct FOO* instead?

That or just write a C extension.

>Luc Heinrich - lucsky@mac.com

E



lucsky

3/24/2005 7:22:00 AM

0

ES <ruby-ml@magical-cat.org> wrote:

> Normally you'd cast from void*, of course, but I don't know
> if it's possible in DL. Maybe pass around a struct FOO* instead?

That's precisely the problem: I'm wrapping a system library so I can't
change it.

> That or just write a C extension.

Yeah, I guess I'll have to go that way. That's too bad because DL is
actually pretty fun and productive.

--
Luc Heinrich - lucsky@mac.com