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

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Andreas Haas (Guest)
on 2006-06-02 04:25
(Received via mailing list)
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
unknown (Guest)
on 2006-06-02 07:17
(Received via mailing list)
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
Andreas Haas (Guest)
on 2006-06-02 16:56
(Received via mailing list)
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
This topic is locked and can not be replied to.