2016-02-10 2 views
3

Я хотел бы назвать код D из Ruby. Я попытался скомпилировать код D с МДД и использовать extconf.rb сделать общий объектный файл, который я мог бы использовать в рубин, но моя сшивание не может каким-то образом, то D библиотека станд по-видимому, отсутствует:Связать библиотеку D с Ruby

hello.rb:1:in `require_relative': /tmp/druby/hello_c.so: undefined symbol: _D3std5stdio12__ModuleInfoZ - /tmp/druby/hello_c.so (LoadError) 
    from hello.rb:1:in `<main>' 

Пожалуйста дайте мне знать, как вызвать код D из Ruby.

Код я попытался здесь:

mkdir -p /tmp/druby 
    cd /tmp/druby 
    cat ->hello_d.d <<EOF 
    import std.stdio; 
    // a D function that we would like to call from ruby 
    extern(C) void hello_d() nothrow { 
     try { writeln("hello from d"); } catch(Throwable t) {} 
    } 
    EOF 

    cat ->hello_d.c <<EOF 
    /* This is a dummy file to trick extconf.rb to include the hello_d.o file, surely this could be done from extconf.rb as well, but how? */ 
    EOF 

    cat ->hello_c.c <<EOF 
    #include <stdio.h> 
    #include "ruby.h" 

    /* c function */ 
    void hello_c(){ 
     printf("hello from c\n"); 
    } 


    /* ruby function for hello_c */ 
    VALUE method_hello_c(VALUE self){ 
     hello_c(); 
     return Qnil; 
    } 


    /* ruby function for hello_d */ 
    VALUE method_hello_d(VALUE self){ 
     if(!rt_init()) { return 1; } 
     hello_d(); 
     rt_term(); 
     return Qnil; 
    } 


    /* ruby module and class definition */ 
    /* This method must be named "Init_#{filename.lower}" */ 
    void Init_hello_c() { 
     VALUE hello_module = rb_define_module("HelloCModule"); 
     VALUE hello_class = rb_define_class_under(hello_module, "HelloC", rb_cObject); 
     rb_define_method(hello_class, "hello_c", method_hello_c, 0); 
     rb_define_method(hello_class, "hello_d", method_hello_d, 0); 
    } 

    EOF 

    cat ->extconf.rb <<EOF 
    # Loads mkmf which is used to make makefiles for Ruby extensions 
    require 'mkmf' 

    lib = File.expand_path('../../lib', __FILE__) 
    \$LOAD_PATH.unshift(lib) unless \$LOAD_PATH.include?(lib) 

    # Give it a name 
    extension_name = 'hello_c' 

    # The destination 
    dir_config(extension_name,".") 

    with_cflags('-fPIC -Wall -O3 -rdynamic -m64 -L/usr/lib/x86_64-linux-gnu -Xlinker --export-dynamic -Xlinker -Bstatic -lphobos2 -Xlinker -Bdynamic -lpthread -lm -lrt -ldl') do 
     create_makefile(extension_name) 
    end 

    EOF 

    cat ->hello.rb <<EOF 
    require_relative 'hello_c' 

    puts "hello from ruby" 

    hello_c = HelloCModule::HelloC.new 

    hello_c.hello_c() 

    EOF 


    # 1. First make the hello_d.o file 
    dmd -c -fPIC hello_d.d -defaultlib=libphobos2.so 


    # 2. Make the ruby Makefile 
    ruby extconf.rb 

    # 3. Compile the shared library 
    make 

    # 4. Try to call it from ruby 
    ruby hello.rb 

    cd - 
+0

ли вы связать в Phobos общей библиотеке тоже? Похоже нет, попробуйте добавить '-defaultlib = libphobos2.so' в команду' dmd'. –

+0

Я попытался добавить libphobos2.so в команду dmd (см. Пересмотренный код выше), но он не изменит результат, спасибо за предложение в любом случае. Также библиотека phobos2 уже была в флагов. –

+0

Ваш способ листинга файлов и команд в одном блоке кода является утомительным для чтения. – weltensturm

ответ

1

Вы можете позвонить D Руби с помощью расширения Ruby-FFI. Взгляните на this Wiki, в котором объясняется, как это сделать с примерами. Такие, как следующий:

Создать файл «i.d», содержащий

import std.stdio; 

extern(C) 
void hello() 
{ 
    writeln("hi from D"); 
} 

Собирать как разделяемая библиотека. Например, чтобы скомпилировать как 64-битной общей библиотеки на Linux, вы можете сделать

dmd -shared -m64 -fPIC -defaultlib=libphobos2.so i.d 

Создать файл "d.rb", содержащий:

require 'rubygems' 
require 'ffi' 

module DInterface 
extend FFI::Library 
ffi_lib './i.so' 
attach_function :rt_init, :rt_init, [], :int 
attach_function :rt_term, :rt_term, [], :int 
attach_function :hello, :hello, [], :void 
end 

# call init 
DInterface::rt_init 

# our function 
DInterface::hello 

# terminate 
DInterface::rt_term 

запустить файл Ruby:

ruby ./d.rb 

вы должны увидеть hi from D

+1

Решение FFI работает хорошо, и я считаю, что в настоящее время это лучшее решение. Однако сохранение и синхронизация объектов между средой исполнения Ruby и D оказывается сложной из-за очень ограниченной функциональности FFI. –

Смежные вопросы