Created
April 8, 2012 14:55
-
-
Save lomereiter/2337729 to your computer and use it in GitHub Desktop.
howto: d & ruby ffi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
test: test_c.o test_d.o | |
cc -shared -m32 test_c.o test_d.o -o test.so -lphobos2 | |
test_c.o: test.c | |
gcc -c -m32 test.c -o test_c.o | |
test_d.o: test.d | |
dmd -c -m32 test.d -oftest_d.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern void attach(void); | |
extern void detach(void); | |
void __attach(void) __attribute__((constructor)); | |
void __detach(void) __attribute__((destructor)); | |
void __attach(void) { attach(); } | |
void __detach(void) { detach(); } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// the following two links are very useful: | |
// 1) http://stackoverflow.com/questions/9956994/return-a-class-instance-as-a-pointer-in-d | |
// 2) http://stackoverflow.com/questions/9759880/automatically-executed-functions-when-loading-shared-libraries | |
module test; | |
import std.conv; | |
import core.memory : GC; | |
import std.c.stdlib : malloc, free; | |
import core.runtime : Runtime; | |
extern (C) export void attach() { Runtime.initialize(); } | |
extern (C) export void detach() { Runtime.terminate(); } | |
public struct Foo { | |
public string hello = "hello, world!"; | |
} | |
extern (C) size_t foo_size = Foo.sizeof; | |
import std.stdio : printf; | |
extern (C) void* foo_new() { | |
Foo* p = cast(Foo*)malloc(Foo.sizeof); | |
std.conv.emplace(p); | |
GC.addRange(p, Foo.sizeof); | |
return p; | |
} | |
extern (C) void foo_free(Foo* p) { | |
GC.removeRange(p); | |
free(cast(void*)p); | |
} | |
extern (C) immutable(char)* foo_hello(Foo* p) { | |
return p.hello.ptr; | |
} | |
void main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'ffi' | |
module MyLibrary | |
extend FFI::Library | |
ffi_lib './test.so' | |
attach_function :foo_hello, [:pointer], :string | |
attach_function :foo_new, [], :pointer | |
attach_function :foo_free, [:pointer], :void | |
end | |
class Foo | |
def initialize | |
@ptr = MyLibrary.foo_new | |
# using FFI::AutoPointer causes too much overhead. | |
ObjectSpace.define_finalizer @ptr, Foo.finalize(@ptr) | |
end | |
def hello | |
@hello ||= MyLibrary.foo_hello @ptr | |
end | |
def self.finalize ptr | |
proc { MyLibrary.foo_free ptr } | |
end | |
end | |
require 'benchmark' | |
10000.times { Foo.new } # warming up | |
GC.start | |
# timings on my machine: | |
# | |
# 0.154811253 ruby 1.9.3p125 (2012-02-16 revision 34643) [i686-linux] | |
# 2.536235094 rubinius 1.2.4 | |
# -- jruby 1.6.6 (ruby-1.8.7-p357) (2012-01-30 5673572) (Java HotSpot(TM) Client VM 1.7.0_03) [linux-i386-java] | |
# | |
# JRuby didn't manage to load D library: | |
# LoadError: Could not open library './test.so' : ./test.so: undefined symbol: __data_start | |
p Benchmark.realtime { 10000.times { Foo.new } } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment