diff --git a/ext/ffi_c/StructByReference.c b/ext/ffi_c/StructByReference.c deleted file mode 100644 index a27eff0a0..000000000 --- a/ext/ffi_c/StructByReference.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2010, Wayne Meissner - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * The name of the author or authors may not be used to endorse or promote - * products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _MSC_VER -# include -#endif -#include -#include -#ifndef _MSC_VER -# include -# include -#else -# include "win32/stdbool.h" -# include "win32/stdint.h" -#endif -#include -#include - -#include -#include "rbffi.h" -#include "compat.h" - -#include "Pointer.h" -#include "Struct.h" -#include "StructByReference.h" - - -#define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) - -static VALUE sbr_allocate(VALUE); -static VALUE sbr_initialize(VALUE, VALUE); -static void sbr_mark(StructByReference *); - -VALUE rbffi_StructByReferenceClass = Qnil; - -static VALUE -sbr_allocate(VALUE klass) -{ - StructByReference* sbr; - - VALUE obj = Data_Make_Struct(klass, StructByReference, sbr_mark, -1, sbr); - - sbr->rbStructClass = Qnil; - - return obj; -} - -/* - * call-seq: initialize(struc_class) - * @param [Struct] struct_calss - * @return [self] - * A new instance of StructByReference. - */ -static VALUE -sbr_initialize(VALUE self, VALUE rbStructClass) -{ - StructByReference* sbr = NULL; - - if (!rb_class_inherited_p(rbStructClass, rbffi_StructClass)) { - rb_raise(rb_eTypeError, "wrong type (expected subclass of FFI::Struct)"); - } - - Data_Get_Struct(self, StructByReference, sbr); - sbr->rbStructClass = rbStructClass; - - return self; -} - -static void -sbr_mark(StructByReference *sbr) -{ - rb_gc_mark(sbr->rbStructClass); -} - - -/* - * call-seq: struct_class - * @return [Struct] - * Get +struct_class+. - */ -static VALUE -sbr_struct_class(VALUE self) -{ - StructByReference* sbr; - - Data_Get_Struct(self, StructByReference, sbr); - - return sbr->rbStructClass; -} - -/* - * call-seq: native_type - * @return [Class] - * Always get {FFI::Type}::POINTER. - */ -static VALUE -sbr_native_type(VALUE self) -{ - return rb_const_get(rbffi_TypeClass, rb_intern("POINTER")); -} - -/* - * call-seq: to_native(value, ctx) - * @param [nil, Struct] value - * @param [nil] ctx - * @return [AbstractMemory] Pointer on +value+. - */ -static VALUE -sbr_to_native(VALUE self, VALUE value, VALUE ctx) -{ - StructByReference* sbr; - Struct* s; - - if (unlikely(value == Qnil)) { - return rbffi_NullPointerSingleton; - } - - Data_Get_Struct(self, StructByReference, sbr); - if (!rb_obj_is_kind_of(value, sbr->rbStructClass)) { - rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", - rb_obj_classname(value), - RSTRING_PTR(rb_class_name(sbr->rbStructClass))); - } - - Data_Get_Struct(value, Struct, s); - - return s->rbPointer; -} - -/* - * call-seq: from_native(value, ctx) - * @param [AbstractMemory] value - * @param [nil] ctx - * @return [Struct] - * Create a struct from content of memory +value+. - */ -static VALUE -sbr_from_native(VALUE self, VALUE value, VALUE ctx) -{ - StructByReference* sbr; - - Data_Get_Struct(self, StructByReference, sbr); - - return rb_class_new_instance(1, &value, sbr->rbStructClass); -} - - -void -rbffi_StructByReference_Init(VALUE moduleFFI) -{ - rbffi_StructByReferenceClass = rb_define_class_under(moduleFFI, "StructByReference", rb_cObject); - rb_global_variable(&rbffi_StructByReferenceClass); - - rb_define_alloc_func(rbffi_StructByReferenceClass, sbr_allocate); - rb_define_method(rbffi_StructByReferenceClass, "initialize", sbr_initialize, 1); - rb_define_method(rbffi_StructByReferenceClass, "struct_class", sbr_struct_class, 0); - rb_define_method(rbffi_StructByReferenceClass, "native_type", sbr_native_type, 0); - rb_define_method(rbffi_StructByReferenceClass, "to_native", sbr_to_native, 2); - rb_define_method(rbffi_StructByReferenceClass, "from_native", sbr_from_native, 2); -} diff --git a/ext/ffi_c/StructByReference.h b/ext/ffi_c/StructByReference.h deleted file mode 100644 index cf797af62..000000000 --- a/ext/ffi_c/StructByReference.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2009, Wayne Meissner - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * * The name of the author or authors may not be used to endorse or promote - * products derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef RBFFI_STRUCTBYREFERENCE_H -#define RBFFI_STRUCTBYREFERENCE_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct StructByReference_ { - VALUE rbStructClass; -} StructByReference; - -void rbffi_StructByReference_Init(VALUE moduleFFI); - -extern VALUE rbffi_StructByReferenceClass; - -#ifdef __cplusplus -} -#endif - -#endif /* RBFFI_STRUCTBYREFERENCE_H */ - diff --git a/ext/ffi_c/ffi.c b/ext/ffi_c/ffi.c index fc0b766d0..22ea3bf7b 100644 --- a/ext/ffi_c/ffi.c +++ b/ext/ffi_c/ffi.c @@ -40,7 +40,6 @@ #include "MemoryPointer.h" #include "Struct.h" #include "StructByValue.h" -#include "StructByReference.h" #include "DynamicLibrary.h" #include "Platform.h" #include "Types.h" @@ -59,9 +58,9 @@ VALUE rbffi_FFIModule = Qnil; static VALUE moduleFFI = Qnil; void -Init_ffi_c(void) +Init_ffi_c(void) { - /* + /* * Document-module: FFI * * This module embbed type constants from {FFI::NativeType}. @@ -70,7 +69,7 @@ Init_ffi_c(void) rb_global_variable(&rbffi_FFIModule); rbffi_Thread_Init(rbffi_FFIModule); - + /* FFI::Type needs to be initialized before most other classes */ rbffi_Type_Init(moduleFFI); @@ -86,7 +85,6 @@ Init_ffi_c(void) rbffi_MemoryPointer_Init(moduleFFI); rbffi_Buffer_Init(moduleFFI); rbffi_StructByValue_Init(moduleFFI); - rbffi_StructByReference_Init(moduleFFI); rbffi_Struct_Init(moduleFFI); rbffi_DynamicLibrary_Init(moduleFFI); rbffi_Variadic_Init(moduleFFI); diff --git a/lib/ffi/struct.rb b/lib/ffi/struct.rb index 1f2adfdd8..126d437ce 100644 --- a/lib/ffi/struct.rb +++ b/lib/ffi/struct.rb @@ -32,72 +32,12 @@ # require 'ffi/platform' +require 'ffi/struct_layout' require 'ffi/struct_layout_builder' +require 'ffi/struct_by_reference' module FFI - class StructLayout - - # @return [Array - # Get an array of tuples (field name, offset of the field). - def offsets - members.map { |m| [ m, self[m].offset ] } - end - - # @return [Numeric] - # Get the offset of a field. - def offset_of(field_name) - self[field_name].offset - end - - # An enum {Field} in a {StructLayout}. - class Enum < Field - - # @param [AbstractMemory] ptr pointer on a {Struct} - # @return [Object] - # Get an object of type {#type} from memory pointed by +ptr+. - def get(ptr) - type.find(ptr.get_int(offset)) - end - - # @param [AbstractMemory] ptr pointer on a {Struct} - # @param value - # @return [nil] - # Set +value+ into memory pointed by +ptr+. - def put(ptr, value) - ptr.put_int(offset, type.find(value)) - end - - end - - class InnerStruct < Field - def get(ptr) - type.struct_class.new(ptr.slice(self.offset, self.size)) - end - - def put(ptr, value) - raise TypeError, "wrong value type (expected #{type.struct_class})" unless value.is_a?(type.struct_class) - ptr.slice(self.offset, self.size).__copy_from__(value.pointer, self.size) - end - end - - class Mapped < Field - def initialize(name, offset, type, orig_field) - super(name, offset, type) - @orig_field = orig_field - end - - def get(ptr) - type.from_native(@orig_field.get(ptr), nil) - end - - def put(ptr, value) - @orig_field.put(ptr, type.to_native(value, nil)) - end - end - end - - class Struct # Get struct size @@ -296,7 +236,7 @@ def packed(packed = 1) @packed = packed end alias :pack :packed - + def aligned(alignment = 1) @min_alignment = alignment end @@ -368,9 +308,4 @@ def array_layout(builder, spec) end end end - - # This class includes the {FFI::DataConverter} module. - class StructByReference - include DataConverter - end end diff --git a/lib/ffi/struct_by_reference.rb b/lib/ffi/struct_by_reference.rb new file mode 100644 index 000000000..27f25eca7 --- /dev/null +++ b/lib/ffi/struct_by_reference.rb @@ -0,0 +1,72 @@ +# +# Copyright (C) 2010 Wayne Meissner +# +# This file is part of ruby-ffi. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the Ruby FFI project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.# + +module FFI + # This class includes the {FFI::DataConverter} module. + class StructByReference + include DataConverter + + attr_reader :struct_class + + # @param [Struct] struct_class + def initialize(struct_class) + unless Class === struct_class and struct_class < FFI::Struct + raise TypeError, 'wrong type (expected subclass of FFI::Struct)' + end + @struct_class = struct_class + end + + # Always get {FFI::Type}::POINTER. + def native_type + FFI::Type::POINTER + end + + # @param [nil, Struct] value + # @param [nil] ctx + # @return [AbstractMemory] Pointer on +value+. + def to_native(value, ctx) + return Pointer::NULL if value.nil? + + unless @struct_class === value + raise TypeError, "wrong argument type #{value.class} (expected #{@struct_class})" + end + + value.pointer + end + + # @param [AbstractMemory] value + # @param [nil] ctx + # @return [Struct] + # Create a struct from content of memory +value+. + def from_native(value, ctx) + @struct_class.new(value) + end + end +end diff --git a/lib/ffi/struct_layout.rb b/lib/ffi/struct_layout.rb new file mode 100644 index 000000000..d5a78a7a7 --- /dev/null +++ b/lib/ffi/struct_layout.rb @@ -0,0 +1,96 @@ +# +# Copyright (C) 2008-2010 Wayne Meissner +# Copyright (C) 2008, 2009 Andrea Fazzi +# Copyright (C) 2008, 2009 Luc Heinrich +# +# This file is part of ruby-ffi. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the Ruby FFI project nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +module FFI + + class StructLayout + + # @return [Array + # Get an array of tuples (field name, offset of the field). + def offsets + members.map { |m| [ m, self[m].offset ] } + end + + # @return [Numeric] + # Get the offset of a field. + def offset_of(field_name) + self[field_name].offset + end + + # An enum {Field} in a {StructLayout}. + class Enum < Field + + # @param [AbstractMemory] ptr pointer on a {Struct} + # @return [Object] + # Get an object of type {#type} from memory pointed by +ptr+. + def get(ptr) + type.find(ptr.get_int(offset)) + end + + # @param [AbstractMemory] ptr pointer on a {Struct} + # @param value + # @return [nil] + # Set +value+ into memory pointed by +ptr+. + def put(ptr, value) + ptr.put_int(offset, type.find(value)) + end + + end + + class InnerStruct < Field + def get(ptr) + type.struct_class.new(ptr.slice(self.offset, self.size)) + end + + def put(ptr, value) + raise TypeError, "wrong value type (expected #{type.struct_class})" unless value.is_a?(type.struct_class) + ptr.slice(self.offset, self.size).__copy_from__(value.pointer, self.size) + end + end + + class Mapped < Field + def initialize(name, offset, type, orig_field) + super(name, offset, type) + @orig_field = orig_field + end + + def get(ptr) + type.from_native(@orig_field.get(ptr), nil) + end + + def put(ptr, value) + @orig_field.put(ptr, type.to_native(value, nil)) + end + end + end +end