[macruby-changes] [1490] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Sat Apr 25 19:26:00 PDT 2009
Revision: 1490
http://trac.macosforge.org/projects/ruby/changeset/1490
Author: lsansonetti at apple.com
Date: 2009-04-25 19:25:59 -0700 (Sat, 25 Apr 2009)
Log Message:
-----------
working on a ruby-FFI compatible API
Modified Paths:
--------------
MacRuby/branches/experimental/inits.c
MacRuby/branches/experimental/roxor.cpp
Modified: MacRuby/branches/experimental/inits.c
===================================================================
--- MacRuby/branches/experimental/inits.c 2009-04-25 04:21:25 UTC (rev 1489)
+++ MacRuby/branches/experimental/inits.c 2009-04-26 02:25:59 UTC (rev 1490)
@@ -55,6 +55,8 @@
void Init_Encoding(void);
void Init_PostGC(void);
void Init_ObjC(void);
+void Init_BridgeSupport(void);
+void Init_FFI(void);
void
rb_call_inits()
@@ -103,4 +105,6 @@
Init_version();
Init_PostGC();
Init_ObjC();
+ Init_BridgeSupport();
+ Init_FFI();
}
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-04-25 04:21:25 UTC (rev 1489)
+++ MacRuby/branches/experimental/roxor.cpp 2009-04-26 02:25:59 UTC (rev 1490)
@@ -202,6 +202,7 @@
Function *compile_bs_struct_new(rb_vm_bs_boxed_t *bs_boxed);
Function *compile_bs_struct_writer(rb_vm_bs_boxed_t *bs_boxed,
int field);
+ Function *compile_ffi_function(void *stub, void *imp, int argc);
private:
const char *fname;
@@ -8954,10 +8955,10 @@
return bs_boxed->bs_type == BS_ELEMENT_OPAQUE ? Qtrue : Qfalse;
}
-static VALUE rb_mVM;
VALUE rb_cBoxed;
-static void
+extern "C"
+void
Init_BridgeSupport(void)
{
rb_cBoxed = rb_define_class("Boxed", rb_cObject);
@@ -8967,7 +8968,8 @@
(void *)rb_boxed_is_opaque, 0);
boxed_ivar_type = rb_intern("__octype__");
- //VALUE rb_mBS = rb_define_module_under(rb_mVM, "BridgeSupport");
+ bs_const_magic_cookie = rb_str_new2("bs_const_magic_cookie");
+ rb_objc_retain((void *)bs_const_magic_cookie);
}
static inline void
@@ -9305,6 +9307,143 @@
#endif
}
+// FFI
+
+static const char *
+convert_ffi_type(VALUE type)
+{
+ const char *typestr = StringValueCStr(type);
+ assert(typestr != NULL);
+
+ // Converting Ruby-FFI types to Objective-C runtime types.
+ if (strcmp(typestr, "char") == 0) {
+ return "c";
+ }
+ if (strcmp(typestr, "uchar") == 0) {
+ return "C";
+ }
+ if (strcmp(typestr, "short") == 0) {
+ return "s";
+ }
+ if (strcmp(typestr, "ushort") == 0) {
+ return "S";
+ }
+ if (strcmp(typestr, "int") == 0) {
+ return "i";
+ }
+ if (strcmp(typestr, "uint") == 0) {
+ return "I";
+ }
+ if (strcmp(typestr, "long") == 0) {
+ return "l";
+ }
+ if (strcmp(typestr, "ulong") == 0) {
+ return "L";
+ }
+ if (strcmp(typestr, "long_long") == 0) {
+ return "q";
+ }
+ if (strcmp(typestr, "ulong_long") == 0) {
+ return "Q";
+ }
+ if (strcmp(typestr, "string") == 0) {
+ return "*";
+ }
+ if (strcmp(typestr, "pointer") == 0) {
+ return "^";
+ }
+
+ rb_raise(rb_eArgError, "unrecognized string `%s' given as FFI type",
+ typestr);
+}
+
+Function *
+RoxorCompiler::compile_ffi_function(void *stub, void *imp, int argc)
+{
+ // VALUE func(VALUE rcv, SEL sel, VALUE arg1, VALUE arg2, ...) {
+ // return stub(imp, arg2, arg1, ...);
+ // }
+ std::vector<const Type *> f_types;
+ f_types.push_back(RubyObjTy);
+ f_types.push_back(PtrTy);
+ for (int i = 0; i < argc; i++) {
+ f_types.push_back(RubyObjTy);
+ }
+ FunctionType *ft = FunctionType::get(RubyObjTy, f_types, false);
+ Function *f = cast<Function>(module->getOrInsertFunction("", ft));
+
+ bb = BasicBlock::Create("EntryBlock", f);
+
+ Function::arg_iterator arg = f->arg_begin();
+ arg++; // skip self
+ arg++; // skip sel
+
+ std::vector<Value *> params;
+ std::vector<const Type *> stub_types;
+
+ // First argument is the function implementation.
+ params.push_back(compile_const_pointer(imp));
+ stub_types.push_back(PtrTy);
+
+ // Following arguments are the given arguments.
+ for (int i = 0; i < argc; i++) {
+ params.push_back(arg++);
+ stub_types.push_back(RubyObjTy);
+ }
+
+ // Cast the given stub using the correct function signature.
+ FunctionType *stub_ft = FunctionType::get(RubyObjTy, stub_types, false);
+ Value *stub_val = new BitCastInst(compile_const_pointer(stub),
+ PointerType::getUnqual(stub_ft), "", bb);
+
+ // Call the stub and return its return value.
+ CallInst *stub_call = CallInst::Create(stub_val, params.begin(),
+ params.end(), "", bb);
+ ReturnInst::Create(stub_call, bb);
+
+ return f;
+}
+
+static VALUE
+rb_ffi_attach_function(VALUE rcv, SEL sel, VALUE name, VALUE args, VALUE ret)
+{
+ const char *symname = StringValueCStr(name);
+ void *sym = dlsym(RTLD_DEFAULT, symname);
+ if (sym == NULL) {
+ rb_raise(rb_eArgError, "given function `%s' could not be located",
+ symname);
+ }
+
+ std::string types;
+ types.append(convert_ffi_type(ret));
+
+ Check_Type(args, T_ARRAY);
+ const int argc = RARRAY_LEN(args);
+ for (int i = 0; i < argc; i++) {
+ types.append(convert_ffi_type(ret));
+ }
+
+ rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)vm_gen_stub(types, argc, false);
+ Function *f = RoxorCompiler::shared->compile_ffi_function((void *)stub,
+ sym, argc);
+ IMP imp = GET_VM()->compile(f);
+
+ VALUE klass = rb_singleton_class(rcv);
+ rb_objc_define_method(klass, symname, (void *)imp, argc);
+
+ return Qnil;
+}
+
+extern "C"
+void
+Init_FFI(void)
+{
+ VALUE mFFI = rb_define_module("FFI");
+ VALUE mFFILib = rb_define_module_under(mFFI, "Library");
+ rb_objc_define_method(mFFILib, "attach_function",
+ (void *)rb_ffi_attach_function, 3);
+}
+
// stubs
static VALUE
@@ -9391,12 +9530,6 @@
VALUE top_self = rb_obj_alloc(rb_cTopLevel);
rb_objc_retain((void *)top_self);
GET_VM()->current_top_object = top_self;
-
- bs_const_magic_cookie = rb_str_new2("bs_const_magic_cookie");
- rb_objc_retain((void *)bs_const_magic_cookie);
-
- rb_mVM = rb_define_module("RubyVM");
- Init_BridgeSupport();
}
extern "C"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090425/83e59b79/attachment.html>
More information about the macruby-changes
mailing list