Testing C++ in Ruby, continued

For a while I’ve been working with SWIG to generate wrappers for my C++ code. I ran into some problems when using it in a real project, so I’ve made the following adjustments to my method. First of all I’m using mkmf to generate a Makefile for the shared objects. This is how the SWIG documentation shows it, and I have added some lines to link in more libraries and run the swig command. I’ve added the -minherit flag to support C++ inheritance.

 require 'mkmf'
# Create wrapper module
`swig -c++ -ruby -minherit -Wall -o units_wrap.cpp units.i`

# Since the SWIG runtime support library for Ruby
# depends on the Ruby library, make sure it's in the list
# of libraries.
$libs = append_library($libs, Config::CONFIG['RUBY_INSTALL_NAME'])

# Also, we need the c++ libraries
$libs = append_library($libs, "stdc++")

# Create the makefile
create_makefile('units') 

This script, src/extconf.rb is executed by automake by adding the following in src/Makefile.am:

bin_PROGRAMS = example
example_SOURCES = example.cpp
noinst_unit_testsdir = .
noinst_unit_tests_DATA = units.so
EXTRA_DIST = extconf.rb autogen.sh
units.so:
     ruby extconf.rb
     make

I love this solution because now I only have 2 files to maintain compiler details instead of 3. src/units.i and src/Makefile.am. Also, by using the noinst_ prefix the module will not be included when I run ‘make dist’. You can see how it all fits together in my APR project.


Don't sweat the technique

Looking at the subtitle of my blog, I hope nobody misses the obvious reference to this. Released in an era when hip-hop (although it was generally known as ‘rap’ at the time) was still sounding good. No need to distinguish true hip-hop music from the boring formulaic derivative it has generally become. From last century, here’s a true hip-hop classic:

Eric B & Rakim - Don’t sweat the technique

 



Apparently, women wore clothes back then!


Creating embedded systems

PIC HAMA device in action
Our device showing off.

For a school project I have teamed up with a friend to create a small embedded system. He had this old serial cash register display lying around which can display semi-alphanumeric strings (actually just 0-9 and the letters H, E, L and P). We’ve programmed a PIC16F636 in C to encode data with RS232 timing and send it through our own circuit which connects to a serial port. Since this PIC chip doesn’t have a hardware UART, we’ve coded a software UART using inline assembly. We’ve created a report about this, which I will only release in Dutch. I believe it should be obvious what’s going on from a technical standpoint.
Here’s the PDF.


Using GeoIP from within Nginx

WebSVN in Japanese
This is what it should look like if you are in Japan.

Since late last summer me and my friends have been experimenting with Nginx. It’s a neat little server, sublimely fast and it’s config format doesn’t make you wince. I use it especially for proxying dynamic content from other servers (like Mongrel) but it handles static content equally well.
I’ve played around with geolocation in most of my Rails apps and it made me think this sort of environmental information might just as well be managed by the server. The folks at MaxMind felt the same way, it seems. There are server-side modules available for Apache and Lighty. For Nginx it takes a little more effort, but it’s very doable. Let’s make it so!
Get the GeoLite CSV:

 $ wget http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip

Unpack it:

 $ unzip GeoIPCountryCSV.zip

Get the Nginx tarball:

 $ wget http://sysoev.ru/nginx/nginx-0.5.35.tar.gz

Unpack it:

 $ tar zxvf nginx-0.5.35.tar.gz

You can also get Nginx through you package manager but mine (Debian) didn’t install the included Perl script to convert the MaxMind CSVfile. You can run the script on the CSV file you extracted by running it like so:

 $ perl ./nginx-0.5.35/contrib/geo2nginx.pl < GeoLiteCity_20080301/GeoLiteCity-Location.csv > countries.conf

This generates a countries.conf which Nginx can use. You have to include it in your nginx.conf. Here’s what I added to my nginx.conf in the http namespace. Before this step I moved the generated countries.conf file to my /etc/nginx directory.

geo $country {
   default no;
   include /etc/nginx/countries.conf;
   127.0.0.0/24  us;
}

This $country variable you set up only lives in Nginx so far. You have to add a proxy_set_header or fastcgi_param like so:

 fastcgi_param COUNTRY $country

Or

 proxy_set_header COUNTRY $country;

This will give you a $_SERVER[‘COUNTRY’] (in PHP) or something simmilar.
I’ve used this to automatically set the preferred language in my WebSVN site.


Melodyne Direct Note Access

Several friends informed me of a new technology by Melodyne called Direct Note Access. So far I’m baffled as to how it works. I find it an amazing feat and I hope they reveal some more information about the mechanics of it. Anyway, here is the very impressive demo video:



Update: I’ve found a video of a presentation at the Frankfurt Musikmesse 2008 by the inventor Peter Neubäcker himself.



Great presentation, more source material explored and some hints as to how it works. From what Peter is saying, I suppose it works a bit like this: The source material’s spectral information is analyzed. For example if a root tone of 220 hz wave is detected that counts as A3 and so on, given some leniency and/or self-reference. I think that’s how the old Melodyne works, but they have extended this technology to deal with polyphonic material. I speculate it’s somehow done by looking for other waves at certain ratios (harmonics) after a root tone (fundamental) has been identified. These resampled tones can be pitched, arranged and timestretched to create new notes and chords.

Update 2: Found another video on Melodyne’s media page that seems to confirm my hypothesis. Thank you Sound on Sound!





All I can say for certain is that Mr. Neubäcker is a genius. Can’t wait to check out the plugin.


Testing C++ in Ruby with Automake and RSpec

Since I’m a C++ newbie, I felt I needed more confidence in my code. As I’ve been programming in Ruby for almost 2 years now, I decided to look for a way to test my C++ code in Ruby. I found an excellent post by Dean Wampler that deals with just this topic. Please take the time to read this fascinating article before continuing. I happened to have been playing with autotools for a different C++ project last week, so I decided to use them for this one too. I decided not to put the SWIG stuff into the Makefile, but rather use a shell script. Automake will make sure the modules get built the way they need to be built, and I can put everything described in Dean’s article in a little shell script which builds the wrapper object for Ruby. I’m using a file src/units.i which loads some module headers for SWIG to wrap. This code is now irrelevant. I’ve found a way to generate this by using mkmf

#!/bin/sh

CXX=/usr/bin/g++
SRC_DIR=src
CFLAGS="-fPIC -fno-strict-aliasing -g -O2"
BIN_DIR=bin
RUBY_LIBS=/usr/lib/ruby/1.8/i486-linux
SWIG=/usr/bin/swig

cd $SRC_DIR

SRCS=`ls *.cpp | sed "s/.*_wrap\.cpp//"`
OBJS=`ls *.o`

`${CXX} -I. -I${RUBY_LIBS} ${CFLAGS} -c ${SRCS}`
`${SWIG} -c++ -ruby -Wall -o units_wrap.cpp units.i`
`${CXX} -I. -I${RUBY_LIBS} ${CFLAGS} -c units_wrap.cpp`
`${CXX} -shared -L. -rdynamic -Wl,-export-dynamic -L/usr/local/lib -o units.so ${OBJS} -lruby1.8 -lpthread -ldl -lcrypt -lm -lc`

You could extend it to take options for which module to build. As in my previous autotools example I have a ‘src’ dir containing my C++ code, and a new ‘spec’ dir containing my RSpec specifications in Ruby. The spec_helper.rb in the spec dir is taken from Dean’s example. Here’s an example of a spec for a FileReader class

require File.dirname(__FILE__) + '/spec_helper'
require 'units'

describe Units::FileReader do
  it "should be a constant on module Units" do
    Units.constants.should include('FileReader')
  end
end

describe Units::FileReader, ".new" do
  it "should create a new object of the type FileReader" do
    fr = Units::FileReader.new("file.txt")
    fr.filename.should_be "file.txt"
  end
end

describe Units::FileReader, "#openFile" do
  it "should open a file" do
    fr = Units::FileReader.new
    fr.openFile("file.txt").should_be true
    fr.filename.should_be "file.txt"
  end
end

describe Units::FileReader, "#closeFile" do
  it "should close a file" do
    fr = Units::FileReader.new
    fr.closeFile.should_be true
    fr.filename.should_be ""
  end
end

describe Units::FileReader, "#readChar" do
  it "should read a char" do
    fr = Units::FileReader.new("file.txt")
    char = fr.readChar
    char.should_be fr.ch
    char.is_a?(String).should_be true
    char.length.should_be 1
  end
end

describe Units::FileReader, "#readLine" do
  it "should read a line from the file" do
    fr = Units::FileReader.new("file.txt")
    line = fr.readLine
    line.is_a?(String).should_be true
    line.match(/^.*\n$/).should_not be_nil
  end
end

One little caveat I ran into: you have to expose the private variables of you C++ class with public accessors to be able to use them. Dean’s example shows these two little methods that do this, but it wasn’t obvious to me as my brain is cooked by programming in Ruby for too long. Hope this was helpful for anyone who wants to get started on testing their C++ code in Ruby easily.


Using autotools with C++ to make GTK apps

I’ve been playing around with GTK+, specifically gtkmm last week. I love the GTK+ GUI and I want to write some portable desktop applications. Luckily there are great docs for newbies to get started with. Although C++ has never been my language of choice, I really want to learn it. I think I will warm up to it given I can find a style that works for me. First up are Makefiles. Oh, Makefile. How slender and seductive you start out. Such warts you grow. So much does your ass inflate. After hacking away on my own Makefile for about 2 days I still had code that compiled. But along with that feat came an ugly Makefile which needed constant pruning. I decided it was enough, and thought I’d give automake a try, as is recommended in the gtkmm docs. Luckily the docs are good. But I think they need a bit of updating. On a new C++ project, here’s what I do. I’m using the first gtkmm example here.

aczid@homer:~/helloworld_gtk$ ls -lR
.:
total 4
drwxr-xr-x 3 aczid aczid 4096 2008-03-18 20:57 src

./src:
total 12
-rw-r--r-- 1 aczid aczid 362 2008-02-09 11:35 helloworld.cpp
-rw-r--r-- 1 aczid aczid 367 2008-02-09 11:32 helloworld.h
-rw-r--r-- 1 aczid aczid 228 2008-02-09 11:33 main.cpp
aczid@homer:~/helloworld_gtk$

As you see I have a ‘src’ dir conatining my C++ sources, and no Makefile. Now comes the magic.

aczid@homer:~/helloworld_gtk$ autoscan
aczid@homer:~/helloworld_gtk$ ls -l
total 8
-rw-r--r-- 1 aczid aczid    0 2008-03-18 20:59 autoscan.log
-rw-r--r-- 1 aczid aczid  475 2008-03-18 20:59 configure.scan
drwxr-xr-x 3 aczid aczid 4096 2008-03-18 20:57 src
aczid@homer:~/helloworld_gtk$ mv configure.scan configure.ac

Autoscan has generated the input file for autoconf for you. Let’s take a look:

 #                                               -*- Autoconf -*-
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
 AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
 AC_CONFIG_SRCDIR([src/main.cpp])
 AC_CONFIG_HEADER([config.h])
 
 # Checks for programs.
 AC_PROG_CXX
 AC_PROG_CC
 
 # Checks for libraries.
 
 # Checks for header files.
 
 # Checks for typedefs, structures, and compiler characteristics.
 
 # Checks for library functions.
 
 AC_OUTPUT

Let’s add a few lines.

 #                                               -*- Autoconf -*-
 # Process this file with autoconf to produce a configure script.
  
 AC_PREREQ(2.61)
 FULL-PACKAGE-NAME(Hello World)
 VERSION(1.0)
 BUG-REPORT-ADDRESS(bugs@aczid.nl)
 AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
 AC_CONFIG_SRCDIR([src/main.cpp])
 AC_CONFIG_HEADER([config.h])
 AM_INIT_AUTOMAKE
 
 # Checks for programs.
 AC_PROG_CXX
 AC_PROG_CC
  
 # Checks for libraries.
 PKG_CHECK_MODULES(DEPS, gtkmm-2.4 >= 2.4 gtk+-2.0 >= 2.2 glib-2.0 >= 2.2)
 AC_SUBST(DEPS_CFLAGS)
 AC_SUBST(DEPS_LIBS)

 # Checks for header files.
  AC_STDC_HEADERS

 # Checks for typedefs, structures, and compiler characteristics.
 
 # Checks for library functions.
 
 AC_CONFIG_FILES([Makefile src/Makefile])
 AC_OUTPUT

You see I added some GTK libs here. The next 2 lines after that set up the compiler options for them. Also notice I added references to a Makefile in the config files macro. These files need stubs to be processed by automake. There are a lot of macros in autoconf to do all kinds of crazy things. Edit ./Makefile.am and add:

 SUBDIRS = src

And in the src/Makefile.am you put:

 bin_PROGRAMS = helloworld
 helloworld_SOURCES = helloworld.cpp main.cpp
 helloworld_LDADD = $(DEPS_LIBS)
 AM_CPPFLAGS = $(DEPS_CFLAGS)

See, those LDADD and CPPFLAGS macros rely on our DEPS_LIBS and DEPS_CFLAGS variables declared in the configure.ac file. Now all you need to do is run some commands!

aczid@homer:~/helloworld_gtk$ aclocal
/usr/share/aclocal/libmcrypt.m4:17: warning: underquoted definition of AM_PATH_LIBMCRYPT
/usr/share/aclocal/libmcrypt.m4:17:   run info '(automake)Extending aclocal'
/usr/share/aclocal/libmcrypt.m4:17:   or see http://sources.redhat.com/automake/automake.html#Extending-aclocal
aczid@homer:~/helloworld_gtk$ autoconf
aczid@homer:~/helloworld_gtk$ autoheader
aczid@homer:~/helloworld_gtk$ touch NEWS README AUTHORS ChangeLog
aczid@homer:~/helloworld_gtk$ automake --add-missing

Phew, that’s it! Now you can run ./confgure and it will generate a Makefile from the Makefile.in, which was in turn generated by Automake.

aczid@homer:~/helloworld_gtk$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for g++... g++
checking for C++ compiler default output file name... a.out
checking whether the C++ compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking for style of include used by make... GNU
checking dependency style of g++... gcc3
checking for gcc... gcc
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking dependency style of gcc... gcc3
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for a BSD-compatible install... /usr/bin/install -c
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for DEPS... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands
aczid@homer:~/helloworld_gtk$ make
cd . && /bin/sh /home/aczid/helloworld_gtk/missing --run autoheader
rm -f stamp-h1
touch config.h.in
cd . && /bin/sh ./config.status config.h
config.status: creating config.h
config.status: config.h is unchanged
make  all-recursive
make[1]: Entering directory `/home/aczid/helloworld_gtk'
Making all in src
make[2]: Entering directory `/home/aczid/helloworld_gtk/src'
g++ -DHAVE_CONFIG_H -I. -I..  -I/usr/include/gtkmm-2.4 -I/usr/lib/gtkmm-2.4/include -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/gdkmm-2.4 -I/usr/lib/gdkmm-2.4/include -I/usr/include/pangomm-1.4 -I/usr/include/atkmm-1.6 -I/usr/include/gtk-2.0 -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/gtk-2.0/include -I/usr/include/cairomm-1.0 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/atk-1.0     -g -O2 -MT helloworld.o -MD -MP -MF .deps/helloworld.Tpo -c -o helloworld.o helloworld.cpp
mv -f .deps/helloworld.Tpo .deps/helloworld.Po
g++ -DHAVE_CONFIG_H -I. -I..  -I/usr/include/gtkmm-2.4 -I/usr/lib/gtkmm-2.4/include -I/usr/include/glibmm-2.4 -I/usr/lib/glibmm-2.4/include -I/usr/include/gdkmm-2.4 -I/usr/lib/gdkmm-2.4/include -I/usr/include/pangomm-1.4 -I/usr/include/atkmm-1.6 -I/usr/include/gtk-2.0 -I/usr/include/sigc++-2.0 -I/usr/lib/sigc++-2.0/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/lib/gtk-2.0/include -I/usr/include/cairomm-1.0 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/atk-1.0     -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.cpp
mv -f .deps/main.Tpo .deps/main.Po
g++  -g -O2   -o helloworld helloworld.o main.o -lgtkmm-2.4 -lgdkmm-2.4 -latkmm-1.6 -lpangomm-1.4 -lcairomm-1.0 -lglibmm-2.4 -lsigc-2.0 -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0
make[2]: Leaving directory `/home/aczid/helloworld_gtk/src'
make[2]: Entering directory `/home/aczid/helloworld_gtk'
make[2]: Leaving directory `/home/aczid/helloworld_gtk'
make[1]: Leaving directory `/home/aczid/helloworld_gtk'
aczid@homer:~/helloworld_gtk$

See? :) I’ve quite enjoyed fooling around with this. It beats the hell out of writing your own Makefiles. It’s nice to know your app will be compatible with GNU standards and there is much less to write and consequently maintain. In the future I think I’ll look at other systems that try to ease the same pains. Autotools were made for much bigger projects than mine. Scons is what I might look into next.



Me elsewhere: