summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ext/dl/cptr.c32
-rw-r--r--test/dl/test_cptr.rb36
2 files changed, 61 insertions, 7 deletions
diff --git a/ext/dl/cptr.c b/ext/dl/cptr.c
index 94632e824..cdcc23c72 100644
--- a/ext/dl/cptr.c
+++ b/ext/dl/cptr.c
@@ -254,7 +254,12 @@ rb_dlptr_null_p(VALUE self)
return data->ptr ? Qfalse : Qtrue;
}
-VALUE
+/*
+ * call-seq: free=(function)
+ *
+ * Set the free function for this pointer to the DL::CFunc in +function+.
+ */
+static VALUE
rb_dlptr_free_set(VALUE self, VALUE val)
{
struct ptr_data *data;
@@ -265,7 +270,12 @@ rb_dlptr_free_set(VALUE self, VALUE val)
return Qnil;
}
-VALUE
+/*
+ * call-seq: free
+ *
+ * Get the free function for this pointer. Returns DL::CFunc or nil.
+ */
+static VALUE
rb_dlptr_free_get(VALUE self)
{
struct ptr_data *pdata;
@@ -499,21 +509,29 @@ rb_dlptr_size_get(VALUE self)
return LONG2NUM(RPTR_DATA(self)->size);
}
-VALUE
+/*
+ * call-seq:
+ * DL::CPtr.to_ptr(val) => cptr
+ * DL::CPtr[val] => cptr
+ *
+ * Get the underlying pointer for ruby object +val+ and return it as a
+ * DL::CPtr object.
+ */
+static VALUE
rb_dlptr_s_to_ptr(VALUE self, VALUE val)
{
VALUE ptr;
- if (rb_obj_is_kind_of(val, rb_cIO) == Qtrue){
+ if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
rb_io_t *fptr;
FILE *fp;
GetOpenFile(val, fptr);
fp = rb_io_stdio_file(fptr);
ptr = rb_dlptr_new(fp, 0, NULL);
}
- else if (rb_obj_is_kind_of(val, rb_cString) == Qtrue){
- char *str = StringValuePtr(val);
- ptr = rb_dlptr_new(str, RSTRING_LEN(val), NULL);
+ else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
+ char *str = StringValuePtr(val);
+ ptr = rb_dlptr_new(str, RSTRING_LEN(val), NULL);
}
else if (rb_respond_to(val, id_to_ptr)){
VALUE vptr = rb_funcall(val, id_to_ptr, 0);
diff --git a/test/dl/test_cptr.rb b/test/dl/test_cptr.rb
index c03abbe73..3c4b5e686 100644
--- a/test/dl/test_cptr.rb
+++ b/test/dl/test_cptr.rb
@@ -3,6 +3,42 @@ require_relative '../ruby/envutil'
module DL
class TestCPtr < TestBase
+ def test_to_ptr_string
+ str = "hello world"
+ ptr = CPtr[str]
+ assert ptr.tainted?, 'pointer should be tainted'
+ assert_equal str.length, ptr.size
+ assert_equal 'hello', ptr[0,5]
+ end
+
+ def test_to_ptr_io
+ buf = CPtr.malloc(10)
+ File.open(__FILE__, 'r') do |f|
+ ptr = CPtr.to_ptr f
+ fread = CFunc.new(@libc['fread'], TYPE_VOID, 'fread')
+ fread.call([buf.to_i, DL::SIZEOF_CHAR, buf.size - 1, ptr.to_i])
+ end
+
+ File.open(__FILE__, 'r') do |f|
+ assert_equal f.read(9), buf.to_s
+ end
+ end
+
+ def test_to_ptr_with_ptr
+ ptr = CPtr.new 0
+ ptr2 = CPtr.to_ptr Struct.new(:to_ptr).new(ptr)
+ assert_equal ptr, ptr2
+
+ assert_raises(DL::DLError) do
+ CPtr.to_ptr Struct.new(:to_ptr).new(nil)
+ end
+ end
+
+ def test_to_ptr_with_num
+ ptr = CPtr.new 0
+ assert_equal ptr, CPtr[0]
+ end
+
def test_equals
ptr = CPtr.new 0
ptr2 = CPtr.new 0