C library functions that take pointers as arguments and return ints (that covers most of the c library functions I have written) ultimately return an array to Ruby. Uncovering that little factoid, and the swig interface format required to make that process work, was the tough bit.
So, I'm taking a few more minutes to make sure you don't have to do that (and to make sure I don't have to do that long after I forget about this exercise).
Step Zero: get swig.
I install all open source software on the mac with fink. Fink Swig
Step One: Copy my example code - inline below.
I provide what you need to make a ruby callable module called Example that contains the C function SimpleFunc() that you will call with a little ruby test program called testsum.rb.
user-64-9-234-209:~/src/c/simplelib richbodo$ ls -lThree of these files you already understand:
total 48
-rw-r--r-- 1 richbodo richbodo 61 Oct 12 16:24 example.i
-rw-r--r-- 1 richbodo richbodo 42 Oct 12 15:52 extconf.rb
-rwxr-xr-x 1 richbodo richbodo 90 Oct 12 16:41 get_it_done.sh
-rw-r--r-- 1 richbodo richbodo 46 Oct 12 16:36 sum.c
-rw-r--r-- 1 richbodo richbodo 24 Oct 12 15:46 sum.h
-rw-r--r-- 1 richbodo richbodo 67 Oct 12 15:57 testsum.rb
sum.c - your library
int SimpleFunc(float *modify_me)sum.h - your library header - not used by swig unless you tell it to - don't need it here.
{
*modify_me = 5;
return 1;
}
testsum.rb - ruby program that calls your library
require 'example'The other three files are specific to getting your swig library going:
afloat = 2
# The first return value gets set as expected in first_returnval.
# However, SWIG puts the float in a second return value.
first_returnval,second_returnval = Example.SimpleFunc(afloat)
puts "Your float is #{first_returnval}, and the return value is: #{second_returnval}"
- example.i - a definition of your library for swig in swigs definition language. INOUT is a SWIG typemap, so typemaps.i is required.
%module example
%include "typemaps.i"
%apply float *INOUT { float *modify_me };
int SimpleFunc(float *modify_me);
- extconf.rb - a ruby program that creates a makefile for your library
require 'mkmf'
create_makefile('example')
- get_it_done.sh - the commands that you run to generate a ruby module from your c library using swig
#!/bin/bashStep 2: Run the get_it_done.sh script to build and test your module. (it will ask for your password to install the library)
rm *.o
rm *.bundle
rm wrap_example.c
rm Makefile
swig -ruby example.i
ruby extconf.rb
make
sudo make install
ruby testsum.rb
user-64-9-234-209:~/src/c/idlerlib richbodo$ ./get_it_done.shStep 3: Look at the five new files you just created, and understand what they do:
rm: wrap_example.c: No such file or directory
creating Makefile
gcc -fno-common -g -O2 -fno-common -pipe -fno-common -I. -I/sw/lib/ruby/1.8/i686-darwin -I/sw/lib/ruby/1.8/i686-darwin -I. -I/sw/include -c example_wrap.c
gcc -fno-common -g -O2 -fno-common -pipe -fno-common -I. -I/sw/lib/ruby/1.8/i686-darwin -I/sw/lib/ruby/1.8/i686-darwin -I. -I/sw/include -c sum.c
cc -dynamic -bundle -L"/sw/lib" -o example.bundle example_wrap.o sum.o -lruby -ldl -lobjc
install -c -p -m 0755 example.bundle /sw/lib/ruby/site_ruby/1.8/i686-darwin
Your float is 5.0, and the return value is: 1
user-64-9-234-209:~/src/c/simplelib richbodo$ ls -l
total 152
-rw-r--r-- 1 richbodo richbodo 3009 Oct 12 16:42 Makefile
-rwxr-xr-x 1 richbodo richbodo 16316 Oct 12 16:42 example.bundle
-rw-r--r-- 1 richbodo richbodo 61 Oct 12 16:24 example.i
-rw-r--r-- 1 richbodo richbodo 17695 Oct 12 16:42 example_wrap.c
-rw-r--r-- 1 richbodo richbodo 5744 Oct 12 16:42 example_wrap.o
-rw-r--r-- 1 richbodo richbodo 42 Oct 12 15:52 extconf.rb
-rwxr-xr-x 1 richbodo richbodo 90 Oct 12 16:41 get_it_done.sh
-rw-r--r-- 1 richbodo richbodo 46 Oct 12 16:36 sum.c
-rw-r--r-- 1 richbodo richbodo 24 Oct 12 15:46 sum.h
-rw-r--r-- 1 richbodo richbodo 644 Oct 12 16:42 sum.o
-rw-r--r-- 1 richbodo richbodo 67 Oct 12 15:57 testsum.rb
- example_wrap.c - created by the swig command, this a c wrapper for your library with a bunch of additional wrapper functions that translate your functions and data into ruby callable functions and data. see chap 21 in the pickaxe.
- Makefile - this is the makefile that was generated by extconf.rb. It will compile your library and that wrapper and make the mac bundle for you.
- sum.o - the object file generated from sum.c
- example_wrap.o - the compiled version of example_wrap.c
- example.bundle - mac osx stores code in bundles, so make makes one and puts it in your site-ruby directory when you type "make install"
References:
- Chapter 21 in the pickaxe book.
- The ruby swig page: http://www.swig.org/Doc1.3/Ruby.html#Ruby_nn5
- The swig basics page: http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn3
- Apple Developer Docs: http://developer.apple.com/documentation/
1 comment:
I was having problems with my own SWIG example so i figured i'd try your code out verbatim and am getting the same error so i'm wondering if my SWIG is configured wrong. Ever had any issues along these lines:
% ruby test_sum.rb
/Library/Ruby/Site/1.8/universal-darwin10.0/example.bundle: dlsym(0x10023f630, Init_example): symbol not found - /Library/Ruby/Site/1.8/universal-darwin10.0/example.bundle (LoadError)
from test_sum.rb:1
Post a Comment