CSC/ECE 517 Fall 2013/ch1 1w04 y: Difference between revisions
No edit summary |
|||
Line 1: | Line 1: | ||
Use [http://en.wikipedia.org/wiki/SWIG SWIG] to improve the performance of [https://www.ruby-lang.org/en/ Ruby] code | Use [http://en.wikipedia.org/wiki/SWIG SWIG] to improve the performance of [https://www.ruby-lang.org/en/ Ruby] code | ||
== Introduction == | == Introduction == | ||
Line 5: | Line 7: | ||
=== What is SWIG === | === What is SWIG === | ||
[http://www.swig.org/ SWIG] (Simplified Wrapper and Interface Generator) is a tool that allows programmers to mix C/C++ programs and libraries with several dynamic languages, including Tcl, Perl, Python, Ruby,and PHP. It was | [http://www.swig.org/ SWIG] (Simplified Wrapper and Interface Generator) is a actually a compiler and a tool that allows programmers to mix C/C++ programs and libraries with several dynamic or high level languages, including Tcl, Perl, Python, Ruby,and PHP. It was developed in 1995, and the latest version is 2.0.10 which means it is still maintained/in progress and used widely. | ||
=== Why we use SWIG === | === Why we use SWIG === | ||
Line 11: | Line 13: | ||
We all know that computer programming languages can be compiled or interpreted to execute instructions, and these languages can be divided into two basic groups: dynamic and static language. | We all know that computer programming languages can be compiled or interpreted to execute instructions, and these languages can be divided into two basic groups: dynamic and static language. | ||
As far as Ruby is concerned, it is a kind of dynamic language, which is high-level and useful for nearly everything as well as more flexible. On the other hand, Ruby also has many disadvantages as a script language. While using c/c++ code can do a support in many tasks to improve the memory usage and execution speed, we can not help thinking of combine these two kinds of languages and make the best use of them. That’s SWIG’s function, | As far as Ruby is concerned, it is a kind of dynamic language, which is high-level and useful for nearly everything as well as more flexible. On the other hand, Ruby also has many disadvantages as a script language. While using c/c++ code can do a support in many tasks to improve the memory usage and execution speed, we can not help thinking of combine these two kinds of languages and make the best use of them. That’s SWIG’s function, “cooperating” with C/C++ header files and using them to generate the wrapper code that script languages like Ruby need to access the underlying C/C++ code. What is more, SWIG provides many kinds of customization features and individual preferences that let you cut the wrapping process to suit your application. It is designed to work with existing c/c++ code, and turn common C/C++ libraries into components for use in popular script languages. In this way, we can manage to run the program in a more efficient and practical way. | ||
The primary purpose of using SWIG is to simplify the task of integrating c/c++ code with other programing languages, allowing people to focus on the underlying C program and using the high-level language interface, but not the tedious and complex | The primary purpose,or goal, of using SWIG is to simplify the task of integrating c/c++ code with other programing languages, allowing people to focus on the underlying C program and using the high-level language interface, but not the tedious and complex task of making the two languages talk to each other. | ||
Besides, we can easily write test scripts to our code. | Besides, we can easily write test scripts to our code. | ||
Line 53: | Line 55: | ||
%} | %} | ||
=== | === Running SWIG === | ||
Next we should | Next we should start the SWIG we have, using the following command(Typically on the Unix System): | ||
$ swig -ruby example.i | $ swig -ruby example.i | ||
if you build a c++ extension, the command should be: | |||
$ swig -c++ -ruby example.i | |||
In this way, SWIG create a file example_wrap.c (in c++ it should be example_wrap.cpp) that should be combined with to build a Ruby extension file. Just link this file with the rest of the program to finish your compiling. | |||
===Acquire the right header files === | |||
To compile the example_wrap.c on your machine, you need to get the right Ruby header file ruby.h for use. If you do not know the location of your header file and take account into the situation that different machines have different locations of ruby programs and files, you can input the following command: | |||
$ ruby -e 'puts $:.join("\n")' | |||
/usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1 | |||
/usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1/x86_64-darwin12.5.0 | |||
/usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby | |||
/usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1 | |||
/usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin12.5.0 | |||
/usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby | |||
/usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1 | |||
/usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/x86_64-darwin12.5.0 | |||
It is easy to run Ruby to find out the correct information. | |||
===Compile your own dynamic module with SWIG=== | |||
You can do this by taking following steps/commands: | |||
1 Create a file called “extconf.rb” | |||
require 'mkmf' | |||
create_makefile('example') | |||
2 Build the extension: | |||
$ ruby extconf.rb | |||
$ make | |||
$ make install | |||
There may be some errors during this process and if you want to add your own make rules to the extconf.rb, you can go through by doing this at the end of the file: | |||
open("Makefile", "a") { |mf| | |||
puts <<EOM | |||
# Your make rules go here | |||
EOM | |||
} | |||
We have almost done the process, and usually a typical series of commands that used in Linux platform looks like this: | |||
$ swig -ruby example.i | |||
$ gcc -c example.c | |||
$ gcc -c example_wrap.c -I/usr/local/lib/ruby/1.6/i686-linux | |||
$ gcc -shared example.o example_wrap.o -o example.so | |||
For other platforms, you may need to add -fPIC to generate position independent code. In Mac OS x system, click [http://stackoverflow.com/questions/14884126/build-so-file-from-c-file-using-gcc-command-line here] for more details. | |||
=== | |||
=== Run your program === | |||
Since we have example.so, the shared object file here, we can next use ruby to access the function and variables declared in the SWIG interface file (You can also use the command line to generate .bundle file to work as the library file of Ruby.). | Since we have example.so, the shared object file here, we can next use ruby to access the function and variables declared in the SWIG interface file (You can also use the command line to generate .bundle file to work as the library file of Ruby.). | ||
Line 76: | Line 127: | ||
Also, [http://www.swig.org/tutorial.html SWIG Tutorial] gives us more examples using other languages, like python,Tcl. | Also, [http://www.swig.org/tutorial.html SWIG Tutorial] gives us more examples using other languages, like python,Tcl. | ||
=== Using your own module === | |||
Since the Ruby module names begin with capitalized letters, but the feature names are usually lowercase, you should always use a lowercase module name with %module directive in SWIG. If you do this following, a SWIG file beginning with this: | |||
%module example | |||
will result in a extension file with the Ruby module name ”Example” and a feature name “example”. | |||
=== Static linking === | |||
The usual way of adding a new module to Ruby involves finding the Ruby source, adding an entry to the ext/Setup file, adding your directory to the list of extensions in the file, and finally rebuilding Ruby. Avoid using static linking unless you have no other choice, since the dynamic loading support situation has improved greatly and you can easily and efficiently work out certain problems. | |||
== Conclusion == | == Conclusion == | ||
Line 84: | Line 148: | ||
There are also gemfiles which can call Ruby code within C++ code and vice versa, such as [https://rubygems.org/gems/cplus2ruby Cplus2Ruby]. For more details and more help as well as tutorials, just go through [http://rubydoc.info/gems/cplus2ruby/1.2.0/frames here]. | There are also gemfiles which can call Ruby code within C++ code and vice versa, such as [https://rubygems.org/gems/cplus2ruby Cplus2Ruby]. For more details and more help as well as tutorials, just go through [http://rubydoc.info/gems/cplus2ruby/1.2.0/frames here]. | ||
For windows 95/NT, we can also create Ruby extensions and make them work for us. | |||
Take a look at [http://binf.gmu.edu/software/SWIG/Ruby.html#Ruby_nn4 here] | |||
== References == | == References == |
Revision as of 15:02, 21 September 2013
Use SWIG to improve the performance of Ruby code
Introduction
What is SWIG
SWIG (Simplified Wrapper and Interface Generator) is a actually a compiler and a tool that allows programmers to mix C/C++ programs and libraries with several dynamic or high level languages, including Tcl, Perl, Python, Ruby,and PHP. It was developed in 1995, and the latest version is 2.0.10 which means it is still maintained/in progress and used widely.
Why we use SWIG
We all know that computer programming languages can be compiled or interpreted to execute instructions, and these languages can be divided into two basic groups: dynamic and static language.
As far as Ruby is concerned, it is a kind of dynamic language, which is high-level and useful for nearly everything as well as more flexible. On the other hand, Ruby also has many disadvantages as a script language. While using c/c++ code can do a support in many tasks to improve the memory usage and execution speed, we can not help thinking of combine these two kinds of languages and make the best use of them. That’s SWIG’s function, “cooperating” with C/C++ header files and using them to generate the wrapper code that script languages like Ruby need to access the underlying C/C++ code. What is more, SWIG provides many kinds of customization features and individual preferences that let you cut the wrapping process to suit your application. It is designed to work with existing c/c++ code, and turn common C/C++ libraries into components for use in popular script languages. In this way, we can manage to run the program in a more efficient and practical way.
The primary purpose,or goal, of using SWIG is to simplify the task of integrating c/c++ code with other programing languages, allowing people to focus on the underlying C program and using the high-level language interface, but not the tedious and complex task of making the two languages talk to each other.
Besides, we can easily write test scripts to our code.
With the help and advantage of SWIG, we can make the program more robust and efficient.
Installation
Installation can be found here, and you may need the software of SWIG and the PCRE on your own computer to complete your installation.
A SWIG example
We will take a look at how we can use SWIG with respect to Ruby by using an example to illustrate. We will begin from creating a .c file.
The C code
Here we create a C code file named example.c :
/* File : example.c */ /* Compute the least common multiple of positive integers */ int lcm(int x, int y) { int g; g = y; while (x > 0) { g = x; x = y % x; y = g; } return x * y / g; }
The SWIG interface
Then we create the SWIG interface file example.i:
/* File : example.i */ %module example %inline %{ extern int lcm(int x, int y); %}
Running SWIG
Next we should start the SWIG we have, using the following command(Typically on the Unix System):
$ swig -ruby example.i
if you build a c++ extension, the command should be:
$ swig -c++ -ruby example.i
In this way, SWIG create a file example_wrap.c (in c++ it should be example_wrap.cpp) that should be combined with to build a Ruby extension file. Just link this file with the rest of the program to finish your compiling.
Acquire the right header files
To compile the example_wrap.c on your machine, you need to get the right Ruby header file ruby.h for use. If you do not know the location of your header file and take account into the situation that different machines have different locations of ruby programs and files, you can input the following command:
$ ruby -e 'puts $:.join("\n")' /usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1 /usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1/x86_64-darwin12.5.0 /usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby /usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1 /usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin12.5.0 /usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby /usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1 /usr/local/rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/x86_64-darwin12.5.0
It is easy to run Ruby to find out the correct information.
Compile your own dynamic module with SWIG
You can do this by taking following steps/commands:
1 Create a file called “extconf.rb”
require 'mkmf' create_makefile('example')
2 Build the extension:
$ ruby extconf.rb $ make $ make install
There may be some errors during this process and if you want to add your own make rules to the extconf.rb, you can go through by doing this at the end of the file:
open("Makefile", "a") { |mf| puts <<EOM # Your make rules go here EOM }
We have almost done the process, and usually a typical series of commands that used in Linux platform looks like this:
$ swig -ruby example.i $ gcc -c example.c $ gcc -c example_wrap.c -I/usr/local/lib/ruby/1.6/i686-linux $ gcc -shared example.o example_wrap.o -o example.so
For other platforms, you may need to add -fPIC to generate position independent code. In Mac OS x system, click here for more details.
Run your program
Since we have example.so, the shared object file here, we can next use ruby to access the function and variables declared in the SWIG interface file (You can also use the command line to generate .bundle file to work as the library file of Ruby.).
unix > irb unix > require ‘example’ unix > true unix > Example.lcm(10,45) unix > 90
In our example, our Ruby module has been compiled into a shared library that can be loaded into Ruby.
Also, SWIG Tutorial gives us more examples using other languages, like python,Tcl.
Using your own module
Since the Ruby module names begin with capitalized letters, but the feature names are usually lowercase, you should always use a lowercase module name with %module directive in SWIG. If you do this following, a SWIG file beginning with this:
%module example
will result in a extension file with the Ruby module name ”Example” and a feature name “example”.
Static linking
The usual way of adding a new module to Ruby involves finding the Ruby source, adding an entry to the ext/Setup file, adding your directory to the list of extensions in the file, and finally rebuilding Ruby. Avoid using static linking unless you have no other choice, since the dynamic loading support situation has improved greatly and you can easily and efficiently work out certain problems.
Conclusion
SWIG is a great tool in an amount of sceneries. It can be used to provide a scripting interface to C/C++ code, making it easier for users and add extensions to your Ruby code or replacing existing modules with high-performance alternatives. As a tool, SWIG is most commonly used to create high-level interpreted or compiled programming environments, user interfaces, and as a tool for testing and prototyping C/C++ software. It is typically used to parse C/C++ interfaces and generate the 'glue code' required for the above target languages to call into the C/C++ code. With the help of SWIG, we can simply let Ruby(as well as other script language) to call the function of C/C++ code. In this way, we can combine the advantages of both languages, and run our programs more efficiently and safely.
Further reading
There are also gemfiles which can call Ruby code within C++ code and vice versa, such as Cplus2Ruby. For more details and more help as well as tutorials, just go through here.
For windows 95/NT, we can also create Ruby extensions and make them work for us. Take a look at here
References
[2] SWIG Tutorial