crubydllffifiddle

access dll function on C project from Ruby


I have a project written in C controlling hardware devices. I'm trying to access DLL functions in my projects from a Ruby app in order to control the hardware from the Ruby web app. I'm failing in loading the dll project files using FFI and Fiddle. Does anyone have an example I can use to share of a similar case?

Thanks.


Solution

  • I suggest using SWIG (http://swig.org)

    I'll give you an example on OSX but you could find the equivalent on Windows as well.

    Let's say you have a library (in my case hello.bundle or in your case hello.DLL) with this header file hello.h

    #ifndef __HELLO__
    #define __HELLO__
    
    extern void say_hello(void); 
    
    #endif
    

    and you wanna call say_hello from a ruby program like that run.rb:

    # file: run.rb
    require 'hello'
    
    # Call a c function
    Hello.say_hello
    

    (Pay attention here that the module name is Capitalised)

    what you have to do is to create a file hello.i like that:

    %module hello
     %{
     #include "hello.h"
     %}
    
     // Parse the original header file
     %include "hello.h"
    

    And then run the command:

    swig -ruby hello.i
    

    This will generate a file .c that is a wrapper that will be installed as a wrapper module for your ruby environment: hello_wrap.c.

    Then you need to create a file extconf.rb with this content:

    require 'mkmf'
    create_makefile('hello')
    

    Pay attention that here "hello" is the name of our module in the file .i.

    Then you must run ruby extconf.rb that will generate a Makefile.

    ruby extconf.rb    
    creating Makefile
    

    Then you must type make that will compile the _wrap.c file against the library (in my case .bundle in your case .DLL).

    make
    compiling hello_wrap.c
    linking shared-object hello.bundle
    

    Now you must type make install (or sudo make install on Unix/Osx)

    sudo make install
    Password:
    /usr/bin/install -c -m 0755 hello.bundle /Library/Ruby/Site/2.3.0/universal-darwin17
    

    Then you can run your program run.rb

    ruby run.rb 
    Hello, world!
    

    I'll paste here below the .c file used to generate the library hello.bundle

    #include <stdio.h>
    #include "hello.h"
    
    void say_hello(void) {
        printf("Hello, world!\n");
        return;
    }
    

    If you leave this file along with it's .h file the Makefile will build the library for you

    make
    compiling hello.c
    compiling hello_wrap.c
    linking shared-object hello.bundle