CSC/ECE 517 Fall 2013/ch1 1w04 y: Difference between revisions
(31 intermediate revisions by the same user not shown) | |||
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 | [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 has been developed since 1995. In 1996, the first alpha released and the latest version is 2.0.10, which means it is still maintained/in progress and used widely. | ||
As a great tool, SWIG can be used in many ways, like: | |||
Building more powerful C/C++ programs, system integration, etc. More details about that can be found [http://www.swig.org/exec.html here] | |||
=== Why we use SWIG === | === Why we use SWIG === | ||
Line 11: | Line 17: | ||
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 | 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 | 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. | ||
With the help and | With the help and advantages of SWIG, we can make the program more robust and efficient, as well as convenient for users and programmers. | ||
== Installation == | ==Installation== | ||
Installation can be found [http://www.swig.org/Doc2.0/SWIGDocumentation.html#Preface_installation here], and you may need the software of SWIG and the [http://www.pcre.org/ PCRE] on your own computer to complete your installation. | |||
Installation can be found [http://www.swig.org/Doc2.0/SWIGDocumentation.html#Preface_installation here], and you may need the software of SWIG and the [http://www.pcre.org/ PCRE] on your own computer to complete your installation. | |||
== A SWIG example == | == A SWIG example == | ||
Line 31: | Line 36: | ||
Here we create a C code file named example.c : | Here we create a C code file named example.c : | ||
/* File : example.c */ | /* File : example.c */ | ||
/* Compute the least common multiple of positive integers */ | |||
/* Compute the least common multiple of positive integers */ | int lcm(int x, int y) { | ||
int lcm(int x, int y) { | |||
int g; | int g; | ||
g = y; | g = y; | ||
Line 44: | Line 47: | ||
} | } | ||
return x * y / g; | return x * y / g; | ||
} | } | ||
=== The SWIG interface === | === The SWIG interface === | ||
Line 50: | Line 53: | ||
Then we create the SWIG interface file example.i: | Then we create the SWIG interface file example.i: | ||
/* File : example.i */ | /* File : example.i */ | ||
%module example | %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 [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 80: | Line 130: | ||
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 === | |||
Given the situation that 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 the following ways: 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. | |||
==SWIG disadvantages == | |||
Up to now we have introduced why and how we can use SWIG to improve our program, but there are still some problems of using SWIG that should be kept an eye on. Such disadvantages of using SWIG include: | |||
1. Extra creation of format specific header files or hand-written wrapper codes that may confuse of interfere us with code/program. | |||
2. Addition of inefficient shadow class layer which means that the number of internal function calls increases quickly. | |||
3. Use of expression-based approximation without true semantic information for wrapper code. | |||
Such problems or disadvantages remind us of being cautious when using SWIG. | |||
== Conclusion == | == Conclusion == | ||
SWIG is a great tool in | SWIG is a great tool in a lot 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. In practice, SWIG precompiles the C/C++ code into a .so shared object file, thereby increasing speed. 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. | ||
Some unpleasant but minor problems still exist, but no one would doubt that SWIG is a great tool for us to use as to improve our code. | |||
==Further reading== | |||
There are also gem files 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] | |||
Mixing dynamic and static languages is under discussion and research by many people, and it is really a lively topic. You can find more background information and development details regarding mixed-language combination [http://wiki.expertiza.ncsu.edu/index.php/CSC/ECE_517_Fall_2010/ch3_3i_MM here] | |||
== References == | == References == | ||
[1] [http://en.wikipedia.org/wiki/SWIG | [1] The introduction to SWIG [http://en.wikipedia.org/wiki/SWIG http://en.wikipedia.org/wiki/SWIG] | ||
[2] [http://www.swig.org/tutorial.html | [2] SWIG Tutorial [http://www.swig.org/tutorial.html http://www.swig.org/tutorial.html ] | ||
[3] [http://en.wikipedia.org/wiki/Ruby_(programming_language) | [3] What is Ruby and its feature [http://en.wikipedia.org/wiki/Ruby_(programming_language) http://en.wikipedia.org/wiki/Ruby_(programming_language) ] | ||
[4] SWIG Ruby examples [http://www.goto.info.waseda.ac.jp/~fukusima/ruby/swig-examples/index.html http://www.goto.info.waseda.ac.jp/~fukusima/ruby/swig-examples/index.html] | |||
[5] [https://github.com/swig/swig https://github.com/swig/swig ] | |||
[6] [http://www.swig.org/ http://www.swig.org] | |||
[ | [7] Ruby C extensions PDF [http://java.ociweb.com/mark/NFJS/RubyCExtensions.pdf http://java.ociweb.com/mark/NFJS/RubyCExtensions.pdf ] |
Latest revision as of 13:25, 24 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 has been developed since 1995. In 1996, the first alpha released and the latest version is 2.0.10, which means it is still maintained/in progress and used widely.
As a great tool, SWIG can be used in many ways, like:
Building more powerful C/C++ programs, system integration, etc. More details about that can be found here
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 advantages of SWIG, we can make the program more robust and efficient, as well as convenient for users and programmers.
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
Given the situation that 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 the following ways: 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.
SWIG disadvantages
Up to now we have introduced why and how we can use SWIG to improve our program, but there are still some problems of using SWIG that should be kept an eye on. Such disadvantages of using SWIG include:
1. Extra creation of format specific header files or hand-written wrapper codes that may confuse of interfere us with code/program.
2. Addition of inefficient shadow class layer which means that the number of internal function calls increases quickly.
3. Use of expression-based approximation without true semantic information for wrapper code.
Such problems or disadvantages remind us of being cautious when using SWIG.
Conclusion
SWIG is a great tool in a lot 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. In practice, SWIG precompiles the C/C++ code into a .so shared object file, thereby increasing speed. 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.
Some unpleasant but minor problems still exist, but no one would doubt that SWIG is a great tool for us to use as to improve our code.
Further reading
There are also gem files 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
Mixing dynamic and static languages is under discussion and research by many people, and it is really a lively topic. You can find more background information and development details regarding mixed-language combination here
References
[1] The introduction to SWIG http://en.wikipedia.org/wiki/SWIG
[2] SWIG Tutorial http://www.swig.org/tutorial.html
[3] What is Ruby and its feature http://en.wikipedia.org/wiki/Ruby_(programming_language)
[4] SWIG Ruby examples http://www.goto.info.waseda.ac.jp/~fukusima/ruby/swig-examples/index.html
[5] https://github.com/swig/swig
[7] Ruby C extensions PDF http://java.ociweb.com/mark/NFJS/RubyCExtensions.pdf