【问题标题】:Ruby C Extensions, loading external librariesRuby C 扩展,加载外部库
【发布时间】:2014-03-28 05:19:14
【问题描述】:

我正在尝试使用一些现有的 C 代码为 Raspberry Pi 构建一个 Ruby C 扩展。该代码依赖于bcm2835-1.35 库的某些功能。问题是当我尝试在 RPi 上运行一个 ruby​​ 程序时,我得到以下信息:

ruby: symbol lookup error: /usr/lib/ruby/site_ruby/2.1.0/armv6l-linux-eabihf/dht_test.so: undefined symbol: bcm2835_gpio_fsel

这是代码的样子,都在一个目录中(~/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;
}

终于

我尝试运行以下 irb,第一个函数 test1 工作正常,第二个需要 bcm2835 的函数失败并出现前面所述的错误

require 'dht_test'
include DhtTest

puts test1
puts test2

我是这个东西的新手,我确信我犯了一些严重的错误,但我几乎被困住了,如果我能得到任何帮助,我将不胜感激。

【问题讨论】:

    标签: c ruby raspberry-pi ruby-c-extension


    【解决方案1】:

    想通了,我需要将以下内容添加到我的 extconf.rb

    unless have_library('bcm2835') && append_library($libs, 'bcm2835')
      abort "Unable to appended Library bcm2835!"
    end
    

    在c99中编译也需要这个

    $CFLAGS << ' -std=c99'  // yes you need the space
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-21
      • 1970-01-01
      • 2011-10-08
      • 1970-01-01
      相关资源
      最近更新 更多