CSC/ECE 517 Fall 2010/ch3 3i IC: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 198: Line 198:
10<br>
10<br>
</code>
</code>
For more examples using other languages besides Python, see the SWIG tutorial. [http://swig.org/tutorial.html [8]]


=Mixing Dynamic Code and Java=
=Mixing Dynamic Code and Java=

Revision as of 02:19, 7 October 2010

Mixing Static and Dynamic Code


Introduction

Many middleware solutions have been developed to combine static and dynamic languages to take advantage of both types of code. Previous wiki chapters have discussed JRuby, a Java implementation of Ruby. These solutions allow programmers the productivity luxuries of newer dynamic languages with the speed, low-level functionality, and pre-existing code base of older static languages. Below, we will give even more examples of mixing several widely used dynamic languages with C, C++, and Java.

Mixing Dynamic Code and C/C++

Ruby

CplusRuby

CplusRuby is a gem that allows programmers to call Ruby code within C++ and vice versa. Assuming an installation of Ruby, the CplusRuby can be installed with the following command [2]:


gem install cplus2ruby


An example is given below. In this sample, C code is embedded in Ruby code. This uses the cplusruby gem, which is garnered toward C code, while cplus2ruby was designed for C++ code in mind. [2 ] gives an example using CplusRuby in C++ and [6 ] gives the corresponding example in C.


require 'cplusruby'

class NeuralEntity < CplusRuby

property :id

end

class Neuron < NeuralEntity

property :potential, :float
property :last_spike_time, :float
property :pre_synapses, :value


method_c :stimulate, %(float at, float weight), %{
// this is C code
selfc->potential += at*weight;

}

def initialize
self.pre_synapses = []
end

end

# generate C file, compile it and load the .so
CplusRuby.evaluate("inspire.cc", "-O3", "-lstdc++")

if __FILE__ == $0
n = Neuron.new
n.id = "n1"
n.potential = 1.0
n.stimulate(1.0, 2.0)
p n.potential # => 3.0
end


In the example above, we declare a class as a C class, but in Ruby syntax. However, we define the method stimulate in C syntax. We then use CplusRuby to evaluate the embedded C code to generate a C code file. CplusRuby then compiles the generated C code, which then becomes available to the Ruby code declared at the bottom of the code sample. This method allows performance sensitive code to be compiled as C, which is much faster than Ruby. These C methods can also call other C methods with native C performance. [6 ] It's worth pointing out that the properties of the class Neuron and NeuralEntity (id, potential, last_spike_time, etc.) are actually members of a C-struct, not instance variables. Their identity as struct members also allows for faster access.

Python

Using Boost

Boost allows programmers to seamlessly expose C++ classes and function to Python and vice versa. No special tools are needed (however, a build tool will be referenced later). All that is required are the Boost libraries and a C++ compiler. Boost is designed to allow Python to use C++ code with no internal modification to the C++ code that will be wrapped.

Exposing Functions

Below is a “Hello, World!” example.

C++ function

string greet()
{

return "Hello, World!";

}

Add to C++ so it can be exposed to Python

#include <boost/python.hpp>
BOOST_PYTHON_MODULE(hello_ext)
{

using namespace boost::python;
def("greet", greet);

}

Python code that calls C++

import hello_ext # parameter passed to BOOST_PYTHON_MODULE
print hello.greet()
>> Hello, World!

Exposing Classes

C++ Class Declaration

class Person
{

private string name;


void setName(string name)
{
this->name = name;
}


string getName()
{
return name;
}

};

Boost.Python C++ Wrapper

#include <boost/python.hpp>
using namespace boost::python;

BOOST_PYTHON_MODULE(person)
{

class_<Person>("person")
.def("getName", &Person::getName)
.def("setName", &Person::setName);

}

Python Code

import person
student = person.Person()
student.setName('John')
student.getName()

Output: >> John


SWIG

Previously we've seen specific examples of middleware libraries that allow us to mix specific languages with C/C++. 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, PHP, and Lua. SWIG was first released in 1995 and is still maintained to this day, with its most recent release on October 4, 2010.

SWIG maintains two purposes for embedding dynamic language code in C/C++

  1. Faster customization using the scripting language
  2. Easier to write test scripts, including unit tests

SWIG allows programmers to replace the main() function of a C program with a scripting interpreter from which they can control the application. This ability adds flexibility and makes the program more easily modifiable. The scripting interface allows programmers to easily modify program behavior without having to modify low-level C/C++ code.

Example

C Code

/* File : math.c */

int a = 5;
int b = 9;

int add(int x, int y)
{

return x + y;

}

int subtract(int x, int y)
{

return x - y;

}

Interface File (Input to SWIG)

/* math.i */
%module math
%{
/* Put header files here or function declarations like below */
extern int a;
extern int b;
extern int add(int x, int y);
extern int subtract(int x, int y);
%}

extern int a;
extern int b;
extern int add(int x, int y);
extern int subtract(int x, int y);

Using with Python

$ swig -python module.i
$ gcc -fpic -I/usr/include/python2.6 -c module_wrap.c
$ gcc -shared module_wrap.o -o module.so

We can now use the Python module as follows:

>>> import math
>>> math.add(5,8)
13
>>> math.subtract(15,5)
10

For more examples using other languages besides Python, see the SWIG tutorial. [8]

Mixing Dynamic Code and Java

Perl

Using Inline::Java

Java Code

public class Person {

String name;
public getName()
{
return name;
}
public setName(String newName)
{
this.name = newName;
}

}

Perl Code

#!/usr/bin/perl use strict; use warnings;

use Inline Java => <<'EOJ';
public class Person
{

// The class body is shown in the Java Code above

}
EOJ

my $student = Person->new("John Smith");
print $student->getName(), "\n";

(This section on Java and Perl is mostly referenced from [4].)

In the Perl example above, we omit the details of the Java class, since they are detailed above. The declaration 'EOJ' ("end of Java", in this case) at the beginning of the Java class declaration in the Perl code is a qualifier to dictate where to end the Java code. In this particular example, we include the Java code directly in our Perl file. However, you can also include Java code via a file reference.

References

[1] http://en.wikipedia.org/wiki/SWIG

[2] Michael Neumann. Cplus2Ruby - Gluing C++ and Ruby together in an OO manner. http://rubydoc.info/gems/cplus2ruby/1.2.0/frames

[3] Dave Abrahams. Boost.Python. http://www.boost.org/doc/libs/1_44_0/libs/python/doc/index.html

[4] Phil Crow. Bringing Java into Perl. http://www.perl.com/pub/2003/11/07/java.html. 2003.

[5] Patrick LeBoutillier. Inline::Java http://search.cpan.org/~patl/Inline-Java-0.52/Java.pod

[6] Michael Neumann. CplusRuby - Gluing C and Ruby. http://www.ntecs.de/blog/articles/2007/09/21/cplusruby-gluing-c-and-ruby/. 2007.

[7] What is SWIG? http://www.swig.org/exec.html