首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将D库链接到Ruby

将D库链接到Ruby
EN

Stack Overflow用户
提问于 2016-02-10 15:12:44
回答 1查看 128关注 0票数 3

我想从Ruby调用D代码。我尝试用dmd编译D代码,并使用extconf.rb创建一个共享对象文件,我可以在ruby中使用,但是我的链接失败了,dmd库显然丢失了:

代码语言:javascript
复制
    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>'

请告诉我如何从Ruby调用D代码。

我试过的代码如下:

代码语言:javascript
复制
    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 -
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-23 18:58:27

您可以使用红宝石-FFI扩展从Ruby调用D。看看这个Wiki,它解释了如何用示例精确地实现这一点。如下所示:

创建包含"i.d“的文件

代码语言:javascript
复制
import std.stdio;

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

将其编译为共享库。例如,要在Linux上编译为64位共享库,可以这样做。

代码语言:javascript
复制
dmd -shared -m64 -fPIC -defaultlib=libphobos2.so i.d

创建包含以下内容的文件"d.rb“:

代码语言:javascript
复制
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文件:

代码语言:javascript
复制
ruby ./d.rb

你应该看看hi from D

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35318856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档