ffi 0.5.0-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/LICENSE +51 -0
- data/README.rdoc +69 -0
- data/Rakefile +191 -0
- data/ext/ffi_c/AbstractMemory.c +489 -0
- data/ext/ffi_c/AbstractMemory.h +160 -0
- data/ext/ffi_c/ArrayType.c +129 -0
- data/ext/ffi_c/ArrayType.h +58 -0
- data/ext/ffi_c/AutoPointer.c +61 -0
- data/ext/ffi_c/AutoPointer.h +18 -0
- data/ext/ffi_c/Buffer.c +187 -0
- data/ext/ffi_c/Call.c +853 -0
- data/ext/ffi_c/Call.h +86 -0
- data/ext/ffi_c/ClosurePool.c +302 -0
- data/ext/ffi_c/ClosurePool.h +29 -0
- data/ext/ffi_c/DynamicLibrary.c +216 -0
- data/ext/ffi_c/DynamicLibrary.h +22 -0
- data/ext/ffi_c/Function.c +478 -0
- data/ext/ffi_c/Function.h +80 -0
- data/ext/ffi_c/FunctionInfo.c +221 -0
- data/ext/ffi_c/LastError.c +159 -0
- data/ext/ffi_c/LastError.h +18 -0
- data/ext/ffi_c/MemoryPointer.c +178 -0
- data/ext/ffi_c/MemoryPointer.h +20 -0
- data/ext/ffi_c/MethodHandle.c +346 -0
- data/ext/ffi_c/MethodHandle.h +53 -0
- data/ext/ffi_c/Platform.c +59 -0
- data/ext/ffi_c/Platform.h +16 -0
- data/ext/ffi_c/Pointer.c +224 -0
- data/ext/ffi_c/Pointer.h +49 -0
- data/ext/ffi_c/Struct.c +770 -0
- data/ext/ffi_c/Struct.h +80 -0
- data/ext/ffi_c/StructByValue.c +140 -0
- data/ext/ffi_c/StructByValue.h +53 -0
- data/ext/ffi_c/StructLayout.c +450 -0
- data/ext/ffi_c/Type.c +329 -0
- data/ext/ffi_c/Type.h +57 -0
- data/ext/ffi_c/Types.c +103 -0
- data/ext/ffi_c/Types.h +85 -0
- data/ext/ffi_c/Variadic.c +260 -0
- data/ext/ffi_c/compat.h +72 -0
- data/ext/ffi_c/endian.h +40 -0
- data/ext/ffi_c/extconf.rb +30 -0
- data/ext/ffi_c/ffi.c +82 -0
- data/ext/ffi_c/libffi.bsd.mk +34 -0
- data/ext/ffi_c/libffi.darwin.mk +75 -0
- data/ext/ffi_c/libffi.gnu.mk +29 -0
- data/ext/ffi_c/libffi.mk +13 -0
- data/ext/ffi_c/libffi/ChangeLog +3243 -0
- data/ext/ffi_c/libffi/ChangeLog.libffi +347 -0
- data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
- data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
- data/ext/ffi_c/libffi/LICENSE +21 -0
- data/ext/ffi_c/libffi/Makefile.am +177 -0
- data/ext/ffi_c/libffi/Makefile.in +1640 -0
- data/ext/ffi_c/libffi/README +328 -0
- data/ext/ffi_c/libffi/TODO +1 -0
- data/ext/ffi_c/libffi/acinclude.m4 +92 -0
- data/ext/ffi_c/libffi/aclocal.m4 +7516 -0
- data/ext/ffi_c/libffi/compile +142 -0
- data/ext/ffi_c/libffi/config.guess +1516 -0
- data/ext/ffi_c/libffi/config.sub +1626 -0
- data/ext/ffi_c/libffi/configure +24414 -0
- data/ext/ffi_c/libffi/configure.ac +365 -0
- data/ext/ffi_c/libffi/configure.host +11 -0
- data/ext/ffi_c/libffi/depcomp +584 -0
- data/ext/ffi_c/libffi/doc/libffi.info +533 -0
- data/ext/ffi_c/libffi/doc/libffi.texi +541 -0
- data/ext/ffi_c/libffi/doc/stamp-vti +4 -0
- data/ext/ffi_c/libffi/doc/version.texi +4 -0
- data/ext/ffi_c/libffi/fficonfig.h.in +160 -0
- data/ext/ffi_c/libffi/include/Makefile.am +9 -0
- data/ext/ffi_c/libffi/include/Makefile.in +422 -0
- data/ext/ffi_c/libffi/include/ffi.h.in +393 -0
- data/ext/ffi_c/libffi/include/ffi_common.h +98 -0
- data/ext/ffi_c/libffi/install-sh +323 -0
- data/ext/ffi_c/libffi/libffi.pc.in +10 -0
- data/ext/ffi_c/libffi/libtool-version +29 -0
- data/ext/ffi_c/libffi/ltcf-c.sh +861 -0
- data/ext/ffi_c/libffi/ltcf-cxx.sh +1069 -0
- data/ext/ffi_c/libffi/ltcf-gcj.sh +700 -0
- data/ext/ffi_c/libffi/ltconfig +2862 -0
- data/ext/ffi_c/libffi/ltmain.sh +6930 -0
- data/ext/ffi_c/libffi/man/Makefile.am +8 -0
- data/ext/ffi_c/libffi/man/Makefile.in +395 -0
- data/ext/ffi_c/libffi/man/ffi.3 +31 -0
- data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
- data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +66 -0
- data/ext/ffi_c/libffi/mdate-sh +201 -0
- data/ext/ffi_c/libffi/missing +353 -0
- data/ext/ffi_c/libffi/mkinstalldirs +158 -0
- data/ext/ffi_c/libffi/src/alpha/ffi.c +284 -0
- data/ext/ffi_c/libffi/src/alpha/ffitarget.h +48 -0
- data/ext/ffi_c/libffi/src/alpha/osf.S +366 -0
- data/ext/ffi_c/libffi/src/arm/ffi.c +309 -0
- data/ext/ffi_c/libffi/src/arm/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/arm/sysv.S +299 -0
- data/ext/ffi_c/libffi/src/closures.c +596 -0
- data/ext/ffi_c/libffi/src/cris/ffi.c +383 -0
- data/ext/ffi_c/libffi/src/cris/ffitarget.h +51 -0
- data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
- data/ext/ffi_c/libffi/src/debug.c +59 -0
- data/ext/ffi_c/libffi/src/dlmalloc.c +5099 -0
- data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
- data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
- data/ext/ffi_c/libffi/src/frv/ffitarget.h +61 -0
- data/ext/ffi_c/libffi/src/ia64/ffi.c +580 -0
- data/ext/ffi_c/libffi/src/ia64/ffitarget.h +50 -0
- data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
- data/ext/ffi_c/libffi/src/ia64/unix.S +560 -0
- data/ext/ffi_c/libffi/src/java_raw_api.c +359 -0
- data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
- data/ext/ffi_c/libffi/src/m32r/ffitarget.h +48 -0
- data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
- data/ext/ffi_c/libffi/src/m68k/ffi.c +278 -0
- data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/m68k/sysv.S +234 -0
- data/ext/ffi_c/libffi/src/mips/ffi.c +926 -0
- data/ext/ffi_c/libffi/src/mips/ffitarget.h +202 -0
- data/ext/ffi_c/libffi/src/mips/n32.S +534 -0
- data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
- data/ext/ffi_c/libffi/src/pa/ffi.c +709 -0
- data/ext/ffi_c/libffi/src/pa/ffitarget.h +77 -0
- data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
- data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
- data/ext/ffi_c/libffi/src/powerpc/aix.S +225 -0
- data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +247 -0
- data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
- data/ext/ffi_c/libffi/src/powerpc/darwin.S +245 -0
- data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +317 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi.c +1429 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +800 -0
- data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +118 -0
- data/ext/ffi_c/libffi/src/powerpc/linux64.S +187 -0
- data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +236 -0
- data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +327 -0
- data/ext/ffi_c/libffi/src/powerpc/sysv.S +230 -0
- data/ext/ffi_c/libffi/src/prep_cif.c +174 -0
- data/ext/ffi_c/libffi/src/raw_api.c +254 -0
- data/ext/ffi_c/libffi/src/s390/ffi.c +780 -0
- data/ext/ffi_c/libffi/src/s390/ffitarget.h +60 -0
- data/ext/ffi_c/libffi/src/s390/sysv.S +434 -0
- data/ext/ffi_c/libffi/src/sh/ffi.c +716 -0
- data/ext/ffi_c/libffi/src/sh/ffitarget.h +49 -0
- data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
- data/ext/ffi_c/libffi/src/sh64/ffi.c +453 -0
- data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
- data/ext/ffi_c/libffi/src/sh64/sysv.S +530 -0
- data/ext/ffi_c/libffi/src/sparc/ffi.c +610 -0
- data/ext/ffi_c/libffi/src/sparc/ffitarget.h +66 -0
- data/ext/ffi_c/libffi/src/sparc/v8.S +272 -0
- data/ext/ffi_c/libffi/src/sparc/v9.S +307 -0
- data/ext/ffi_c/libffi/src/types.c +77 -0
- data/ext/ffi_c/libffi/src/x86/darwin.S +443 -0
- data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
- data/ext/ffi_c/libffi/src/x86/ffi.c +475 -0
- data/ext/ffi_c/libffi/src/x86/ffi64.c +572 -0
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +90 -0
- data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
- data/ext/ffi_c/libffi/src/x86/sysv.S +437 -0
- data/ext/ffi_c/libffi/src/x86/unix64.S +418 -0
- data/ext/ffi_c/libffi/src/x86/win32.S +391 -0
- data/ext/ffi_c/libffi/testsuite/Makefile.am +71 -0
- data/ext/ffi_c/libffi/testsuite/Makefile.in +447 -0
- data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
- data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +289 -0
- data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +263 -0
- data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +89 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +89 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +90 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +72 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +102 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +103 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +104 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +110 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +97 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +101 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +121 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +103 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +106 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +117 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +106 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +132 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +121 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +107 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +125 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +105 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +96 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +101 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +100 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +101 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +100 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +94 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +99 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +82 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +94 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +52 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +54 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +51 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +86 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +58 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +57 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +72 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +69 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +63 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +53 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +160 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +169 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +141 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +118 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +119 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +119 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +120 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +139 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +119 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +139 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +139 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +98 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +35 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +42 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +65 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +59 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +63 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +65 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +80 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +67 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +86 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +38 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +123 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
- data/ext/ffi_c/libffi/texinfo.tex +7482 -0
- data/ext/ffi_c/rbffi.h +26 -0
- data/gen/Rakefile +12 -0
- data/lib/1.8/ffi_c.so +0 -0
- data/lib/1.9/ffi_c.so +0 -0
- data/lib/ffi.rb +11 -0
- data/lib/ffi/autopointer.rb +61 -0
- data/lib/ffi/buffer.rb +0 -0
- data/lib/ffi/callback.rb +10 -0
- data/lib/ffi/enum.rb +78 -0
- data/lib/ffi/errno.rb +8 -0
- data/lib/ffi/ffi.rb +99 -0
- data/lib/ffi/io.rb +21 -0
- data/lib/ffi/library.rb +218 -0
- data/lib/ffi/managedstruct.rb +55 -0
- data/lib/ffi/memorypointer.rb +73 -0
- data/lib/ffi/platform.rb +88 -0
- data/lib/ffi/pointer.rb +119 -0
- data/lib/ffi/struct.rb +183 -0
- data/lib/ffi/tools/const_generator.rb +177 -0
- data/lib/ffi/tools/generator.rb +58 -0
- data/lib/ffi/tools/generator_task.rb +35 -0
- data/lib/ffi/tools/struct_generator.rb +194 -0
- data/lib/ffi/tools/types_generator.rb +123 -0
- data/lib/ffi/types.rb +153 -0
- data/lib/ffi/union.rb +12 -0
- data/lib/ffi/variadic.rb +25 -0
- data/spec/ffi/bool_spec.rb +24 -0
- data/spec/ffi/buffer_spec.rb +202 -0
- data/spec/ffi/callback_spec.rb +591 -0
- data/spec/ffi/enum_spec.rb +164 -0
- data/spec/ffi/errno_spec.rb +13 -0
- data/spec/ffi/function_spec.rb +73 -0
- data/spec/ffi/library_spec.rb +148 -0
- data/spec/ffi/managed_struct_spec.rb +56 -0
- data/spec/ffi/number_spec.rb +231 -0
- data/spec/ffi/pointer_spec.rb +195 -0
- data/spec/ffi/rbx/attach_function_spec.rb +27 -0
- data/spec/ffi/rbx/memory_pointer_spec.rb +102 -0
- data/spec/ffi/rbx/spec_helper.rb +1 -0
- data/spec/ffi/rbx/struct_spec.rb +13 -0
- data/spec/ffi/spec_helper.rb +17 -0
- data/spec/ffi/string_spec.rb +103 -0
- data/spec/ffi/struct_callback_spec.rb +64 -0
- data/spec/ffi/struct_initialize_spec.rb +30 -0
- data/spec/ffi/struct_spec.rb +529 -0
- data/spec/ffi/typedef_spec.rb +48 -0
- data/spec/ffi/union_spec.rb +60 -0
- data/spec/ffi/variadic_spec.rb +84 -0
- data/spec/spec.opts +4 -0
- metadata +396 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2009, Wayne Meissner
|
3
|
+
* All rights reserved.
|
4
|
+
*
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
7
|
+
*
|
8
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
9
|
+
* list of conditions and the following disclaimer.
|
10
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
11
|
+
* this list of conditions and the following disclaimer in the documentation
|
12
|
+
* and/or other materials provided with the distribution.
|
13
|
+
* * The name of the author or authors may not be used to endorse or promote
|
14
|
+
* products derived from this software without specific prior written permission.
|
15
|
+
*
|
16
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
17
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
20
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
21
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
22
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
23
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
24
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
25
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
#ifndef _METHODHANDLE_H
|
29
|
+
#define _METHODHANDLE_H
|
30
|
+
|
31
|
+
#ifdef __cplusplus
|
32
|
+
extern "C" {
|
33
|
+
#endif
|
34
|
+
|
35
|
+
#include <ruby.h>
|
36
|
+
#include "Function.h"
|
37
|
+
|
38
|
+
|
39
|
+
typedef struct MethodHandlePool MethodHandlePool;
|
40
|
+
typedef struct MethodHandle MethodHandle;
|
41
|
+
|
42
|
+
|
43
|
+
MethodHandle* rbffi_MethodHandle_Alloc(FunctionType* fnInfo, void* function);
|
44
|
+
void rbffi_MethodHandle_Free(MethodHandle* handle);
|
45
|
+
void* rbffi_MethodHandle_CodeAddress(MethodHandle* handle);
|
46
|
+
void rbffi_MethodHandle_Init(VALUE module);
|
47
|
+
|
48
|
+
#ifdef __cplusplus
|
49
|
+
}
|
50
|
+
#endif
|
51
|
+
|
52
|
+
#endif /* _METHODHANDLE_H */
|
53
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#include <sys/param.h>
|
2
|
+
#include <sys/types.h>
|
3
|
+
#include <stdint.h>
|
4
|
+
#include <stdbool.h>
|
5
|
+
#include <ruby.h>
|
6
|
+
#include <ctype.h>
|
7
|
+
#include "endian.h"
|
8
|
+
#include "Platform.h"
|
9
|
+
|
10
|
+
static VALUE PlatformModule = Qnil;
|
11
|
+
|
12
|
+
/*
|
13
|
+
* Determine the cpu type at compile time - useful for MacOSX where the the
|
14
|
+
* system installed ruby incorrectly reports 'host_cpu' as 'powerpc' when running
|
15
|
+
* on intel.
|
16
|
+
*/
|
17
|
+
#ifdef __i386__
|
18
|
+
#define CPU "i386"
|
19
|
+
#elif defined(__ppc__) || defined(__powerpc__)
|
20
|
+
#define CPU "powerpc"
|
21
|
+
#elif defined(__x86_64__)
|
22
|
+
#define CPU "x86_64"
|
23
|
+
#elif defined(__sparc__)
|
24
|
+
#define CPU "sparc"
|
25
|
+
#elif defined(__sparcv9__)
|
26
|
+
#define CPU "sparcv9"
|
27
|
+
#else
|
28
|
+
#error "Unknown cpu type"
|
29
|
+
#endif
|
30
|
+
|
31
|
+
static void
|
32
|
+
export_primitive_types(VALUE module)
|
33
|
+
{
|
34
|
+
#define S(name, T) do { \
|
35
|
+
typedef struct { char c; T v; } s; \
|
36
|
+
rb_define_const(module, #name "_ALIGN", INT2NUM((sizeof(s) - sizeof(T)) * 8)); \
|
37
|
+
rb_define_const(module, #name "_SIZE", INT2NUM(sizeof(T)* 8)); \
|
38
|
+
} while(0)
|
39
|
+
S(INT8, char);
|
40
|
+
S(INT16, short);
|
41
|
+
S(INT32, int);
|
42
|
+
S(INT64, long long);
|
43
|
+
S(LONG, long);
|
44
|
+
S(FLOAT, float);
|
45
|
+
S(DOUBLE, double);
|
46
|
+
S(ADDRESS, void*);
|
47
|
+
#undef S
|
48
|
+
}
|
49
|
+
|
50
|
+
void
|
51
|
+
rbffi_Platform_Init(VALUE moduleFFI)
|
52
|
+
{
|
53
|
+
PlatformModule = rb_define_module_under(moduleFFI, "Platform");
|
54
|
+
rb_define_const(PlatformModule, "BYTE_ORDER", INT2FIX(BYTE_ORDER));
|
55
|
+
rb_define_const(PlatformModule, "LITTLE_ENDIAN", INT2FIX(LITTLE_ENDIAN));
|
56
|
+
rb_define_const(PlatformModule, "BIG_ENDIAN", INT2FIX(BIG_ENDIAN));
|
57
|
+
rb_define_const(PlatformModule, "CPU", rb_str_new2(CPU));
|
58
|
+
export_primitive_types(PlatformModule);
|
59
|
+
}
|
data/ext/ffi_c/Pointer.c
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2008, 2009, Wayne Meissner
|
3
|
+
*
|
4
|
+
* All rights reserved.
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions are met:
|
8
|
+
*
|
9
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
10
|
+
* list of conditions and the following disclaimer.
|
11
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
13
|
+
* and/or other materials provided with the distribution.
|
14
|
+
* * The name of the author or authors may not be used to endorse or promote
|
15
|
+
* products derived from this software without specific prior written permission.
|
16
|
+
*
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
*/
|
28
|
+
|
29
|
+
#include <stdbool.h>
|
30
|
+
#include <stdint.h>
|
31
|
+
#include <limits.h>
|
32
|
+
#include <ruby.h>
|
33
|
+
#include "rbffi.h"
|
34
|
+
#include "AbstractMemory.h"
|
35
|
+
#include "Pointer.h"
|
36
|
+
|
37
|
+
typedef struct Pointer {
|
38
|
+
AbstractMemory memory;
|
39
|
+
VALUE parent;
|
40
|
+
} Pointer;
|
41
|
+
|
42
|
+
#define POINTER(obj) rbffi_AbstractMemory_Cast((obj), rbffi_PointerClass)
|
43
|
+
|
44
|
+
VALUE rbffi_PointerClass = Qnil;
|
45
|
+
VALUE rbffi_NullPointerSingleton = Qnil;
|
46
|
+
|
47
|
+
static void ptr_mark(Pointer* ptr);
|
48
|
+
|
49
|
+
VALUE
|
50
|
+
rbffi_Pointer_NewInstance(void* addr)
|
51
|
+
{
|
52
|
+
Pointer* p;
|
53
|
+
VALUE obj;
|
54
|
+
|
55
|
+
if (addr == NULL) {
|
56
|
+
return rbffi_NullPointerSingleton;
|
57
|
+
}
|
58
|
+
|
59
|
+
obj = Data_Make_Struct(rbffi_PointerClass, Pointer, NULL, -1, p);
|
60
|
+
p->memory.address = addr;
|
61
|
+
p->memory.size = LONG_MAX;
|
62
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
63
|
+
p->memory.access = (addr == NULL) ? 0 : (MEM_RD | MEM_WR);
|
64
|
+
p->memory.typeSize = 1;
|
65
|
+
p->parent = Qnil;
|
66
|
+
|
67
|
+
return obj;
|
68
|
+
}
|
69
|
+
|
70
|
+
static VALUE
|
71
|
+
ptr_allocate(VALUE klass)
|
72
|
+
{
|
73
|
+
Pointer* p;
|
74
|
+
VALUE obj;
|
75
|
+
|
76
|
+
obj = Data_Make_Struct(klass, Pointer, NULL, -1, p);
|
77
|
+
p->parent = Qnil;
|
78
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
79
|
+
p->memory.access = MEM_RD | MEM_WR;
|
80
|
+
|
81
|
+
return obj;
|
82
|
+
}
|
83
|
+
|
84
|
+
static VALUE
|
85
|
+
ptr_initialize(int argc, VALUE* argv, VALUE self)
|
86
|
+
{
|
87
|
+
Pointer* p;
|
88
|
+
VALUE rbType = Qnil, rbAddress = Qnil;
|
89
|
+
int typeSize = 1;
|
90
|
+
|
91
|
+
Data_Get_Struct(self, Pointer, p);
|
92
|
+
|
93
|
+
switch (rb_scan_args(argc, argv, "11", &rbType, &rbAddress)) {
|
94
|
+
case 1:
|
95
|
+
rbAddress = rbType;
|
96
|
+
typeSize = 1;
|
97
|
+
break;
|
98
|
+
case 2:
|
99
|
+
typeSize = rbffi_type_size(rbType);
|
100
|
+
break;
|
101
|
+
default:
|
102
|
+
rb_raise(rb_eArgError, "Invalid arguments");
|
103
|
+
}
|
104
|
+
|
105
|
+
switch (TYPE(rbAddress)) {
|
106
|
+
case T_FIXNUM:
|
107
|
+
case T_BIGNUM:
|
108
|
+
p->memory.address = (void*) (uintptr_t) NUM2LL(rbAddress);
|
109
|
+
p->memory.size = LONG_MAX;
|
110
|
+
if (p->memory.address == NULL) {
|
111
|
+
p->memory.access = 0;
|
112
|
+
}
|
113
|
+
break;
|
114
|
+
|
115
|
+
default:
|
116
|
+
if (rb_obj_is_kind_of(rbAddress, rbffi_PointerClass)) {
|
117
|
+
Pointer* orig;
|
118
|
+
|
119
|
+
p->parent = rbAddress;
|
120
|
+
Data_Get_Struct(rbAddress, Pointer, orig);
|
121
|
+
p->memory = orig->memory;
|
122
|
+
} else {
|
123
|
+
rb_raise(rb_eTypeError, "wrong argument type, expected Integer or FFI::Pointer");
|
124
|
+
}
|
125
|
+
break;
|
126
|
+
}
|
127
|
+
|
128
|
+
p->memory.typeSize = typeSize;
|
129
|
+
|
130
|
+
return self;
|
131
|
+
}
|
132
|
+
|
133
|
+
|
134
|
+
static VALUE
|
135
|
+
ptr_plus(VALUE self, VALUE offset)
|
136
|
+
{
|
137
|
+
AbstractMemory* ptr;
|
138
|
+
Pointer* p;
|
139
|
+
VALUE retval;
|
140
|
+
long off = NUM2LONG(offset);
|
141
|
+
|
142
|
+
Data_Get_Struct(self, AbstractMemory, ptr);
|
143
|
+
checkBounds(ptr, off, 1);
|
144
|
+
|
145
|
+
retval = Data_Make_Struct(rbffi_PointerClass, Pointer, ptr_mark, -1, p);
|
146
|
+
|
147
|
+
p->memory.address = ptr->address + off;
|
148
|
+
p->memory.size = ptr->size == LONG_MAX ? LONG_MAX : ptr->size - off;
|
149
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
150
|
+
p->memory.access = ptr->access;
|
151
|
+
p->memory.typeSize = ptr->typeSize;
|
152
|
+
p->parent = self;
|
153
|
+
|
154
|
+
return retval;
|
155
|
+
}
|
156
|
+
|
157
|
+
static VALUE
|
158
|
+
ptr_inspect(VALUE self)
|
159
|
+
{
|
160
|
+
Pointer* ptr;
|
161
|
+
char tmp[100];
|
162
|
+
|
163
|
+
Data_Get_Struct(self, Pointer, ptr);
|
164
|
+
snprintf(tmp, sizeof(tmp), "#<FFI::Pointer address=%p>", ptr->memory.address);
|
165
|
+
|
166
|
+
return rb_str_new2(tmp);
|
167
|
+
}
|
168
|
+
|
169
|
+
static VALUE
|
170
|
+
ptr_null_p(VALUE self)
|
171
|
+
{
|
172
|
+
Pointer* ptr;
|
173
|
+
|
174
|
+
Data_Get_Struct(self, Pointer, ptr);
|
175
|
+
|
176
|
+
return ptr->memory.address == NULL ? Qtrue : Qfalse;
|
177
|
+
}
|
178
|
+
|
179
|
+
static VALUE
|
180
|
+
ptr_equals(VALUE self, VALUE other)
|
181
|
+
{
|
182
|
+
Pointer* ptr;
|
183
|
+
|
184
|
+
Data_Get_Struct(self, Pointer, ptr);
|
185
|
+
|
186
|
+
return ptr->memory.address == POINTER(other)->address ? Qtrue : Qfalse;
|
187
|
+
}
|
188
|
+
|
189
|
+
static VALUE
|
190
|
+
ptr_address(VALUE self)
|
191
|
+
{
|
192
|
+
Pointer* ptr;
|
193
|
+
|
194
|
+
Data_Get_Struct(self, Pointer, ptr);
|
195
|
+
|
196
|
+
return ULL2NUM((uintptr_t) ptr->memory.address);
|
197
|
+
}
|
198
|
+
|
199
|
+
static void
|
200
|
+
ptr_mark(Pointer* ptr)
|
201
|
+
{
|
202
|
+
rb_gc_mark(ptr->parent);
|
203
|
+
}
|
204
|
+
|
205
|
+
void
|
206
|
+
rbffi_Pointer_Init(VALUE moduleFFI)
|
207
|
+
{
|
208
|
+
VALUE rbNullAddress = ULL2NUM(0);
|
209
|
+
|
210
|
+
rbffi_PointerClass = rb_define_class_under(moduleFFI, "Pointer", rbffi_AbstractMemoryClass);
|
211
|
+
rb_global_variable(&rbffi_PointerClass);
|
212
|
+
|
213
|
+
rb_define_alloc_func(rbffi_PointerClass, ptr_allocate);
|
214
|
+
rb_define_method(rbffi_PointerClass, "initialize", ptr_initialize, -1);
|
215
|
+
rb_define_method(rbffi_PointerClass, "inspect", ptr_inspect, 0);
|
216
|
+
rb_define_method(rbffi_PointerClass, "+", ptr_plus, 1);
|
217
|
+
rb_define_method(rbffi_PointerClass, "null?", ptr_null_p, 0);
|
218
|
+
rb_define_method(rbffi_PointerClass, "address", ptr_address, 0);
|
219
|
+
rb_define_alias(rbffi_PointerClass, "to_i", "address");
|
220
|
+
rb_define_method(rbffi_PointerClass, "==", ptr_equals, 1);
|
221
|
+
|
222
|
+
rbffi_NullPointerSingleton = rb_class_new_instance(1, &rbNullAddress, rbffi_PointerClass);
|
223
|
+
rb_define_const(rbffi_PointerClass, "NULL", rbffi_NullPointerSingleton);
|
224
|
+
}
|
data/ext/ffi_c/Pointer.h
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2008, 2009, Wayne Meissner
|
3
|
+
*
|
4
|
+
* All rights reserved.
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions are met:
|
8
|
+
*
|
9
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
10
|
+
* list of conditions and the following disclaimer.
|
11
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
12
|
+
* this list of conditions and the following disclaimer in the documentation
|
13
|
+
* and/or other materials provided with the distribution.
|
14
|
+
* * The name of the author or authors may not be used to endorse or promote
|
15
|
+
* products derived from this software without specific prior written permission.
|
16
|
+
*
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
*/
|
28
|
+
|
29
|
+
#ifndef RBFFI_POINTER_H
|
30
|
+
#define RBFFI_POINTER_H
|
31
|
+
|
32
|
+
#ifdef __cplusplus
|
33
|
+
extern "C" {
|
34
|
+
#endif
|
35
|
+
|
36
|
+
#include "AbstractMemory.h"
|
37
|
+
|
38
|
+
extern void rbffi_Pointer_Init(VALUE moduleFFI);
|
39
|
+
extern VALUE rbffi_Pointer_NewInstance(void* addr);
|
40
|
+
extern VALUE rbffi_PointerClass;
|
41
|
+
extern VALUE rbffi_NullPointerSingleton;
|
42
|
+
|
43
|
+
|
44
|
+
#ifdef __cplusplus
|
45
|
+
}
|
46
|
+
#endif
|
47
|
+
|
48
|
+
#endif /* RBFFI_POINTER_H */
|
49
|
+
|
data/ext/ffi_c/Struct.c
ADDED
@@ -0,0 +1,770 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2008, 2009, Wayne Meissner
|
3
|
+
* Copyright (c) 2009, Luc Heinrich <luc@honk-honk.com>
|
4
|
+
*
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions are met:
|
9
|
+
*
|
10
|
+
* * Redistributions of source code must retain the above copyright notice, this
|
11
|
+
* list of conditions and the following disclaimer.
|
12
|
+
* * Redistributions in binary form must reproduce the above copyright notice
|
13
|
+
* this list of conditions and the following disclaimer in the documentation
|
14
|
+
* and/or other materials provided with the distribution.
|
15
|
+
* * The name of the author or authors may not be used to endorse or promote
|
16
|
+
* products derived from this software without specific prior written permission.
|
17
|
+
*
|
18
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
22
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
*/
|
29
|
+
|
30
|
+
#include <sys/types.h>
|
31
|
+
|
32
|
+
#include "Function.h"
|
33
|
+
#include <sys/param.h>
|
34
|
+
#include <stdint.h>
|
35
|
+
#include <stdbool.h>
|
36
|
+
#include <ruby.h>
|
37
|
+
#include "rbffi.h"
|
38
|
+
#include "compat.h"
|
39
|
+
#include "AbstractMemory.h"
|
40
|
+
#include "Pointer.h"
|
41
|
+
#include "MemoryPointer.h"
|
42
|
+
#include "Function.h"
|
43
|
+
#include "Types.h"
|
44
|
+
#include "Struct.h"
|
45
|
+
#include "StructByValue.h"
|
46
|
+
#include "ArrayType.h"
|
47
|
+
|
48
|
+
#define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
|
49
|
+
|
50
|
+
typedef struct StructLayoutBuilder {
|
51
|
+
VALUE rbFieldNames;
|
52
|
+
VALUE rbFieldMap;
|
53
|
+
unsigned int size;
|
54
|
+
unsigned int alignment;
|
55
|
+
bool isUnion;
|
56
|
+
} StructLayoutBuilder;
|
57
|
+
|
58
|
+
typedef struct InlineArray_ {
|
59
|
+
VALUE rbMemory;
|
60
|
+
VALUE rbField;
|
61
|
+
|
62
|
+
AbstractMemory* memory;
|
63
|
+
StructField* field;
|
64
|
+
MemoryOp *op;
|
65
|
+
Type* componentType;
|
66
|
+
} InlineArray;
|
67
|
+
|
68
|
+
|
69
|
+
static void struct_mark(Struct *);
|
70
|
+
static void struct_layout_builder_mark(StructLayoutBuilder *);
|
71
|
+
static void struct_layout_builder_free(StructLayoutBuilder *);
|
72
|
+
static void inline_array_mark(InlineArray *);
|
73
|
+
|
74
|
+
static inline int align(int offset, int align);
|
75
|
+
|
76
|
+
VALUE rbffi_StructClass = Qnil;
|
77
|
+
static VALUE StructLayoutBuilderClass = Qnil;
|
78
|
+
|
79
|
+
VALUE rbffi_StructInlineArrayClass = Qnil;
|
80
|
+
static ID id_pointer_ivar = 0, id_layout_ivar = 0;
|
81
|
+
static ID id_get = 0, id_put = 0, id_to_ptr = 0, id_to_s = 0, id_layout = 0;
|
82
|
+
|
83
|
+
static inline char*
|
84
|
+
memory_address(VALUE self)
|
85
|
+
{
|
86
|
+
return ((AbstractMemory *)DATA_PTR((self)))->address;
|
87
|
+
}
|
88
|
+
|
89
|
+
static VALUE
|
90
|
+
struct_allocate(VALUE klass)
|
91
|
+
{
|
92
|
+
Struct* s;
|
93
|
+
VALUE obj = Data_Make_Struct(klass, Struct, struct_mark, -1, s);
|
94
|
+
|
95
|
+
s->rbPointer = Qnil;
|
96
|
+
s->rbLayout = Qnil;
|
97
|
+
|
98
|
+
return obj;
|
99
|
+
}
|
100
|
+
|
101
|
+
static VALUE
|
102
|
+
struct_initialize(int argc, VALUE* argv, VALUE self)
|
103
|
+
{
|
104
|
+
Struct* s;
|
105
|
+
VALUE rbPointer = Qnil, rest = Qnil, klass = CLASS_OF(self);
|
106
|
+
int nargs;
|
107
|
+
|
108
|
+
Data_Get_Struct(self, Struct, s);
|
109
|
+
|
110
|
+
nargs = rb_scan_args(argc, argv, "01*", &rbPointer, &rest);
|
111
|
+
|
112
|
+
/* Call up into ruby code to adjust the layout */
|
113
|
+
if (nargs > 1) {
|
114
|
+
s->rbLayout = rb_funcall2(CLASS_OF(self), id_layout, RARRAY_LEN(rest), RARRAY_PTR(rest));
|
115
|
+
} else if (rb_cvar_defined(klass, id_layout_ivar)) {
|
116
|
+
s->rbLayout = rb_cvar_get(klass, id_layout_ivar);
|
117
|
+
} else {
|
118
|
+
rb_raise(rb_eRuntimeError, "No Struct layout configured");
|
119
|
+
}
|
120
|
+
|
121
|
+
if (!rb_obj_is_kind_of(s->rbLayout, rbffi_StructLayoutClass)) {
|
122
|
+
rb_raise(rb_eRuntimeError, "Invalid Struct layout");
|
123
|
+
}
|
124
|
+
|
125
|
+
Data_Get_Struct(s->rbLayout, StructLayout, s->layout);
|
126
|
+
|
127
|
+
if (rbPointer != Qnil) {
|
128
|
+
s->pointer = MEMORY(rbPointer);
|
129
|
+
s->rbPointer = rbPointer;
|
130
|
+
} else {
|
131
|
+
s->rbPointer = rbffi_MemoryPointer_NewInstance(s->layout->size, 1, true);
|
132
|
+
s->pointer = (AbstractMemory *) DATA_PTR(s->rbPointer);
|
133
|
+
}
|
134
|
+
|
135
|
+
if (s->pointer->ops == NULL) {
|
136
|
+
VALUE name = rb_class_name(CLASS_OF(s->rbPointer));
|
137
|
+
rb_raise(rb_eRuntimeError, "No memory ops set for %s", StringValueCStr(name));
|
138
|
+
}
|
139
|
+
|
140
|
+
return self;
|
141
|
+
}
|
142
|
+
|
143
|
+
static void
|
144
|
+
struct_mark(Struct *s)
|
145
|
+
{
|
146
|
+
rb_gc_mark(s->rbPointer);
|
147
|
+
rb_gc_mark(s->rbLayout);
|
148
|
+
}
|
149
|
+
|
150
|
+
static VALUE
|
151
|
+
struct_field(Struct* s, VALUE fieldName)
|
152
|
+
{
|
153
|
+
StructLayout* layout = s->layout;
|
154
|
+
VALUE rbField;
|
155
|
+
if (layout == NULL) {
|
156
|
+
rb_raise(rb_eRuntimeError, "layout not set for Struct");
|
157
|
+
}
|
158
|
+
|
159
|
+
rbField = rb_hash_aref(layout->rbFieldMap, fieldName);
|
160
|
+
if (rbField == Qnil) {
|
161
|
+
VALUE str = rb_funcall2(fieldName, id_to_s, 0, NULL);
|
162
|
+
rb_raise(rb_eArgError, "No such field '%s'", StringValuePtr(str));
|
163
|
+
}
|
164
|
+
|
165
|
+
return rbField;
|
166
|
+
}
|
167
|
+
|
168
|
+
static VALUE
|
169
|
+
struct_aref(VALUE self, VALUE fieldName)
|
170
|
+
{
|
171
|
+
Struct* s;
|
172
|
+
VALUE rbField;
|
173
|
+
StructField* f;
|
174
|
+
MemoryOp* op;
|
175
|
+
|
176
|
+
Data_Get_Struct(self, Struct, s);
|
177
|
+
rbField = struct_field(s, fieldName);
|
178
|
+
f = (StructField *) DATA_PTR(rbField);
|
179
|
+
|
180
|
+
op = memory_get_op(s->pointer, f->type);
|
181
|
+
if (op != NULL) {
|
182
|
+
return (*op->get)(s->pointer, f->offset);
|
183
|
+
}
|
184
|
+
|
185
|
+
/* call up to the ruby code to fetch the value */
|
186
|
+
return rb_funcall2(rbField, id_get, 1, &s->rbPointer);
|
187
|
+
}
|
188
|
+
|
189
|
+
static VALUE
|
190
|
+
struct_aset(VALUE self, VALUE fieldName, VALUE value)
|
191
|
+
{
|
192
|
+
Struct* s;
|
193
|
+
VALUE rbField;
|
194
|
+
StructField* f;
|
195
|
+
MemoryOp* op;
|
196
|
+
VALUE argv[2];
|
197
|
+
|
198
|
+
Data_Get_Struct(self, Struct, s);
|
199
|
+
rbField = struct_field(s, fieldName);
|
200
|
+
f = (StructField *) DATA_PTR(rbField);
|
201
|
+
|
202
|
+
op = memory_get_op(s->pointer, f->type);
|
203
|
+
if (op != NULL) {
|
204
|
+
(*op->put)(s->pointer, f->offset, value);
|
205
|
+
return self;
|
206
|
+
}
|
207
|
+
|
208
|
+
/* call up to the ruby code to set the value */
|
209
|
+
argv[0] = s->rbPointer;
|
210
|
+
argv[1] = value;
|
211
|
+
rb_funcall2(rbField, id_put, 2, argv);
|
212
|
+
|
213
|
+
return self;
|
214
|
+
}
|
215
|
+
|
216
|
+
static VALUE
|
217
|
+
struct_set_pointer(VALUE self, VALUE pointer)
|
218
|
+
{
|
219
|
+
Struct* s;
|
220
|
+
|
221
|
+
if (!rb_obj_is_kind_of(pointer, rbffi_AbstractMemoryClass)) {
|
222
|
+
rb_raise(rb_eArgError, "Invalid pointer");
|
223
|
+
}
|
224
|
+
|
225
|
+
Data_Get_Struct(self, Struct, s);
|
226
|
+
s->pointer = MEMORY(pointer);
|
227
|
+
s->rbPointer = pointer;
|
228
|
+
rb_ivar_set(self, id_pointer_ivar, pointer);
|
229
|
+
|
230
|
+
return self;
|
231
|
+
}
|
232
|
+
|
233
|
+
static VALUE
|
234
|
+
struct_get_pointer(VALUE self)
|
235
|
+
{
|
236
|
+
Struct* s;
|
237
|
+
|
238
|
+
Data_Get_Struct(self, Struct, s);
|
239
|
+
|
240
|
+
return s->rbPointer;
|
241
|
+
}
|
242
|
+
|
243
|
+
static VALUE
|
244
|
+
struct_set_layout(VALUE self, VALUE layout)
|
245
|
+
{
|
246
|
+
Struct* s;
|
247
|
+
Data_Get_Struct(self, Struct, s);
|
248
|
+
|
249
|
+
if (!rb_obj_is_kind_of(layout, rbffi_StructLayoutClass)) {
|
250
|
+
rb_raise(rb_eArgError, "Invalid Struct layout");
|
251
|
+
}
|
252
|
+
|
253
|
+
Data_Get_Struct(layout, StructLayout, s->layout);
|
254
|
+
rb_ivar_set(self, id_layout_ivar, layout);
|
255
|
+
|
256
|
+
return self;
|
257
|
+
}
|
258
|
+
|
259
|
+
static VALUE
|
260
|
+
struct_get_layout(VALUE self)
|
261
|
+
{
|
262
|
+
Struct* s;
|
263
|
+
|
264
|
+
Data_Get_Struct(self, Struct, s);
|
265
|
+
|
266
|
+
return s->rbLayout;
|
267
|
+
}
|
268
|
+
|
269
|
+
static VALUE
|
270
|
+
struct_layout_builder_allocate(VALUE klass)
|
271
|
+
{
|
272
|
+
StructLayoutBuilder* builder;
|
273
|
+
VALUE obj;
|
274
|
+
|
275
|
+
obj = Data_Make_Struct(klass, StructLayoutBuilder, struct_layout_builder_mark, struct_layout_builder_free, builder);
|
276
|
+
|
277
|
+
builder->size = 0;
|
278
|
+
builder->alignment = 1;
|
279
|
+
builder->isUnion = false;
|
280
|
+
builder->rbFieldNames = rb_ary_new();
|
281
|
+
builder->rbFieldMap = rb_hash_new();
|
282
|
+
|
283
|
+
return obj;
|
284
|
+
}
|
285
|
+
|
286
|
+
static void
|
287
|
+
struct_layout_builder_mark(StructLayoutBuilder* builder)
|
288
|
+
{
|
289
|
+
rb_gc_mark(builder->rbFieldNames);
|
290
|
+
rb_gc_mark(builder->rbFieldMap);
|
291
|
+
}
|
292
|
+
|
293
|
+
static void
|
294
|
+
struct_layout_builder_free(StructLayoutBuilder* builder)
|
295
|
+
{
|
296
|
+
xfree(builder);
|
297
|
+
}
|
298
|
+
|
299
|
+
static VALUE
|
300
|
+
struct_layout_builder_initialize(VALUE self)
|
301
|
+
{
|
302
|
+
StructLayoutBuilder* builder;
|
303
|
+
|
304
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
305
|
+
|
306
|
+
return self;
|
307
|
+
}
|
308
|
+
|
309
|
+
static VALUE
|
310
|
+
struct_layout_builder_get_size(VALUE self)
|
311
|
+
{
|
312
|
+
StructLayoutBuilder* builder;
|
313
|
+
|
314
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
315
|
+
|
316
|
+
return UINT2NUM(builder->size);
|
317
|
+
}
|
318
|
+
|
319
|
+
static VALUE
|
320
|
+
struct_layout_builder_set_size(VALUE self, VALUE rbSize)
|
321
|
+
{
|
322
|
+
StructLayoutBuilder* builder;
|
323
|
+
unsigned int size = NUM2UINT(rbSize);
|
324
|
+
|
325
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
326
|
+
builder->size = MAX(size, builder->size);
|
327
|
+
|
328
|
+
return UINT2NUM(builder->size);
|
329
|
+
}
|
330
|
+
|
331
|
+
static VALUE
|
332
|
+
struct_layout_builder_get_alignment(VALUE self)
|
333
|
+
{
|
334
|
+
StructLayoutBuilder* builder;
|
335
|
+
|
336
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
337
|
+
|
338
|
+
return UINT2NUM(builder->alignment);
|
339
|
+
}
|
340
|
+
|
341
|
+
static VALUE
|
342
|
+
struct_layout_builder_set_alignment(VALUE self, VALUE rbAlign)
|
343
|
+
{
|
344
|
+
StructLayoutBuilder* builder;
|
345
|
+
unsigned int align = NUM2UINT(rbAlign);
|
346
|
+
|
347
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
348
|
+
builder->size = MAX(align, builder->alignment);
|
349
|
+
|
350
|
+
return UINT2NUM(builder->alignment);
|
351
|
+
}
|
352
|
+
|
353
|
+
static VALUE
|
354
|
+
struct_layout_builder_set_union(VALUE self, VALUE rbUnion)
|
355
|
+
{
|
356
|
+
StructLayoutBuilder* builder;
|
357
|
+
|
358
|
+
|
359
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
360
|
+
builder->isUnion = RTEST(rbUnion);
|
361
|
+
|
362
|
+
return rbUnion;
|
363
|
+
}
|
364
|
+
|
365
|
+
static VALUE
|
366
|
+
struct_layout_builder_union_p(VALUE self)
|
367
|
+
{
|
368
|
+
StructLayoutBuilder* builder;
|
369
|
+
|
370
|
+
|
371
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
372
|
+
|
373
|
+
|
374
|
+
return builder->isUnion ? Qtrue : Qfalse;
|
375
|
+
}
|
376
|
+
|
377
|
+
static void
|
378
|
+
store_field(StructLayoutBuilder* builder, VALUE rbName, VALUE rbField,
|
379
|
+
unsigned int offset, unsigned int size, unsigned int alignment)
|
380
|
+
{
|
381
|
+
rb_ary_push(builder->rbFieldNames, rbName);
|
382
|
+
rb_hash_aset(builder->rbFieldMap, rbName, rbField);
|
383
|
+
|
384
|
+
builder->alignment = MAX(builder->alignment, alignment);
|
385
|
+
|
386
|
+
if (builder->isUnion) {
|
387
|
+
builder->size = MAX(builder->size, size);
|
388
|
+
} else {
|
389
|
+
builder->size = MAX(builder->size, offset + size);
|
390
|
+
}
|
391
|
+
}
|
392
|
+
|
393
|
+
static int
|
394
|
+
calculate_offset(StructLayoutBuilder* builder, int alignment, VALUE rbOffset)
|
395
|
+
{
|
396
|
+
if (rbOffset != Qnil) {
|
397
|
+
return NUM2UINT(rbOffset);
|
398
|
+
} else {
|
399
|
+
return builder->isUnion ? 0 : align(builder->size, alignment);
|
400
|
+
}
|
401
|
+
}
|
402
|
+
|
403
|
+
static VALUE
|
404
|
+
struct_layout_builder_add_field(int argc, VALUE* argv, VALUE self)
|
405
|
+
{
|
406
|
+
StructLayoutBuilder* builder;
|
407
|
+
VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil;
|
408
|
+
unsigned int size, alignment, offset;
|
409
|
+
int nargs;
|
410
|
+
|
411
|
+
nargs = rb_scan_args(argc, argv, "21", &rbName, &rbType, &rbOffset);
|
412
|
+
|
413
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
414
|
+
|
415
|
+
alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
|
416
|
+
size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
|
417
|
+
|
418
|
+
offset = calculate_offset(builder, alignment, rbOffset);
|
419
|
+
|
420
|
+
//
|
421
|
+
// If a primitive type was passed in as the type arg, try and convert
|
422
|
+
//
|
423
|
+
if (!rb_obj_is_kind_of(rbType, rbffi_StructLayoutFieldClass)) {
|
424
|
+
VALUE fargv[3], rbFieldClass;
|
425
|
+
fargv[0] = rbName;
|
426
|
+
fargv[1] = UINT2NUM(offset);
|
427
|
+
fargv[2] = rbType;
|
428
|
+
if (rb_obj_is_kind_of(rbType, rbffi_FunctionTypeClass)) {
|
429
|
+
rbFieldClass = rbffi_StructLayoutFunctionFieldClass;
|
430
|
+
} else if (rb_obj_is_kind_of(rbType, rbffi_StructByValueClass)) {
|
431
|
+
rbFieldClass = rbffi_StructLayoutStructFieldClass;
|
432
|
+
} else if (rb_obj_is_kind_of(rbType, rbffi_ArrayTypeClass)) {
|
433
|
+
rbFieldClass = rbffi_StructLayoutArrayFieldClass;
|
434
|
+
} else {
|
435
|
+
rbFieldClass = rbffi_StructLayoutFieldClass;
|
436
|
+
}
|
437
|
+
|
438
|
+
rbField = rb_class_new_instance(3, fargv, rbFieldClass);
|
439
|
+
} else {
|
440
|
+
rbField = rbType;
|
441
|
+
}
|
442
|
+
|
443
|
+
store_field(builder, rbName, rbField, offset, size, alignment);
|
444
|
+
|
445
|
+
return self;
|
446
|
+
}
|
447
|
+
|
448
|
+
static VALUE
|
449
|
+
struct_layout_builder_add_struct(int argc, VALUE* argv, VALUE self)
|
450
|
+
{
|
451
|
+
StructLayoutBuilder* builder;
|
452
|
+
VALUE rbName = Qnil, rbType = Qnil, rbOffset = Qnil, rbField = Qnil, rbStructClass = Qnil;
|
453
|
+
VALUE fargv[3];
|
454
|
+
unsigned int size, alignment, offset;
|
455
|
+
int nargs;
|
456
|
+
|
457
|
+
nargs = rb_scan_args(argc, argv, "21", &rbName, &rbStructClass, &rbOffset);
|
458
|
+
|
459
|
+
if (!rb_obj_is_instance_of(rbStructClass, rb_cClass) || !rb_class_inherited(rbStructClass, rbffi_StructClass)) {
|
460
|
+
rb_raise(rb_eTypeError, "wrong argument type. Expected subclass of FFI::Struct");
|
461
|
+
}
|
462
|
+
|
463
|
+
rbType = rb_class_new_instance(1, &rbStructClass, rbffi_StructByValueClass);
|
464
|
+
|
465
|
+
alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
|
466
|
+
size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL));
|
467
|
+
|
468
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
469
|
+
|
470
|
+
offset = calculate_offset(builder, alignment, rbOffset);
|
471
|
+
|
472
|
+
fargv[0] = rbName;
|
473
|
+
fargv[1] = UINT2NUM(offset);
|
474
|
+
fargv[2] = rbType;
|
475
|
+
rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutStructFieldClass);
|
476
|
+
store_field(builder, rbName, rbField, offset, size, alignment);
|
477
|
+
|
478
|
+
return self;
|
479
|
+
}
|
480
|
+
|
481
|
+
static VALUE
|
482
|
+
struct_layout_builder_add_array(int argc, VALUE* argv, VALUE self)
|
483
|
+
{
|
484
|
+
StructLayoutBuilder* builder;
|
485
|
+
VALUE rbName = Qnil, rbType = Qnil, rbLength = Qnil, rbOffset = Qnil, rbField;
|
486
|
+
VALUE fargv[3], aargv[2];
|
487
|
+
unsigned int size, alignment, offset;
|
488
|
+
int nargs;
|
489
|
+
|
490
|
+
nargs = rb_scan_args(argc, argv, "31", &rbName, &rbType, &rbLength, &rbOffset);
|
491
|
+
|
492
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
493
|
+
|
494
|
+
alignment = NUM2UINT(rb_funcall2(rbType, rb_intern("alignment"), 0, NULL));
|
495
|
+
size = NUM2UINT(rb_funcall2(rbType, rb_intern("size"), 0, NULL)) * NUM2UINT(rbLength);
|
496
|
+
|
497
|
+
offset = calculate_offset(builder, alignment, rbOffset);
|
498
|
+
|
499
|
+
aargv[0] = rbType;
|
500
|
+
aargv[1] = rbLength;
|
501
|
+
fargv[0] = rbName;
|
502
|
+
fargv[1] = UINT2NUM(offset);
|
503
|
+
fargv[2] = rb_class_new_instance(2, aargv, rbffi_ArrayTypeClass);
|
504
|
+
rbField = rb_class_new_instance(3, fargv, rbffi_StructLayoutArrayFieldClass);
|
505
|
+
|
506
|
+
store_field(builder, rbName, rbField, offset, size, alignment);
|
507
|
+
|
508
|
+
return self;
|
509
|
+
}
|
510
|
+
|
511
|
+
static inline int
|
512
|
+
align(int offset, int align)
|
513
|
+
{
|
514
|
+
return align + ((offset - 1) & ~(align - 1));
|
515
|
+
}
|
516
|
+
|
517
|
+
static VALUE
|
518
|
+
struct_layout_builder_build(VALUE self)
|
519
|
+
{
|
520
|
+
StructLayoutBuilder* builder;
|
521
|
+
VALUE argv[4];
|
522
|
+
|
523
|
+
Data_Get_Struct(self, StructLayoutBuilder, builder);
|
524
|
+
|
525
|
+
argv[0] = builder->rbFieldNames;
|
526
|
+
argv[1] = builder->rbFieldMap;
|
527
|
+
argv[2] = UINT2NUM(align(builder->size, builder->alignment)); // tail padding
|
528
|
+
argv[3] = UINT2NUM(builder->alignment);
|
529
|
+
|
530
|
+
return rb_class_new_instance(4, argv, rbffi_StructLayoutClass);
|
531
|
+
}
|
532
|
+
|
533
|
+
static VALUE
|
534
|
+
inline_array_allocate(VALUE klass)
|
535
|
+
{
|
536
|
+
InlineArray* array;
|
537
|
+
VALUE obj;
|
538
|
+
|
539
|
+
obj = Data_Make_Struct(klass, InlineArray, inline_array_mark, -1, array);
|
540
|
+
array->rbField = Qnil;
|
541
|
+
array->rbMemory = Qnil;
|
542
|
+
|
543
|
+
return obj;
|
544
|
+
}
|
545
|
+
|
546
|
+
static void
|
547
|
+
inline_array_mark(InlineArray* array)
|
548
|
+
{
|
549
|
+
rb_gc_mark(array->rbField);
|
550
|
+
rb_gc_mark(array->rbMemory);
|
551
|
+
}
|
552
|
+
|
553
|
+
static VALUE
|
554
|
+
inline_array_initialize(VALUE self, VALUE rbMemory, VALUE rbField)
|
555
|
+
{
|
556
|
+
InlineArray* array;
|
557
|
+
ArrayType* arrayType;
|
558
|
+
|
559
|
+
Data_Get_Struct(self, InlineArray, array);
|
560
|
+
array->rbMemory = rbMemory;
|
561
|
+
array->rbField = rbField;
|
562
|
+
|
563
|
+
Data_Get_Struct(rbMemory, AbstractMemory, array->memory);
|
564
|
+
Data_Get_Struct(rbField, StructField, array->field);
|
565
|
+
Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
|
566
|
+
Data_Get_Struct(arrayType->rbComponentType, Type, array->componentType);
|
567
|
+
|
568
|
+
array->op = memory_get_op(array->memory, array->componentType);
|
569
|
+
if (array->op == NULL) {
|
570
|
+
rb_raise(rb_eRuntimeError, "invalid memory ops");
|
571
|
+
}
|
572
|
+
|
573
|
+
return self;
|
574
|
+
}
|
575
|
+
|
576
|
+
static VALUE
|
577
|
+
inline_array_size(VALUE self)
|
578
|
+
{
|
579
|
+
InlineArray* array;
|
580
|
+
|
581
|
+
Data_Get_Struct(self, InlineArray, array);
|
582
|
+
|
583
|
+
return UINT2NUM(array->field->type->ffiType->size);
|
584
|
+
}
|
585
|
+
|
586
|
+
static int
|
587
|
+
inline_array_offset(InlineArray* array, unsigned int index)
|
588
|
+
{
|
589
|
+
return array->field->offset + (index * array->componentType->ffiType->size);
|
590
|
+
}
|
591
|
+
|
592
|
+
static VALUE
|
593
|
+
inline_array_aref(VALUE self, VALUE rbIndex)
|
594
|
+
{
|
595
|
+
InlineArray* array;
|
596
|
+
|
597
|
+
Data_Get_Struct(self, InlineArray, array);
|
598
|
+
|
599
|
+
return array->op->get(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)));
|
600
|
+
}
|
601
|
+
|
602
|
+
static VALUE
|
603
|
+
inline_array_aset(VALUE self, VALUE rbIndex, VALUE rbValue)
|
604
|
+
{
|
605
|
+
InlineArray* array;
|
606
|
+
|
607
|
+
Data_Get_Struct(self, InlineArray, array);
|
608
|
+
|
609
|
+
array->op->put(array->memory, inline_array_offset(array, NUM2UINT(rbIndex)),
|
610
|
+
rbValue);
|
611
|
+
|
612
|
+
return rbValue;
|
613
|
+
}
|
614
|
+
|
615
|
+
static VALUE
|
616
|
+
inline_array_each(VALUE self)
|
617
|
+
{
|
618
|
+
InlineArray* array;
|
619
|
+
ArrayType* arrayType;
|
620
|
+
|
621
|
+
int i;
|
622
|
+
|
623
|
+
Data_Get_Struct(self, InlineArray, array);
|
624
|
+
Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
|
625
|
+
|
626
|
+
for (i = 0; i < arrayType->length; ++i) {
|
627
|
+
int offset = inline_array_offset(array, i);
|
628
|
+
rb_yield(array->op->get(array->memory, offset));
|
629
|
+
}
|
630
|
+
|
631
|
+
return self;
|
632
|
+
}
|
633
|
+
|
634
|
+
static VALUE
|
635
|
+
inline_array_to_a(VALUE self)
|
636
|
+
{
|
637
|
+
InlineArray* array;
|
638
|
+
ArrayType* arrayType;
|
639
|
+
VALUE obj;
|
640
|
+
int i;
|
641
|
+
|
642
|
+
Data_Get_Struct(self, InlineArray, array);
|
643
|
+
Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
|
644
|
+
obj = rb_ary_new2(arrayType->length);
|
645
|
+
|
646
|
+
|
647
|
+
for (i = 0; i < arrayType->length; ++i) {
|
648
|
+
int offset = inline_array_offset(array, i);
|
649
|
+
rb_ary_push(obj, array->op->get(array->memory, offset));
|
650
|
+
}
|
651
|
+
|
652
|
+
return obj;
|
653
|
+
}
|
654
|
+
|
655
|
+
static VALUE
|
656
|
+
inline_array_to_s(VALUE self)
|
657
|
+
{
|
658
|
+
InlineArray* array;
|
659
|
+
ArrayType* arrayType;
|
660
|
+
VALUE argv[2];
|
661
|
+
|
662
|
+
Data_Get_Struct(self, InlineArray, array);
|
663
|
+
Data_Get_Struct(array->field->rbType, ArrayType, arrayType);
|
664
|
+
|
665
|
+
if (arrayType->componentType->nativeType != NATIVE_INT8 && arrayType->componentType->nativeType != NATIVE_UINT8) {
|
666
|
+
rb_raise(rb_eNoMethodError, "to_s not defined for this array type");
|
667
|
+
return Qnil;
|
668
|
+
}
|
669
|
+
|
670
|
+
argv[0] = UINT2NUM(array->field->offset);
|
671
|
+
argv[1] = UINT2NUM(arrayType->length);
|
672
|
+
|
673
|
+
return rb_funcall2(array->rbMemory, rb_intern("get_string"), 2, argv);
|
674
|
+
}
|
675
|
+
|
676
|
+
|
677
|
+
static VALUE
|
678
|
+
inline_array_to_ptr(VALUE self)
|
679
|
+
{
|
680
|
+
InlineArray* array;
|
681
|
+
AbstractMemory* ptr;
|
682
|
+
VALUE rbOffset, rbPointer;
|
683
|
+
|
684
|
+
Data_Get_Struct(self, InlineArray, array);
|
685
|
+
|
686
|
+
rbOffset = UINT2NUM(array->field->offset);
|
687
|
+
rbPointer = rb_funcall2(array->rbMemory, rb_intern("+"), 1, &rbOffset);
|
688
|
+
Data_Get_Struct(rbPointer, AbstractMemory, ptr);
|
689
|
+
|
690
|
+
// Restrict the size of the pointer so ops like ptr.get_string(0) are bounds checked
|
691
|
+
ptr->size = MIN(ptr->size, array->field->type->ffiType->size);
|
692
|
+
|
693
|
+
return rbPointer;
|
694
|
+
}
|
695
|
+
|
696
|
+
|
697
|
+
void
|
698
|
+
rbffi_Struct_Init(VALUE moduleFFI)
|
699
|
+
{
|
700
|
+
VALUE StructClass;
|
701
|
+
|
702
|
+
rbffi_StructLayout_Init(moduleFFI);
|
703
|
+
|
704
|
+
rbffi_StructClass = StructClass = rb_define_class_under(moduleFFI, "Struct", rb_cObject);
|
705
|
+
rb_global_variable(&rbffi_StructClass);
|
706
|
+
|
707
|
+
|
708
|
+
StructLayoutBuilderClass = rb_define_class_under(moduleFFI, "StructLayoutBuilder", rb_cObject);
|
709
|
+
rb_global_variable(&StructLayoutBuilderClass);
|
710
|
+
|
711
|
+
rbffi_StructInlineArrayClass = rb_define_class_under(rbffi_StructClass, "InlineArray", rb_cObject);
|
712
|
+
rb_global_variable(&rbffi_StructInlineArrayClass);
|
713
|
+
|
714
|
+
|
715
|
+
|
716
|
+
rb_define_alloc_func(StructClass, struct_allocate);
|
717
|
+
rb_define_method(StructClass, "initialize", struct_initialize, -1);
|
718
|
+
|
719
|
+
rb_define_alias(rb_singleton_class(StructClass), "alloc_in", "new");
|
720
|
+
rb_define_alias(rb_singleton_class(StructClass), "alloc_out", "new");
|
721
|
+
rb_define_alias(rb_singleton_class(StructClass), "alloc_inout", "new");
|
722
|
+
rb_define_alias(rb_singleton_class(StructClass), "new_in", "new");
|
723
|
+
rb_define_alias(rb_singleton_class(StructClass), "new_out", "new");
|
724
|
+
rb_define_alias(rb_singleton_class(StructClass), "new_inout", "new");
|
725
|
+
|
726
|
+
rb_define_method(StructClass, "pointer", struct_get_pointer, 0);
|
727
|
+
rb_define_private_method(StructClass, "pointer=", struct_set_pointer, 1);
|
728
|
+
|
729
|
+
rb_define_method(StructClass, "layout", struct_get_layout, 0);
|
730
|
+
rb_define_private_method(StructClass, "layout=", struct_set_layout, 1);
|
731
|
+
|
732
|
+
rb_define_method(StructClass, "[]", struct_aref, 1);
|
733
|
+
rb_define_method(StructClass, "[]=", struct_aset, 2);
|
734
|
+
|
735
|
+
|
736
|
+
|
737
|
+
rb_define_alloc_func(StructLayoutBuilderClass, struct_layout_builder_allocate);
|
738
|
+
rb_define_method(StructLayoutBuilderClass, "initialize", struct_layout_builder_initialize, 0);
|
739
|
+
rb_define_method(StructLayoutBuilderClass, "build", struct_layout_builder_build, 0);
|
740
|
+
|
741
|
+
rb_define_method(StructLayoutBuilderClass, "alignment", struct_layout_builder_get_alignment, 0);
|
742
|
+
rb_define_method(StructLayoutBuilderClass, "alignment=", struct_layout_builder_set_alignment, 1);
|
743
|
+
rb_define_method(StructLayoutBuilderClass, "size", struct_layout_builder_get_size, 0);
|
744
|
+
rb_define_method(StructLayoutBuilderClass, "size=", struct_layout_builder_set_size, 1);
|
745
|
+
rb_define_method(StructLayoutBuilderClass, "union=", struct_layout_builder_set_union, 1);
|
746
|
+
rb_define_method(StructLayoutBuilderClass, "union?", struct_layout_builder_union_p, 0);
|
747
|
+
rb_define_method(StructLayoutBuilderClass, "add_field", struct_layout_builder_add_field, -1);
|
748
|
+
rb_define_method(StructLayoutBuilderClass, "add_array", struct_layout_builder_add_array, -1);
|
749
|
+
rb_define_method(StructLayoutBuilderClass, "add_struct", struct_layout_builder_add_struct, -1);
|
750
|
+
|
751
|
+
rb_include_module(rbffi_StructInlineArrayClass, rb_mEnumerable);
|
752
|
+
rb_define_alloc_func(rbffi_StructInlineArrayClass, inline_array_allocate);
|
753
|
+
rb_define_method(rbffi_StructInlineArrayClass, "initialize", inline_array_initialize, 2);
|
754
|
+
rb_define_method(rbffi_StructInlineArrayClass, "[]", inline_array_aref, 1);
|
755
|
+
rb_define_method(rbffi_StructInlineArrayClass, "[]=", inline_array_aset, 2);
|
756
|
+
rb_define_method(rbffi_StructInlineArrayClass, "each", inline_array_each, 0);
|
757
|
+
rb_define_method(rbffi_StructInlineArrayClass, "size", inline_array_size, 0);
|
758
|
+
rb_define_method(rbffi_StructInlineArrayClass, "to_a", inline_array_to_a, 0);
|
759
|
+
rb_define_method(rbffi_StructInlineArrayClass, "to_s", inline_array_to_s, 0);
|
760
|
+
rb_define_alias(rbffi_StructInlineArrayClass, "to_str", "to_s");
|
761
|
+
rb_define_method(rbffi_StructInlineArrayClass, "to_ptr", inline_array_to_ptr, 0);
|
762
|
+
|
763
|
+
id_pointer_ivar = rb_intern("@pointer");
|
764
|
+
id_layout_ivar = rb_intern("@layout");
|
765
|
+
id_layout = rb_intern("layout");
|
766
|
+
id_get = rb_intern("get");
|
767
|
+
id_put = rb_intern("put");
|
768
|
+
id_to_ptr = rb_intern("to_ptr");
|
769
|
+
id_to_s = rb_intern("to_s");
|
770
|
+
}
|