How to pass const char *vect[] to C via Ruby/DL?


#1

Hi all,

I’m having problems to understand how to build-up “const char *vect[]”
data for passing to a C function that I wish to call via Ruby/DL:

-----------------

int setv(const char *ids[])
{
while (*ids) {
printf(“setv: %s\n”, ids[0]);
ids++;
}
}

-----------------

My current Ruby program looks like this:

-----------------

#!/usr/bin/ruby

require ‘dl/import’

def setv(ary)
setv = $lib[‘setv’, ‘IP’]
ids = DL.malloc(DL.sizeof(‘S’)*(ary.size + 1))
i = 0
ary.each do |s|
ids[DL.sizeof(‘S’)*i] = s.to_ptr
i += 1
end
# ids[3] = nil ?
r,r1 = setv.call(ids.ref)
end

$lib = DL.dlopen(‘lib.dylib’)

setv([“1”, “2”, “3”])

-----------------

but I get a SEGV and it is not complete anyways. Instead of

ids[DL.sizeof('S')*i] = s.to_ptr

I already tried

ids[DL.sizeof(‘S’)*i] = s

and other variations I could think of …

You know: I can imagine there were better means for
passing string vectors to C, yet the C function interface
as such is given.

So any help or hint is greatly appreciated!

Best regards,
Andreas


#2

On Fri, 2 Jun 2006, Andreas Haas wrote:

You know: I can imagine there were better means for
passing string vectors to C, yet the C function interface
as such is given.

So any help or hint is greatly appreciated!

i’m no dl expert, but:

harp:~ > cat a.rb

generate the lib

unless test(?e, ‘a.so’)
open(‘a.c’,‘w’) do |f|
f.write <<-‘code’
int setv(const char *ids[]){
while(*ids){ printf(“setv: %s\n”, ids[0]); ids++; }
printf(“setv: %s\n”, ids[0]);
}
code
end
system “gcc -shared a.c -o a.so”
end

require ‘dl/import’

def setv(ary)
setv = $lib[‘setv’, ‘IP’]
ids = ary.map{|s| s.to_ptr}
ids << DL::PtrData.new(0)
r,r1 = setv.call ids.to_ptr
end

$lib = DL.dlopen(’./a.so’)

setv %w( 1 2 3 )

harp:~ > ruby a.rb
setv: 1
setv: 2
setv: 3
setv: (null)

regards.

-a


#3

Am Freitag, 02.06.06 um 05:14 Uhr schrieb removed_email_address@domain.invalid:

i’m no dl expert, but:

def setv(ary)
setv = $lib[‘setv’, ‘IP’]
ids = ary.map{|s| s.to_ptr}
ids << DL::PtrData.new(0)
r,r1 = setv.call ids.to_ptr
end

Now it works.

Thanks Ara!

Regards,
Andreas