Skip to content

Commit

Permalink
Flesh out more of capi trying to build a number of extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
Evan Phoenix committed Mar 30, 2010
1 parent 69b2a03 commit 71cf2a5
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 37 deletions.
10 changes: 10 additions & 0 deletions vm/builtin/io.cpp
Expand Up @@ -746,6 +746,16 @@ namespace rubinius {
return Fixnum::from(new_fd);
}

void IO::set_nonblock(STATE) {
int flags = fcntl(descriptor_->to_native(), F_GETFL);
if(flags == -1) return;

if(flags & O_NONBLOCK == 0) {
flags |= O_NONBLOCK;
fcntl(descriptor_->to_native(), F_SETFL, flags);
}
}

/* IOBuffer methods */
IOBuffer* IOBuffer::create(STATE, size_t bytes) {
IOBuffer* buf = state->new_object<IOBuffer>(G(iobuffer));
Expand Down
2 changes: 2 additions & 0 deletions vm/builtin/io.hpp
Expand Up @@ -114,6 +114,8 @@ namespace rubinius {
// Ruby.primitive :io_query
Object* query(STATE, Symbol* op);

void set_nonblock(STATE);

class Info : public TypeInfo {
public:
BASIC_TYPEINFO(TypeInfo)
Expand Down
5 changes: 5 additions & 0 deletions vm/builtin/module.cpp
Expand Up @@ -87,6 +87,11 @@ namespace rubinius {
state->shared.inc_global_serial();
}

void Module::del_const(STATE, Symbol* sym) {
constants_->remove(state, sym);
state->shared.inc_global_serial();
}

void Module::set_const(STATE, const char* name, Object* val) {
set_const(state, state->symbol(name), val);
}
Expand Down
2 changes: 2 additions & 0 deletions vm/builtin/module.hpp
Expand Up @@ -70,6 +70,8 @@ namespace rubinius {
Object* get_const(STATE, Symbol* sym, bool* found);
Object* get_const(STATE, const char* sym);

void del_const(STATE, Symbol* sym);

void set_name(STATE, Module* under, Symbol* name);

void add_method(STATE, Symbol* name, Executable* exec, Symbol* vis = 0);
Expand Down
11 changes: 4 additions & 7 deletions vm/capi/capi.cpp
Expand Up @@ -20,7 +20,6 @@
#include "dispatch.hpp"
#include "capi/capi.hpp"
#include "capi/ruby.h"

#include <string>
#include <vector>
#include <tr1/unordered_map>
Expand Down Expand Up @@ -282,8 +281,7 @@ extern "C" {
return capi_call_super_native(env, argc, args);
}

VALUE capi_rb_funcall(const char* file, int line,
VALUE receiver, ID method_name, int arg_count, ...) {
VALUE rb_funcall(VALUE receiver, ID method_name, int arg_count, ...) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

va_list varargs;
Expand All @@ -297,14 +295,13 @@ extern "C" {

va_end(varargs);

return capi_funcall_backend_native(env, file, line,
return capi_funcall_backend_native(env, "", 0,
env->get_object(receiver),
reinterpret_cast<Symbol*>(method_name),
arg_count, args);
}

VALUE capi_rb_funcall2(const char* file, int line,
VALUE receiver, ID method_name, int arg_count, VALUE* v_args) {
VALUE rb_funcall2(VALUE receiver, ID method_name, int arg_count, const VALUE* v_args) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

Object** args = reinterpret_cast<Object**>(alloca(sizeof(Object**) * arg_count));
Expand All @@ -313,7 +310,7 @@ extern "C" {
args[i] = env->get_object(v_args[i]);
}

return capi_funcall_backend_native(env, file, line,
return capi_funcall_backend_native(env, "", 0,
env->get_object(receiver),
reinterpret_cast<Symbol*>(method_name),
arg_count, args);
Expand Down
11 changes: 11 additions & 0 deletions vm/capi/exception.cpp
Expand Up @@ -24,4 +24,15 @@ extern "C" {
Exception *exc = capi::c_as<Exception>(env->get_object(exc_handle));
capi::capi_raise_backend(exc);
}

VALUE rb_errinfo() {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
return env->get_handle(env->state()->thread_state()->current_exception());
}

void rb_set_errinfo(VALUE err) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
Exception *exc = capi::c_as<Exception>(env->get_object(err));
env->state()->thread_state()->set_current_exception(exc);
}
}
8 changes: 8 additions & 0 deletions vm/capi/io.cpp
Expand Up @@ -86,4 +86,12 @@ extern "C" {

lock.lock();
}

void rb_io_set_nonblock(rb_io_t* dummy) {
VALUE io_handle = (VALUE)dummy;
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

IO* io = c_as<IO>(env->get_object(io_handle));
io->set_nonblock(env->state());
}
}
27 changes: 27 additions & 0 deletions vm/capi/module.cpp
Expand Up @@ -72,6 +72,13 @@ extern "C" {
rb_define_singleton_method(class_handle, "allocate", allocator, 0);
}

void rb_undef_alloc_func(VALUE class_handle) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
rb_undef_method(
env->get_handle(env->get_object(class_handle)->metaclass(env->state())),
"allocate");
}

void rb_define_attr(VALUE module_handle, const char* attr_name, int readable, int writable) {
if(readable) {
rb_funcall(module_handle, rb_intern("attr_reader"), 1, rb_intern(attr_name));
Expand Down Expand Up @@ -129,4 +136,24 @@ extern "C" {
void rb_undef_method(VALUE module_handle, const char* name) {
rb_funcall(module_handle, rb_intern("undef_method!"), 1, ID2SYM(rb_intern(name)));
}

VALUE rb_mod_ancestors(VALUE mod) {
return rb_funcall(mod, rb_intern("ancestors"), 0);
}

VALUE rb_mod_name(VALUE mod) {
return rb_funcall(mod, rb_intern("name"), 0);
}

VALUE rb_module_new(void) {
return rb_funcall(rb_cModule, rb_intern("new"), 0);
}

VALUE rb_mod_remove_const(VALUE mod, VALUE name) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

Module* module = c_as<Module>(env->get_object(mod));
module->del_const(env->state(), reinterpret_cast<Symbol*>(name));
return Qnil;
}
}
9 changes: 6 additions & 3 deletions vm/capi/object.cpp
Expand Up @@ -70,7 +70,8 @@ extern "C" {
};

// Copied from MRI
void rb_check_type(VALUE x, CApiType t) {
void rb_check_type(VALUE x, int i) {
CApiType t = (CApiType)i;
struct types *type = builtin_types;

if (x == Qundef) {
Expand Down Expand Up @@ -311,6 +312,8 @@ extern "C" {
VALUE rb_any_to_s(VALUE obj) {
return rb_obj_as_string(obj);
}



VALUE rb_obj_instance_eval(int argc, VALUE* argv, VALUE self) {
return rb_funcall2(self, rb_intern("instance_eval"), argc, (const VALUE*)argv);
}
}
73 changes: 46 additions & 27 deletions vm/capi/ruby.h
Expand Up @@ -352,6 +352,16 @@ struct RFloat {
// To provide nicer error reporting
#define RHASH(obj) assert("RHASH() is not supported")

typedef struct {
void* dummy;
} rb_io_t;

#define HAVE_RB_IO_T 1

// Fake it out, just make the ptr be the val
// MRI checks also that it's not closed...
#define GetOpenFile(val, ptr) (ptr) = ((rb_io_t*)(val))

/*
* The immediates.
*/
Expand Down Expand Up @@ -638,16 +648,6 @@ double rb_num2dbl(VALUE);
int arity,
CApiMethodKind kind);

/** Call method on receiver, args as varargs. */
VALUE capi_rb_funcall(const char* file, int line,
VALUE receiver, ID method_name,
int arg_count, ...);

/** Call the method with args provided in a C array. */
VALUE capi_rb_funcall2(const char* file, int line,
VALUE receiver, ID method_name,
int arg_count, VALUE* args);

/** Retrieve a Handle to a globally available object. @internal. */
VALUE capi_get_constant(CApiConstant type);

Expand Down Expand Up @@ -811,12 +811,13 @@ double rb_num2dbl(VALUE);

/** check if obj is frozen. */
VALUE rb_obj_frozen_p(VALUE obj);
#define OBJ_FROZEN(obj) (RTEST(rb_obj_frozen_p(obj)))

/** raise error on class */
void rb_error_frozen(const char* what);

/** Raises an exception if obj_handle is not the same type as 'type'. */
void rb_check_type(VALUE obj_handle, CApiType type);
void rb_check_type(VALUE obj_handle, int type);

#define Check_Type(v,t) rb_check_type((VALUE)(v),(t))

Expand Down Expand Up @@ -866,6 +867,11 @@ double rb_num2dbl(VALUE);
/** Set constant on the given module */
void rb_const_set(VALUE module_handle, ID name, VALUE const_handle);

VALUE rb_mod_remove_const(VALUE mod, VALUE name);
VALUE rb_mod_ancestors(VALUE mod);
VALUE rb_mod_name(VALUE mod);
VALUE rb_module_new(void);

/** Parses a string into a double value. If badcheck is true, raises an
* exception if the string contains non-digit or '.' characters.
*/
Expand Down Expand Up @@ -902,6 +908,9 @@ double rb_num2dbl(VALUE);
/** Define an .allocate for the given class. Should take no args and return a VALUE. */
void rb_define_alloc_func(VALUE class_handle, CApiAllocFunction allocator);

/** Undefine the .allocate for the given class. */
void rb_undef_alloc_func(VALUE class_handle);

/** Ruby's attr_* for given name. Nonzeros to toggle read/write. */
void rb_define_attr(VALUE module_handle, const char* attr_name,
int readable, int writable);
Expand Down Expand Up @@ -967,6 +976,16 @@ double rb_num2dbl(VALUE);
/** Raises passed exception handle */
void rb_exc_raise(VALUE exc_handle);

/** Return the current exception */
VALUE rb_errinfo();
#define ruby_errinfo rb_errinfo()

/** Set the current exception */
void rb_set_errinfo(VALUE err);

// To advertise we have rb_errinfo to extensions
#define HAVE_RB_ERRINFO 1

/** Remove a previously declared global variable. */
void rb_free_global(VALUE global_handle);

Expand All @@ -978,25 +997,14 @@ double rb_num2dbl(VALUE);

/**
* Call method on receiver, args as varargs. Calls private methods.
*
* @todo Requires C99, change later for production code if needed.
* Pretty much all C++ compilers support this too. It can be
* done by introducing an intermediary function to grab the
* debug info, but it is far uglier. --rue
*
* See http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html
* regarding use of ##__VA_ARGS__.
*/
#define rb_funcall(receiver, method_name, arg_count, ...) \
capi_rb_funcall(__FILE__, __LINE__, \
(receiver), (method_name), \
(arg_count) , ##__VA_ARGS__)
VALUE rb_funcall(VALUE receiver, ID method_name,
int arg_count, ...);


/** Call the method with args provided in a C array. Calls private methods. */
#define rb_funcall2(receiver, method_name, arg_count, args) \
capi_rb_funcall2(__FILE__, __LINE__, \
(receiver), (method_name), \
(arg_count), (args) )
VALUE rb_funcall2(VALUE receiver, ID method_name,
int arg_count, const VALUE* args);

/** @todo define rb_funcall3, which is the same as rb_funcall2 but
* will not call private methods.
Expand All @@ -1012,6 +1020,10 @@ double rb_num2dbl(VALUE);
/** Return the value associated with the key, excluding default values. */
VALUE rb_hash_lookup(VALUE self, VALUE key);

// There is code that uses RHASH_TBL to detect if rb_hash_lookup
// is available. I know, silly.
#define RHASH_TBL 1

/** Set the value associated with the key. */
VALUE rb_hash_aset(VALUE self, VALUE key, VALUE value);

Expand All @@ -1035,8 +1047,13 @@ double rb_num2dbl(VALUE);
VALUE rb_io_write(VALUE io, VALUE str);

int rb_io_fd(VALUE io);
#define HAVE_RB_IO_FD 1

void rb_io_wait_readable(int fd);
void rb_io_wait_writable(int fd);

void rb_io_set_nonblock(rb_io_t *dummy);

void rb_thread_wait_fd(int fd);

/** convert a native int to Fixnum */
Expand Down Expand Up @@ -1124,6 +1141,8 @@ double rb_num2dbl(VALUE);
/** Call #to_s on object. */
VALUE rb_obj_as_string(VALUE obj_handle);

VALUE rb_obj_instance_eval(int argc, VALUE* argv, VALUE self);

VALUE rb_any_to_s(VALUE obj);

/** Return a clone of the object by calling the method bound
Expand Down
4 changes: 4 additions & 0 deletions vm/thread_state.hpp
Expand Up @@ -25,6 +25,10 @@ namespace rubinius {
return current_exception_.get();
}

void set_current_exception(Exception* exc) {
current_exception_.set((Object*)exc);
}

Object* raise_value() {
return raise_value_.get();
}
Expand Down

0 comments on commit 71cf2a5

Please sign in to comment.