I'm trying to build a Ruby C Extension for Raspberry Pi using some existing C code. The code relies on the bcm2835-1.35 library for some functions. Problem is that when I try to run the a ruby program using on the RPi, I get the following:
ruby: symbol lookup error: /usr/lib/ruby/site_ruby/2.1.0/armv6l-linux-eabihf/dht_test.so: undefined symbol: bcm2835_gpio_fsel
Here's what the code looks like, this is all in one directory (~/Ruby/dht_test)
extconf.rb
# Loads mkmf which is used to make makefiles for Ruby extensions
require 'mkmf'
# Load Libraries
LIBDIR = RbConfig::CONFIG['libdir']
INCLUDEDIR = RbConfig::CONFIG['includedir']
HEADER_DIRS = [
# First search /opt/local for macports
'/opt/local/include',
# Then search /usr/local for people that installed from source
'/usr/local/include',
# Check the ruby install locations
INCLUDEDIR,
# Finally fall back to /usr
'/usr/include',
]
LIB_DIRS = [
# Then search /usr/local for people that installed from source
'/usr/local/lib',
# Check the ruby install locations
LIBDIR,
# Finally fall back to /usr
'/usr/lib',
]
unless find_header('bcm2835.h')
abort 'bcm2835 is missing'
end
dir_config('bcm2835', HEADER_DIRS, LIB_DIRS) # Tried with the line commented out, doesn't make any difference
# Give it a name
extension_name = 'dht_test'
# The destination
dir_config(extension_name)
# Do the work
create_makefile(extension_name)
dhtreader.h
/* for usleep */
//#define _BSD_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <bcm2835.h>
#include <unistd.h>
int readDHT(int type, int pin, float *temp_p, float *hum_p);
dhtreader.c
#include "dhtreader.h"
int readDHT(int type, int pin, float *temp_p, float *hum_p)
{
int counter = 0;
int laststate = HIGH;
int i = 0;
int j = 0;
int checksum = 0;
#ifdef DEBUG
int bitidx = 0;
int bits[250];
#endif
int data[100];
// Set GPIO pin to output
bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_write(pin, HIGH);
usleep(500000); // 500 ms
bcm2835_gpio_write(pin, LOW);
usleep(20000);
bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT);
ect....
dht_test.c
// Include the Ruby headers and goodies
#include "ruby.h"
#include "dhtreader.h"
// Defining a space for information and references about the module to be stored internally
VALUE DhtTest = Qnil;
// Prototype for the initialization method - Ruby calls this, not you
void Init_dht_test();
// Prototype for our method 'test1' - methods are prefixed by 'method_' here
VALUE method_test1(VALUE self);
VALUE method_test2(VALUE self);
// The initialization method for this module
void Init_dht_test() {
DhtTest = rb_define_module("DhtTest");
rb_define_method(DhtTest, "test1", method_test1, 0);
rb_define_method(DhtTest, "test2", method_test2, 0);
}
// Our 'test1' method.. it simply returns a value of '10' for now.
VALUE method_test1(VALUE self) {
int x = 10;
return INT2NUM(x);
}
VALUE method_test2(VALUE self){
float temp;
float hum;
readDHT(22, 4, &temp, &hum);
printf("Temperture: %f, Humidity %f", temp, hum);
return temp;
}
Finally
I try to run the following irb, the first function test1 works fine, the second function which requires the bcm2835 fails with the previously stated error
require 'dht_test'
include DhtTest
puts test1
puts test2
I'm new to this stuff and I'm sure I'm making some egregious mistakes, but I'm pretty much stuck and would appreciate any help I can get.