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
data/LICENSE
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
Copyright (c) 2008, JRuby Project
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
* Redistributions in binary form must reproduce the above copyright notice
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
* Neither the name of the JRuby Project nor the names of its contributors
|
13
|
+
may be used to endorse or promote products derived from this software
|
14
|
+
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
|
+
Copyright (c) 2007, Evan Phoenix
|
28
|
+
All rights reserved.
|
29
|
+
|
30
|
+
Redistribution and use in source and binary forms, with or without
|
31
|
+
modification, are permitted provided that the following conditions are met:
|
32
|
+
|
33
|
+
* Redistributions of source code must retain the above copyright notice, this
|
34
|
+
list of conditions and the following disclaimer.
|
35
|
+
* Redistributions in binary form must reproduce the above copyright notice
|
36
|
+
this list of conditions and the following disclaimer in the documentation
|
37
|
+
and/or other materials provided with the distribution.
|
38
|
+
* Neither the name of the Evan Phoenix nor the names of its contributors
|
39
|
+
may be used to endorse or promote products derived from this software
|
40
|
+
without specific prior written permission.
|
41
|
+
|
42
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
43
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
44
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
45
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
46
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
47
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
48
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
49
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
50
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
51
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
ruby-ffi
|
2
|
+
by Wayne Meissner
|
3
|
+
http://wiki.github.com/ffi/ffi
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Ruby-FFI is a ruby extension for programmatically loading dynamic
|
8
|
+
libraries, binding functions within them, and calling those functions
|
9
|
+
from Ruby code. Moreover, a Ruby-FFI extension works without changes
|
10
|
+
on Ruby and JRuby. Discover why should you write your next extension
|
11
|
+
using Ruby-FFI here[http://wiki.github.com/ffi/ffi/why-use-ffi].
|
12
|
+
|
13
|
+
== FEATURES/PROBLEMS:
|
14
|
+
|
15
|
+
* It has a very intuitive DSL
|
16
|
+
* It supports all C native types
|
17
|
+
* It supports C structs (also nested), enums and global variables
|
18
|
+
* It supports callbacks
|
19
|
+
* It has smart methods to handle memory management of pointers and structs
|
20
|
+
|
21
|
+
== SYNOPSIS:
|
22
|
+
|
23
|
+
require 'ffi'
|
24
|
+
|
25
|
+
module MyLib
|
26
|
+
extend FFI::Library
|
27
|
+
attach_function :puts, [ :string ], :int
|
28
|
+
end
|
29
|
+
|
30
|
+
MyLib.puts 'Hello boys using libc!'
|
31
|
+
|
32
|
+
For less minimalistic and more sane examples you may look at:
|
33
|
+
|
34
|
+
* the samples/ folder
|
35
|
+
* the examples on the wiki[http://wiki.github.com/ffi/ffi]
|
36
|
+
* the projects using FFI listed on this page[http://wiki.github.com/ffi/ffi/projects-using-ffi]
|
37
|
+
|
38
|
+
== REQUIREMENTS:
|
39
|
+
|
40
|
+
* You need a sane building environment in order to compile the extension.
|
41
|
+
|
42
|
+
== DOWNLOAD/INSTALL:
|
43
|
+
|
44
|
+
From rubyforge:
|
45
|
+
|
46
|
+
[sudo] gem install ffi
|
47
|
+
|
48
|
+
or from the git repository on github:
|
49
|
+
|
50
|
+
git clone git://github.com/ffi/ffi.git
|
51
|
+
cd ffi
|
52
|
+
rake gem:install
|
53
|
+
|
54
|
+
== CREDITS:
|
55
|
+
|
56
|
+
Special thanks to:
|
57
|
+
|
58
|
+
* Yehuda Katz
|
59
|
+
* Luc Heinrich
|
60
|
+
* Andrea Fazzi
|
61
|
+
* Mike Dalessio
|
62
|
+
* Hongli Lai
|
63
|
+
* Evan Phoenix
|
64
|
+
* Aman Gupta
|
65
|
+
* Beoran
|
66
|
+
|
67
|
+
== LICENSE:
|
68
|
+
|
69
|
+
See LICENSE file.
|
data/Rakefile
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rbconfig'
|
3
|
+
|
4
|
+
USE_RAKE_COMPILER = (RUBY_PLATFORM =~ /java/) ? false : true
|
5
|
+
if USE_RAKE_COMPILER
|
6
|
+
gem 'rake-compiler', '>=0.6.0'
|
7
|
+
require 'rake/extensiontask'
|
8
|
+
ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'date'
|
12
|
+
require 'fileutils'
|
13
|
+
require 'rbconfig'
|
14
|
+
|
15
|
+
begin
|
16
|
+
require 'bones'
|
17
|
+
Bones.setup
|
18
|
+
rescue LoadError
|
19
|
+
begin
|
20
|
+
load 'tasks/setup.rb'
|
21
|
+
rescue LoadError
|
22
|
+
raise RuntimeError, '### please install the "bones" gem ###'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
LIBEXT = case Config::CONFIG['host_os'].downcase
|
27
|
+
when /darwin/
|
28
|
+
"dylib"
|
29
|
+
when /mswin|mingw/
|
30
|
+
"dll"
|
31
|
+
else
|
32
|
+
Config::CONFIG['DLEXT']
|
33
|
+
end
|
34
|
+
|
35
|
+
CPU = case Config::CONFIG['host_cpu'].downcase
|
36
|
+
when /i[3456]86/
|
37
|
+
# Darwin always reports i686, even when running in 64bit mode
|
38
|
+
if Config::CONFIG['host_os'] =~ /darwin/ && 0xfee1deadbeef.is_a?(Fixnum)
|
39
|
+
"x86_64"
|
40
|
+
else
|
41
|
+
"i386"
|
42
|
+
end
|
43
|
+
when /amd64|x86_64/
|
44
|
+
"x86_64"
|
45
|
+
when /ppc|powerpc/
|
46
|
+
"powerpc"
|
47
|
+
else
|
48
|
+
Config::CONFIG['host_cpu']
|
49
|
+
end
|
50
|
+
|
51
|
+
OS = case Config::CONFIG['host_os'].downcase
|
52
|
+
when /linux/
|
53
|
+
"linux"
|
54
|
+
when /darwin/
|
55
|
+
"darwin"
|
56
|
+
when /freebsd/
|
57
|
+
"freebsd"
|
58
|
+
when /openbsd/
|
59
|
+
"openbsd"
|
60
|
+
when /sunos|solaris/
|
61
|
+
"solaris"
|
62
|
+
when /mswin|mingw/
|
63
|
+
"win32"
|
64
|
+
else
|
65
|
+
Config::CONFIG['host_os'].downcase
|
66
|
+
end
|
67
|
+
|
68
|
+
CC=ENV['CC'] || Config::CONFIG['CC'] || "gcc"
|
69
|
+
|
70
|
+
GMAKE = Config::CONFIG['host_os'].downcase =~ /bsd|solaris/ ? "gmake" : "make"
|
71
|
+
|
72
|
+
LIBTEST = "build/libtest.#{LIBEXT}"
|
73
|
+
BUILD_DIR = "build"
|
74
|
+
BUILD_EXT_DIR = File.join(BUILD_DIR, "#{Config::CONFIG['arch']}", 'ffi_c', RUBY_VERSION)
|
75
|
+
|
76
|
+
# Project general information
|
77
|
+
PROJ.name = 'ffi'
|
78
|
+
PROJ.authors = 'Wayne Meissner'
|
79
|
+
PROJ.email = 'wmeissner@gmail.com'
|
80
|
+
PROJ.url = 'http://wiki.github.com/ffi/ffi'
|
81
|
+
PROJ.version = '0.5.0'
|
82
|
+
PROJ.rubyforge.name = 'ffi'
|
83
|
+
PROJ.readme_file = 'README.rdoc'
|
84
|
+
|
85
|
+
# Annoucement
|
86
|
+
PROJ.ann.paragraphs << 'FEATURES' << 'SYNOPSIS' << 'REQUIREMENTS' << 'DOWNLOAD/INSTALL' << 'CREDITS' << 'LICENSE'
|
87
|
+
|
88
|
+
PROJ.ann.email[:from] = 'andrea.fazzi@alcacoop.it'
|
89
|
+
PROJ.ann.email[:to] << 'ruby-ffi@groups.google.com'
|
90
|
+
PROJ.ann.email[:server] = 'smtp.gmail.com'
|
91
|
+
|
92
|
+
# Gem specifications
|
93
|
+
PROJ.gem.need_tar = false
|
94
|
+
PROJ.gem.files = %w(LICENSE README.rdoc Rakefile) + Dir.glob("{ext,gen,lib,spec}/**/*")
|
95
|
+
PROJ.gem.platform = Gem::Platform::RUBY
|
96
|
+
|
97
|
+
# Override Mr. Bones autogenerated extensions and force ours in
|
98
|
+
PROJ.gem.extras['extensions'] = %w(ext/ffi_c/extconf.rb gen/Rakefile)
|
99
|
+
|
100
|
+
# RDoc
|
101
|
+
PROJ.rdoc.exclude << '^ext\/'
|
102
|
+
PROJ.rdoc.opts << '-x' << 'ext'
|
103
|
+
|
104
|
+
# Ruby
|
105
|
+
PROJ.ruby_opts = []
|
106
|
+
PROJ.ruby_opts << '-I' << BUILD_EXT_DIR unless RUBY_PLATFORM == "java"
|
107
|
+
|
108
|
+
# RSpec
|
109
|
+
PROJ.spec.files.exclude /rbx/
|
110
|
+
PROJ.spec.opts << '--color' << '-fs'
|
111
|
+
|
112
|
+
# Dependencies
|
113
|
+
|
114
|
+
depend_on 'rake', '>=0.8.7'
|
115
|
+
|
116
|
+
TEST_DEPS = [ LIBTEST ]
|
117
|
+
if RUBY_PLATFORM == "java"
|
118
|
+
desc "Run all specs"
|
119
|
+
task :specs => TEST_DEPS do
|
120
|
+
sh %{#{Gem.ruby} -S spec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
|
121
|
+
end
|
122
|
+
desc "Run rubinius specs"
|
123
|
+
task :rbxspecs => TEST_DEPS do
|
124
|
+
sh %{#{Gem.ruby} -S spec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
|
125
|
+
end
|
126
|
+
else
|
127
|
+
TEST_DEPS.unshift :compile
|
128
|
+
desc "Run all specs"
|
129
|
+
task :specs => TEST_DEPS do
|
130
|
+
ENV["MRI_FFI"] = "1"
|
131
|
+
sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S spec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color}
|
132
|
+
end
|
133
|
+
desc "Run rubinius specs"
|
134
|
+
task :rbxspecs => TEST_DEPS do
|
135
|
+
ENV["MRI_FFI"] = "1"
|
136
|
+
sh %{#{Gem.ruby} -Ilib -I#{BUILD_EXT_DIR} -S spec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
desc "Build all packages"
|
141
|
+
task :package => 'gem:package'
|
142
|
+
|
143
|
+
desc "Install the gem locally"
|
144
|
+
task :install => 'gem:install'
|
145
|
+
|
146
|
+
|
147
|
+
desc "Clean all built files"
|
148
|
+
task :distclean => :clobber do
|
149
|
+
FileUtils.rm_rf('build')
|
150
|
+
FileUtils.rm_rf(Dir["lib/**/ffi_c.#{Config::CONFIG['DLEXT']}"])
|
151
|
+
FileUtils.rm_rf('lib/1.8')
|
152
|
+
FileUtils.rm_rf('lib/1.9')
|
153
|
+
FileUtils.rm_rf('conftest.dSYM')
|
154
|
+
FileUtils.rm_rf('pkg')
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
desc "Build the native test lib"
|
159
|
+
task "build/libtest.#{LIBEXT}" do
|
160
|
+
sh %{#{GMAKE} -f libtest/GNUmakefile CPU=#{CPU} OS=#{OS} }
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
desc "Build test helper lib"
|
165
|
+
task :libtest => "build/libtest.#{LIBEXT}"
|
166
|
+
|
167
|
+
desc "Test the extension"
|
168
|
+
task :test => [ :specs, :rbxspecs ]
|
169
|
+
|
170
|
+
|
171
|
+
namespace :bench do
|
172
|
+
ITER = ENV['ITER'] ? ENV['ITER'].to_i : 100000
|
173
|
+
bench_libs = "-Ilib -I#{BUILD_DIR}" unless RUBY_PLATFORM == "java"
|
174
|
+
bench_files = Dir["bench/bench_*.rb"].reject { |f| f == "bench_helper.rb" }
|
175
|
+
bench_files.each do |bench|
|
176
|
+
task File.basename(bench, ".rb")[6..-1] => TEST_DEPS do
|
177
|
+
sh %{#{Gem.ruby} #{bench_libs} #{bench} #{ITER}}
|
178
|
+
end
|
179
|
+
end
|
180
|
+
task :all => TEST_DEPS do
|
181
|
+
bench_files.each do |bench|
|
182
|
+
sh %{#{Gem.ruby} #{bench_libs} #{bench}}
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
task 'spec:run' => TEST_DEPS
|
188
|
+
task 'spec:specdoc' => TEST_DEPS
|
189
|
+
|
190
|
+
task :default => :specs
|
191
|
+
|
@@ -0,0 +1,489 @@
|
|
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 <sys/types.h>
|
30
|
+
#include <sys/param.h>
|
31
|
+
#include <stdint.h>
|
32
|
+
#include <stdbool.h>
|
33
|
+
#include <ruby.h>
|
34
|
+
#include "rbffi.h"
|
35
|
+
#include "compat.h"
|
36
|
+
#include "AbstractMemory.h"
|
37
|
+
#include "Pointer.h"
|
38
|
+
#include "Function.h"
|
39
|
+
|
40
|
+
|
41
|
+
static inline char* memory_address(VALUE self);
|
42
|
+
VALUE rbffi_AbstractMemoryClass = Qnil;
|
43
|
+
static VALUE NullPointerErrorClass = Qnil;
|
44
|
+
static ID id_to_ptr = 0, id_plus = 0, id_call = 0;
|
45
|
+
|
46
|
+
static VALUE
|
47
|
+
memory_allocate(VALUE klass)
|
48
|
+
{
|
49
|
+
AbstractMemory* memory;
|
50
|
+
VALUE obj;
|
51
|
+
obj = Data_Make_Struct(klass, AbstractMemory, NULL, -1, memory);
|
52
|
+
memory->ops = &rbffi_AbstractMemoryOps;
|
53
|
+
memory->access = MEM_RD | MEM_WR;
|
54
|
+
|
55
|
+
return obj;
|
56
|
+
}
|
57
|
+
|
58
|
+
#define NUM_OP(name, type, toNative, fromNative) \
|
59
|
+
static void memory_op_put_##name(AbstractMemory* memory, long off, VALUE value); \
|
60
|
+
static void \
|
61
|
+
memory_op_put_##name(AbstractMemory* memory, long off, VALUE value) \
|
62
|
+
{ \
|
63
|
+
type tmp = (type) toNative(value); \
|
64
|
+
checkWrite(memory); \
|
65
|
+
checkBounds(memory, off, sizeof(type)); \
|
66
|
+
memcpy(memory->address + off, &tmp, sizeof(tmp)); \
|
67
|
+
} \
|
68
|
+
static VALUE memory_put_##name(VALUE self, VALUE offset, VALUE value); \
|
69
|
+
static VALUE \
|
70
|
+
memory_put_##name(VALUE self, VALUE offset, VALUE value) \
|
71
|
+
{ \
|
72
|
+
AbstractMemory* memory; \
|
73
|
+
Data_Get_Struct(self, AbstractMemory, memory); \
|
74
|
+
memory_op_put_##name(memory, NUM2LONG(offset), value); \
|
75
|
+
return self; \
|
76
|
+
} \
|
77
|
+
static VALUE memory_op_get_##name(AbstractMemory* memory, long off); \
|
78
|
+
static VALUE \
|
79
|
+
memory_op_get_##name(AbstractMemory* memory, long off) \
|
80
|
+
{ \
|
81
|
+
type tmp; \
|
82
|
+
checkRead(memory); \
|
83
|
+
checkBounds(memory, off, sizeof(type)); \
|
84
|
+
memcpy(&tmp, memory->address + off, sizeof(tmp)); \
|
85
|
+
return fromNative(tmp); \
|
86
|
+
} \
|
87
|
+
static VALUE memory_get_##name(VALUE self, VALUE offset); \
|
88
|
+
static VALUE \
|
89
|
+
memory_get_##name(VALUE self, VALUE offset) \
|
90
|
+
{ \
|
91
|
+
AbstractMemory* memory; \
|
92
|
+
Data_Get_Struct(self, AbstractMemory, memory); \
|
93
|
+
return memory_op_get_##name(memory, NUM2LONG(offset)); \
|
94
|
+
} \
|
95
|
+
static MemoryOp memory_op_##name = { memory_op_get_##name, memory_op_put_##name }; \
|
96
|
+
\
|
97
|
+
static VALUE memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary); \
|
98
|
+
static VALUE \
|
99
|
+
memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary) \
|
100
|
+
{ \
|
101
|
+
long count = RARRAY_LEN(ary); \
|
102
|
+
long off = NUM2LONG(offset); \
|
103
|
+
AbstractMemory* memory = MEMORY(self); \
|
104
|
+
long i; \
|
105
|
+
checkWrite(memory); \
|
106
|
+
checkBounds(memory, off, count * sizeof(type)); \
|
107
|
+
for (i = 0; i < count; i++) { \
|
108
|
+
type tmp = (type) toNative(RARRAY_PTR(ary)[i]); \
|
109
|
+
memcpy(memory->address + off + (i * sizeof(type)), &tmp, sizeof(tmp)); \
|
110
|
+
} \
|
111
|
+
return self; \
|
112
|
+
} \
|
113
|
+
static VALUE memory_get_array_of_##name(VALUE self, VALUE offset, VALUE length); \
|
114
|
+
static VALUE \
|
115
|
+
memory_get_array_of_##name(VALUE self, VALUE offset, VALUE length) \
|
116
|
+
{ \
|
117
|
+
long count = NUM2LONG(length); \
|
118
|
+
long off = NUM2LONG(offset); \
|
119
|
+
AbstractMemory* memory = MEMORY(self); \
|
120
|
+
long i; \
|
121
|
+
checkRead(memory); \
|
122
|
+
checkBounds(memory, off, count * sizeof(type)); \
|
123
|
+
VALUE retVal = rb_ary_new2(count); \
|
124
|
+
for (i = 0; i < count; ++i) { \
|
125
|
+
type tmp; \
|
126
|
+
memcpy(&tmp, memory->address + off + (i * sizeof(type)), sizeof(tmp)); \
|
127
|
+
rb_ary_push(retVal, fromNative(tmp)); \
|
128
|
+
} \
|
129
|
+
return retVal; \
|
130
|
+
}
|
131
|
+
|
132
|
+
NUM_OP(int8, int8_t, NUM2INT, INT2NUM);
|
133
|
+
NUM_OP(uint8, uint8_t, NUM2UINT, UINT2NUM);
|
134
|
+
NUM_OP(int16, int16_t, NUM2INT, INT2NUM);
|
135
|
+
NUM_OP(uint16, uint16_t, NUM2UINT, UINT2NUM);
|
136
|
+
NUM_OP(int32, int32_t, NUM2INT, INT2NUM);
|
137
|
+
NUM_OP(uint32, uint32_t, NUM2UINT, UINT2NUM);
|
138
|
+
NUM_OP(int64, int64_t, NUM2LL, LL2NUM);
|
139
|
+
NUM_OP(uint64, uint64_t, NUM2ULL, ULL2NUM);
|
140
|
+
NUM_OP(float32, float, NUM2DBL, rb_float_new);
|
141
|
+
NUM_OP(float64, double, NUM2DBL, rb_float_new);
|
142
|
+
|
143
|
+
static inline void*
|
144
|
+
get_pointer_value(VALUE value)
|
145
|
+
{
|
146
|
+
const int type = TYPE(value);
|
147
|
+
if (type == T_DATA && rb_obj_is_kind_of(value, rbffi_PointerClass)) {
|
148
|
+
return memory_address(value);
|
149
|
+
} else if (type == T_NIL) {
|
150
|
+
return NULL;
|
151
|
+
} else if (type == T_FIXNUM) {
|
152
|
+
return (void *) (uintptr_t) FIX2INT(value);
|
153
|
+
} else if (type == T_BIGNUM) {
|
154
|
+
return (void *) (uintptr_t) NUM2ULL(value);
|
155
|
+
} else if (rb_respond_to(value, id_to_ptr)) {
|
156
|
+
return MEMORY_PTR(rb_funcall2(value, id_to_ptr, 0, NULL));
|
157
|
+
} else {
|
158
|
+
rb_raise(rb_eArgError, "value is not a pointer");
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
NUM_OP(pointer, void *, get_pointer_value, rbffi_Pointer_NewInstance);
|
163
|
+
|
164
|
+
static VALUE
|
165
|
+
memory_clear(VALUE self)
|
166
|
+
{
|
167
|
+
AbstractMemory* ptr = MEMORY(self);
|
168
|
+
memset(ptr->address, 0, ptr->size);
|
169
|
+
return self;
|
170
|
+
}
|
171
|
+
|
172
|
+
static VALUE
|
173
|
+
memory_size(VALUE self)
|
174
|
+
{
|
175
|
+
AbstractMemory* ptr;
|
176
|
+
|
177
|
+
Data_Get_Struct(self, AbstractMemory, ptr);
|
178
|
+
|
179
|
+
return LONG2NUM(ptr->size);
|
180
|
+
}
|
181
|
+
|
182
|
+
static VALUE
|
183
|
+
memory_get_string(int argc, VALUE* argv, VALUE self)
|
184
|
+
{
|
185
|
+
VALUE length = Qnil, offset = Qnil;
|
186
|
+
AbstractMemory* ptr = MEMORY(self);
|
187
|
+
long off, len;
|
188
|
+
char* end;
|
189
|
+
int nargs = rb_scan_args(argc, argv, "11", &offset, &length);
|
190
|
+
|
191
|
+
off = NUM2LONG(offset);
|
192
|
+
len = nargs > 1 && length != Qnil ? NUM2LONG(length) : (ptr->size - off);
|
193
|
+
checkRead(ptr);
|
194
|
+
checkBounds(ptr, off, len);
|
195
|
+
|
196
|
+
end = memchr(ptr->address + off, 0, len);
|
197
|
+
return rb_tainted_str_new((char *) ptr->address + off,
|
198
|
+
(end != NULL ? end - ptr->address - off : len));
|
199
|
+
}
|
200
|
+
|
201
|
+
static VALUE
|
202
|
+
memory_get_array_of_string(int argc, VALUE* argv, VALUE self)
|
203
|
+
{
|
204
|
+
VALUE offset = Qnil, countnum = Qnil, retVal = Qnil;
|
205
|
+
AbstractMemory* ptr;
|
206
|
+
long off;
|
207
|
+
int count;
|
208
|
+
|
209
|
+
rb_scan_args(argc, argv, "11", &offset, &countnum);
|
210
|
+
off = NUM2LONG(offset);
|
211
|
+
count = (countnum == Qnil ? 0 : NUM2INT(countnum));
|
212
|
+
retVal = rb_ary_new2(count);
|
213
|
+
|
214
|
+
Data_Get_Struct(self, AbstractMemory, ptr);
|
215
|
+
checkRead(ptr);
|
216
|
+
|
217
|
+
if (countnum != Qnil) {
|
218
|
+
int i;
|
219
|
+
|
220
|
+
checkBounds(ptr, off, count * sizeof (char*));
|
221
|
+
|
222
|
+
for (i = 0; i < count; ++i) {
|
223
|
+
const char* strptr = *((const char**) (ptr->address + off) + i);
|
224
|
+
rb_ary_push(retVal, (strptr == NULL ? Qnil : rb_tainted_str_new2(strptr)));
|
225
|
+
}
|
226
|
+
|
227
|
+
} else {
|
228
|
+
checkBounds(ptr, off, sizeof (char*));
|
229
|
+
for ( ; off < ptr->size - sizeof (void *); off += sizeof (void *)) {
|
230
|
+
const char* strptr = *(const char**) (ptr->address + off);
|
231
|
+
if (strptr == NULL) {
|
232
|
+
break;
|
233
|
+
}
|
234
|
+
rb_ary_push(retVal, rb_tainted_str_new2(strptr));
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
238
|
+
return retVal;
|
239
|
+
}
|
240
|
+
|
241
|
+
static VALUE
|
242
|
+
memory_put_string(VALUE self, VALUE offset, VALUE str)
|
243
|
+
{
|
244
|
+
AbstractMemory* ptr = MEMORY(self);
|
245
|
+
long off, len;
|
246
|
+
|
247
|
+
Check_Type(str, T_STRING);
|
248
|
+
off = NUM2LONG(offset);
|
249
|
+
len = RSTRING_LEN(str);
|
250
|
+
|
251
|
+
checkWrite(ptr);
|
252
|
+
checkBounds(ptr, off, len + 1);
|
253
|
+
|
254
|
+
if (rb_safe_level() >= 1 && OBJ_TAINTED(str)) {
|
255
|
+
rb_raise(rb_eSecurityError, "Writing unsafe string to memory");
|
256
|
+
}
|
257
|
+
|
258
|
+
memcpy(ptr->address + off, RSTRING_PTR(str), len);
|
259
|
+
*((char *) ptr->address + off + len) = '\0';
|
260
|
+
|
261
|
+
return self;
|
262
|
+
}
|
263
|
+
|
264
|
+
static VALUE
|
265
|
+
memory_get_bytes(VALUE self, VALUE offset, VALUE length)
|
266
|
+
{
|
267
|
+
AbstractMemory* ptr = MEMORY(self);
|
268
|
+
long off, len;
|
269
|
+
|
270
|
+
off = NUM2LONG(offset);
|
271
|
+
len = NUM2LONG(length);
|
272
|
+
|
273
|
+
checkRead(ptr);
|
274
|
+
checkBounds(ptr, off, len);
|
275
|
+
|
276
|
+
return rb_tainted_str_new((char *) ptr->address + off, len);
|
277
|
+
}
|
278
|
+
|
279
|
+
static VALUE
|
280
|
+
memory_put_bytes(int argc, VALUE* argv, VALUE self)
|
281
|
+
{
|
282
|
+
AbstractMemory* ptr = MEMORY(self);
|
283
|
+
VALUE offset = Qnil, str = Qnil, rbIndex = Qnil, rbLength = Qnil;
|
284
|
+
long off, len, idx;
|
285
|
+
int nargs = rb_scan_args(argc, argv, "22", &offset, &str, &rbIndex, &rbLength);
|
286
|
+
|
287
|
+
Check_Type(str, T_STRING);
|
288
|
+
|
289
|
+
off = NUM2LONG(offset);
|
290
|
+
idx = nargs > 2 ? NUM2LONG(rbIndex) : 0;
|
291
|
+
if (idx < 0) {
|
292
|
+
rb_raise(rb_eRangeError, "index canot be less than zero");
|
293
|
+
}
|
294
|
+
len = nargs > 3 ? NUM2LONG(rbLength) : (RSTRING_LEN(str) - idx);
|
295
|
+
if ((idx + len) > RSTRING_LEN(str)) {
|
296
|
+
rb_raise(rb_eRangeError, "index+length is greater than size of string");
|
297
|
+
}
|
298
|
+
|
299
|
+
checkWrite(ptr);
|
300
|
+
checkBounds(ptr, off, len);
|
301
|
+
|
302
|
+
if (rb_safe_level() >= 1 && OBJ_TAINTED(str)) {
|
303
|
+
rb_raise(rb_eSecurityError, "Writing unsafe string to memory");
|
304
|
+
}
|
305
|
+
memcpy(ptr->address + off, RSTRING_PTR(str) + idx, len);
|
306
|
+
|
307
|
+
return self;
|
308
|
+
}
|
309
|
+
|
310
|
+
static VALUE
|
311
|
+
memory_type_size(VALUE self)
|
312
|
+
{
|
313
|
+
AbstractMemory* ptr;
|
314
|
+
|
315
|
+
Data_Get_Struct(self, AbstractMemory, ptr);
|
316
|
+
|
317
|
+
return INT2NUM(ptr->typeSize);
|
318
|
+
}
|
319
|
+
|
320
|
+
static VALUE
|
321
|
+
memory_aref(VALUE self, VALUE idx)
|
322
|
+
{
|
323
|
+
AbstractMemory* ptr;
|
324
|
+
VALUE rbOffset = Qnil;
|
325
|
+
|
326
|
+
Data_Get_Struct(self, AbstractMemory, ptr);
|
327
|
+
|
328
|
+
rbOffset = ULONG2NUM(NUM2ULONG(idx) * ptr->typeSize);
|
329
|
+
|
330
|
+
return rb_funcall2(self, id_plus, 1, &rbOffset);
|
331
|
+
}
|
332
|
+
|
333
|
+
static inline char*
|
334
|
+
memory_address(VALUE obj)
|
335
|
+
{
|
336
|
+
return ((AbstractMemory *) DATA_PTR(obj))->address;
|
337
|
+
}
|
338
|
+
|
339
|
+
AbstractMemory*
|
340
|
+
rbffi_AbstractMemory_Cast(VALUE obj, VALUE klass)
|
341
|
+
{
|
342
|
+
if (rb_obj_is_kind_of(obj, klass)) {
|
343
|
+
AbstractMemory* memory;
|
344
|
+
Data_Get_Struct(obj, AbstractMemory, memory);
|
345
|
+
return memory;
|
346
|
+
}
|
347
|
+
|
348
|
+
rb_raise(rb_eArgError, "Invalid Memory object");
|
349
|
+
return NULL;
|
350
|
+
}
|
351
|
+
|
352
|
+
void
|
353
|
+
rbffi_AbstractMemory_Error(AbstractMemory *mem, int op)
|
354
|
+
{
|
355
|
+
VALUE rbErrorClass = mem->address == NULL ? NullPointerErrorClass : rb_eRuntimeError;
|
356
|
+
if (op == MEM_RD) {
|
357
|
+
rb_raise(rbErrorClass, "invalid memory read at address=%p", mem->address);
|
358
|
+
} else if (op == MEM_WR) {
|
359
|
+
rb_raise(rbErrorClass, "invalid memory write at address=%p", mem->address);
|
360
|
+
} else {
|
361
|
+
rb_raise(rbErrorClass, "invalid memory access at address=%p", mem->address);
|
362
|
+
}
|
363
|
+
}
|
364
|
+
|
365
|
+
static VALUE
|
366
|
+
memory_op_get_strptr(AbstractMemory* ptr, long offset)
|
367
|
+
{
|
368
|
+
void* tmp = NULL;
|
369
|
+
|
370
|
+
if (ptr != NULL && ptr->address != NULL) {
|
371
|
+
checkRead(ptr);
|
372
|
+
checkBounds(ptr, offset, sizeof(tmp));
|
373
|
+
memcpy(&tmp, ptr->address + offset, sizeof(tmp));
|
374
|
+
}
|
375
|
+
|
376
|
+
return tmp != NULL ? rb_tainted_str_new2(tmp) : Qnil;
|
377
|
+
}
|
378
|
+
|
379
|
+
static void
|
380
|
+
memory_op_put_strptr(AbstractMemory* ptr, long offset, VALUE value)
|
381
|
+
{
|
382
|
+
rb_raise(rb_eArgError, "Cannot set :string fields");
|
383
|
+
}
|
384
|
+
|
385
|
+
static MemoryOp memory_op_strptr = { memory_op_get_strptr, memory_op_put_strptr };
|
386
|
+
|
387
|
+
//static MemoryOp memory_op_pointer = { memory_op_get_pointer, memory_op_put_pointer };
|
388
|
+
|
389
|
+
MemoryOps rbffi_AbstractMemoryOps = {
|
390
|
+
.int8 = &memory_op_int8,
|
391
|
+
.uint8 = &memory_op_uint8,
|
392
|
+
.int16 = &memory_op_int16,
|
393
|
+
.uint16 = &memory_op_uint16,
|
394
|
+
.int32 = &memory_op_int32,
|
395
|
+
.uint32 = &memory_op_uint32,
|
396
|
+
.int64 = &memory_op_int64,
|
397
|
+
.uint64 = &memory_op_uint64,
|
398
|
+
.float32 = &memory_op_float32,
|
399
|
+
.float64 = &memory_op_float64,
|
400
|
+
.pointer = &memory_op_pointer,
|
401
|
+
.strptr = &memory_op_strptr,
|
402
|
+
};
|
403
|
+
|
404
|
+
void
|
405
|
+
rbffi_AbstractMemory_Init(VALUE moduleFFI)
|
406
|
+
{
|
407
|
+
VALUE classMemory = rb_define_class_under(moduleFFI, "AbstractMemory", rb_cObject);
|
408
|
+
rbffi_AbstractMemoryClass = classMemory;
|
409
|
+
rb_global_variable(&rbffi_AbstractMemoryClass);
|
410
|
+
rb_define_alloc_func(classMemory, memory_allocate);
|
411
|
+
|
412
|
+
NullPointerErrorClass = rb_define_class_under(moduleFFI, "NullPointerError", rb_eRuntimeError);
|
413
|
+
rb_global_variable(&NullPointerErrorClass);
|
414
|
+
|
415
|
+
|
416
|
+
#undef INT
|
417
|
+
#define INT(type) \
|
418
|
+
rb_define_method(classMemory, "put_" #type, memory_put_##type, 2); \
|
419
|
+
rb_define_method(classMemory, "get_" #type, memory_get_##type, 1); \
|
420
|
+
rb_define_method(classMemory, "put_u" #type, memory_put_u##type, 2); \
|
421
|
+
rb_define_method(classMemory, "get_u" #type, memory_get_u##type, 1); \
|
422
|
+
rb_define_method(classMemory, "put_array_of_" #type, memory_put_array_of_##type, 2); \
|
423
|
+
rb_define_method(classMemory, "get_array_of_" #type, memory_get_array_of_##type, 2); \
|
424
|
+
rb_define_method(classMemory, "put_array_of_u" #type, memory_put_array_of_u##type, 2); \
|
425
|
+
rb_define_method(classMemory, "get_array_of_u" #type, memory_get_array_of_u##type, 2);
|
426
|
+
|
427
|
+
INT(int8);
|
428
|
+
INT(int16);
|
429
|
+
INT(int32);
|
430
|
+
INT(int64);
|
431
|
+
|
432
|
+
#define ALIAS(name, old) \
|
433
|
+
rb_define_alias(classMemory, "put_" #name, "put_" #old); \
|
434
|
+
rb_define_alias(classMemory, "get_" #name, "get_" #old); \
|
435
|
+
rb_define_alias(classMemory, "put_u" #name, "put_u" #old); \
|
436
|
+
rb_define_alias(classMemory, "get_u" #name, "get_u" #old); \
|
437
|
+
rb_define_alias(classMemory, "put_array_of_" #name, "put_array_of_" #old); \
|
438
|
+
rb_define_alias(classMemory, "get_array_of_" #name, "get_array_of_" #old); \
|
439
|
+
rb_define_alias(classMemory, "put_array_of_u" #name, "put_array_of_u" #old); \
|
440
|
+
rb_define_alias(classMemory, "get_array_of_u" #name, "get_array_of_u" #old);
|
441
|
+
|
442
|
+
ALIAS(char, int8);
|
443
|
+
ALIAS(short, int16);
|
444
|
+
ALIAS(int, int32);
|
445
|
+
ALIAS(long_long, int64);
|
446
|
+
|
447
|
+
if (sizeof(long) == 4) {
|
448
|
+
ALIAS(long, int32);
|
449
|
+
} else {
|
450
|
+
ALIAS(long, int64);
|
451
|
+
}
|
452
|
+
|
453
|
+
rb_define_method(classMemory, "put_float32", memory_put_float32, 2);
|
454
|
+
rb_define_method(classMemory, "get_float32", memory_get_float32, 1);
|
455
|
+
rb_define_alias(classMemory, "put_float", "put_float32");
|
456
|
+
rb_define_alias(classMemory, "get_float", "get_float32");
|
457
|
+
rb_define_method(classMemory, "put_array_of_float32", memory_put_array_of_float32, 2);
|
458
|
+
rb_define_method(classMemory, "get_array_of_float32", memory_get_array_of_float32, 2);
|
459
|
+
rb_define_alias(classMemory, "put_array_of_float", "put_array_of_float32");
|
460
|
+
rb_define_alias(classMemory, "get_array_of_float", "get_array_of_float32");
|
461
|
+
rb_define_method(classMemory, "put_float64", memory_put_float64, 2);
|
462
|
+
rb_define_method(classMemory, "get_float64", memory_get_float64, 1);
|
463
|
+
rb_define_alias(classMemory, "put_double", "put_float64");
|
464
|
+
rb_define_alias(classMemory, "get_double", "get_float64");
|
465
|
+
rb_define_method(classMemory, "put_array_of_float64", memory_put_array_of_float64, 2);
|
466
|
+
rb_define_method(classMemory, "get_array_of_float64", memory_get_array_of_float64, 2);
|
467
|
+
rb_define_alias(classMemory, "put_array_of_double", "put_array_of_float64");
|
468
|
+
rb_define_alias(classMemory, "get_array_of_double", "get_array_of_float64");
|
469
|
+
rb_define_method(classMemory, "put_pointer", memory_put_pointer, 2);
|
470
|
+
rb_define_method(classMemory, "get_pointer", memory_get_pointer, 1);
|
471
|
+
rb_define_method(classMemory, "put_array_of_pointer", memory_put_array_of_pointer, 2);
|
472
|
+
rb_define_method(classMemory, "get_array_of_pointer", memory_get_array_of_pointer, 2);
|
473
|
+
rb_define_method(classMemory, "get_string", memory_get_string, -1);
|
474
|
+
rb_define_method(classMemory, "put_string", memory_put_string, 2);
|
475
|
+
rb_define_method(classMemory, "get_bytes", memory_get_bytes, 2);
|
476
|
+
rb_define_method(classMemory, "put_bytes", memory_put_bytes, -1);
|
477
|
+
rb_define_method(classMemory, "get_array_of_string", memory_get_array_of_string, -1);
|
478
|
+
|
479
|
+
rb_define_method(classMemory, "clear", memory_clear, 0);
|
480
|
+
rb_define_method(classMemory, "total", memory_size, 0);
|
481
|
+
rb_define_alias(classMemory, "size", "total");
|
482
|
+
rb_define_method(classMemory, "type_size", memory_type_size, 0);
|
483
|
+
rb_define_method(classMemory, "[]", memory_aref, 1);
|
484
|
+
|
485
|
+
id_to_ptr = rb_intern("to_ptr");
|
486
|
+
id_call = rb_intern("call");
|
487
|
+
id_plus = rb_intern("+");
|
488
|
+
}
|
489
|
+
|