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,18 @@
|
|
1
|
+
#ifndef RBFFI_LASTERROR_H
|
2
|
+
#define RBFFI_LASTERROR_H
|
3
|
+
|
4
|
+
#ifdef __cplusplus
|
5
|
+
extern "C" {
|
6
|
+
#endif
|
7
|
+
|
8
|
+
|
9
|
+
void rbffi_LastError_Init(VALUE moduleFFI);
|
10
|
+
|
11
|
+
void rbffi_save_errno(void);
|
12
|
+
|
13
|
+
#ifdef __cplusplus
|
14
|
+
}
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#endif /* RBFFI_LASTERROR_H */
|
18
|
+
|
@@ -0,0 +1,178 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2008, 2009, Wayne Meissner
|
3
|
+
* Copyright (c) 2008, 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 <stdbool.h>
|
31
|
+
#include <stdint.h>
|
32
|
+
#include <limits.h>
|
33
|
+
#include <ruby.h>
|
34
|
+
#include "rbffi.h"
|
35
|
+
#include "AbstractMemory.h"
|
36
|
+
#include "Pointer.h"
|
37
|
+
#include "MemoryPointer.h"
|
38
|
+
|
39
|
+
typedef struct MemoryPointer {
|
40
|
+
AbstractMemory memory;
|
41
|
+
char* storage; /* start of malloc area */
|
42
|
+
bool autorelease;
|
43
|
+
bool allocated;
|
44
|
+
} MemoryPointer;
|
45
|
+
|
46
|
+
static VALUE memptr_allocate(VALUE klass);
|
47
|
+
static void memptr_release(MemoryPointer* ptr);
|
48
|
+
static VALUE memptr_malloc(VALUE self, long size, long count, bool clear);
|
49
|
+
static VALUE memptr_free(VALUE self);
|
50
|
+
|
51
|
+
VALUE rbffi_MemoryPointerClass;
|
52
|
+
|
53
|
+
#define MEMPTR(obj) ((MemoryPointer *) rbffi_AbstractMemory_Cast(obj, rbffi_MemoryPointerClass))
|
54
|
+
|
55
|
+
VALUE
|
56
|
+
rbffi_MemoryPointer_NewInstance(long size, long count, bool clear)
|
57
|
+
{
|
58
|
+
return memptr_malloc(memptr_allocate(rbffi_MemoryPointerClass), size, count, clear);
|
59
|
+
}
|
60
|
+
|
61
|
+
static VALUE
|
62
|
+
memptr_allocate(VALUE klass)
|
63
|
+
{
|
64
|
+
MemoryPointer* p;
|
65
|
+
VALUE obj = Data_Make_Struct(klass, MemoryPointer, NULL, memptr_release, p);
|
66
|
+
p->memory.ops = &rbffi_AbstractMemoryOps;
|
67
|
+
p->memory.access = MEM_RD | MEM_WR;
|
68
|
+
|
69
|
+
return obj;
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE
|
73
|
+
memptr_initialize(int argc, VALUE* argv, VALUE self)
|
74
|
+
{
|
75
|
+
VALUE size = Qnil, count = Qnil, clear = Qnil;
|
76
|
+
int nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
|
77
|
+
|
78
|
+
memptr_malloc(self, rbffi_type_size(size), nargs > 1 ? NUM2LONG(count) : 1,
|
79
|
+
RTEST(clear) || clear == Qnil);
|
80
|
+
|
81
|
+
if (rb_block_given_p()) {
|
82
|
+
return rb_ensure(rb_yield, self, memptr_free, self);
|
83
|
+
}
|
84
|
+
|
85
|
+
return self;
|
86
|
+
}
|
87
|
+
|
88
|
+
static VALUE
|
89
|
+
memptr_malloc(VALUE self, long size, long count, bool clear)
|
90
|
+
{
|
91
|
+
MemoryPointer* p;
|
92
|
+
unsigned long msize;
|
93
|
+
|
94
|
+
Data_Get_Struct(self, MemoryPointer, p);
|
95
|
+
|
96
|
+
msize = size * count;
|
97
|
+
|
98
|
+
p->storage = xmalloc(msize + 7);
|
99
|
+
if (p->storage == NULL) {
|
100
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory size=%ld bytes", msize);
|
101
|
+
}
|
102
|
+
p->autorelease = true;
|
103
|
+
p->memory.typeSize = size;
|
104
|
+
p->memory.size = msize;
|
105
|
+
/* ensure the memory is aligned on at least a 8 byte boundary */
|
106
|
+
p->memory.address = (char *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7UL);;
|
107
|
+
p->allocated = true;
|
108
|
+
|
109
|
+
if (clear && p->memory.size > 0) {
|
110
|
+
memset(p->memory.address, 0, p->memory.size);
|
111
|
+
}
|
112
|
+
|
113
|
+
return self;
|
114
|
+
}
|
115
|
+
|
116
|
+
static VALUE
|
117
|
+
memptr_inspect(VALUE self)
|
118
|
+
{
|
119
|
+
MemoryPointer* ptr;
|
120
|
+
char tmp[100];
|
121
|
+
|
122
|
+
Data_Get_Struct(self, MemoryPointer, ptr);
|
123
|
+
|
124
|
+
snprintf(tmp, sizeof(tmp), "#<FFI::MemoryPointer address=%p size=%lu>", ptr->memory.address, ptr->memory.size);
|
125
|
+
return rb_str_new2(tmp);
|
126
|
+
}
|
127
|
+
|
128
|
+
static VALUE
|
129
|
+
memptr_free(VALUE self)
|
130
|
+
{
|
131
|
+
MemoryPointer* ptr;
|
132
|
+
|
133
|
+
Data_Get_Struct(self, MemoryPointer, ptr);
|
134
|
+
|
135
|
+
if (ptr->allocated) {
|
136
|
+
if (ptr->storage != NULL) {
|
137
|
+
free(ptr->storage);
|
138
|
+
ptr->storage = NULL;
|
139
|
+
}
|
140
|
+
ptr->allocated = false;
|
141
|
+
}
|
142
|
+
|
143
|
+
return self;
|
144
|
+
}
|
145
|
+
|
146
|
+
static VALUE
|
147
|
+
memptr_autorelease(VALUE self, VALUE autorelease)
|
148
|
+
{
|
149
|
+
MemoryPointer* ptr;
|
150
|
+
|
151
|
+
Data_Get_Struct(self, MemoryPointer, ptr);
|
152
|
+
ptr->autorelease = autorelease == Qtrue;
|
153
|
+
|
154
|
+
return autorelease;
|
155
|
+
}
|
156
|
+
|
157
|
+
static void
|
158
|
+
memptr_release(MemoryPointer* ptr)
|
159
|
+
{
|
160
|
+
if (ptr->autorelease && ptr->allocated && ptr->storage != NULL) {
|
161
|
+
xfree(ptr->storage);
|
162
|
+
ptr->storage = NULL;
|
163
|
+
}
|
164
|
+
xfree(ptr);
|
165
|
+
}
|
166
|
+
|
167
|
+
void
|
168
|
+
rbffi_MemoryPointer_Init(VALUE moduleFFI)
|
169
|
+
{
|
170
|
+
rbffi_MemoryPointerClass = rb_define_class_under(moduleFFI, "MemoryPointer", rbffi_PointerClass);
|
171
|
+
rb_global_variable(&rbffi_MemoryPointerClass);
|
172
|
+
|
173
|
+
rb_define_alloc_func(rbffi_MemoryPointerClass, memptr_allocate);
|
174
|
+
rb_define_method(rbffi_MemoryPointerClass, "initialize", memptr_initialize, -1);
|
175
|
+
rb_define_method(rbffi_MemoryPointerClass, "inspect", memptr_inspect, 0);
|
176
|
+
rb_define_method(rbffi_MemoryPointerClass, "autorelease=", memptr_autorelease, 1);
|
177
|
+
rb_define_method(rbffi_MemoryPointerClass, "free", memptr_free, 0);
|
178
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
#ifndef _MEMORYPOINTER_H
|
3
|
+
#define _MEMORYPOINTER_H
|
4
|
+
|
5
|
+
#include <stdbool.h>
|
6
|
+
#include <ruby.h>
|
7
|
+
|
8
|
+
#ifdef __cplusplus
|
9
|
+
extern "C" {
|
10
|
+
#endif
|
11
|
+
|
12
|
+
extern void rbffi_MemoryPointer_Init(VALUE moduleFFI);
|
13
|
+
extern VALUE rbffi_MemoryPointerClass;
|
14
|
+
extern VALUE rbffi_MemoryPointer_NewInstance(long size, long count, bool clear);
|
15
|
+
#ifdef __cplusplus
|
16
|
+
}
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#endif /* _MEMORYPOINTER_H */
|
20
|
+
|
@@ -0,0 +1,346 @@
|
|
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
|
+
#include <sys/param.h>
|
29
|
+
#include <sys/types.h>
|
30
|
+
#ifndef _WIN32
|
31
|
+
# include <sys/mman.h>
|
32
|
+
#endif
|
33
|
+
#include <stdio.h>
|
34
|
+
#include <stdint.h>
|
35
|
+
#include <stdbool.h>
|
36
|
+
#ifndef _WIN32
|
37
|
+
# include <unistd.h>
|
38
|
+
#endif
|
39
|
+
#include <errno.h>
|
40
|
+
#include <ruby.h>
|
41
|
+
#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
|
42
|
+
# include <pthread.h>
|
43
|
+
#endif
|
44
|
+
|
45
|
+
#include <ffi.h>
|
46
|
+
#include "rbffi.h"
|
47
|
+
#include "compat.h"
|
48
|
+
|
49
|
+
#include "Function.h"
|
50
|
+
#include "Types.h"
|
51
|
+
#include "Type.h"
|
52
|
+
#include "LastError.h"
|
53
|
+
#include "Call.h"
|
54
|
+
#include "ClosurePool.h"
|
55
|
+
#include "MethodHandle.h"
|
56
|
+
|
57
|
+
|
58
|
+
#define MAX_METHOD_FIXED_ARITY (6)
|
59
|
+
|
60
|
+
#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
|
61
|
+
# define USE_PTHREAD_LOCAL
|
62
|
+
#endif
|
63
|
+
|
64
|
+
#ifndef roundup
|
65
|
+
# define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
|
66
|
+
#endif
|
67
|
+
#ifdef _WIN32
|
68
|
+
typedef char* caddr_t;
|
69
|
+
#endif
|
70
|
+
|
71
|
+
#ifdef USE_RAW
|
72
|
+
# define METHOD_CLOSURE ffi_raw_closure
|
73
|
+
# define METHOD_PARAMS ffi_raw*
|
74
|
+
#else
|
75
|
+
# define METHOD_CLOSURE ffi_closure
|
76
|
+
# define METHOD_PARAMS void**
|
77
|
+
#endif
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
static bool prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize);
|
82
|
+
static int trampoline_size(void);
|
83
|
+
|
84
|
+
#if defined(__x86_64__) && defined(__GNUC__)
|
85
|
+
# define CUSTOM_TRAMPOLINE 1
|
86
|
+
#endif
|
87
|
+
|
88
|
+
|
89
|
+
struct MethodHandle {
|
90
|
+
Closure* closure;
|
91
|
+
};
|
92
|
+
|
93
|
+
static ClosurePool* defaultClosurePool;
|
94
|
+
|
95
|
+
|
96
|
+
MethodHandle*
|
97
|
+
rbffi_MethodHandle_Alloc(FunctionType* fnInfo, void* function)
|
98
|
+
{
|
99
|
+
MethodHandle* handle;
|
100
|
+
Closure* closure = rbffi_Closure_Alloc(defaultClosurePool);
|
101
|
+
if (closure == NULL) {
|
102
|
+
rb_raise(rb_eNoMemError, "failed to allocate closure from pool");
|
103
|
+
return NULL;
|
104
|
+
}
|
105
|
+
|
106
|
+
handle = xcalloc(1, sizeof(*handle));
|
107
|
+
handle->closure = closure;
|
108
|
+
closure->info = fnInfo;
|
109
|
+
closure->function = function;
|
110
|
+
|
111
|
+
return handle;
|
112
|
+
}
|
113
|
+
|
114
|
+
void
|
115
|
+
rbffi_MethodHandle_Free(MethodHandle* handle)
|
116
|
+
{
|
117
|
+
if (handle != NULL) {
|
118
|
+
rbffi_Closure_Free(handle->closure);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
void*
|
123
|
+
rbffi_MethodHandle_CodeAddress(MethodHandle* handle)
|
124
|
+
{
|
125
|
+
return handle->closure->code;
|
126
|
+
}
|
127
|
+
|
128
|
+
#ifndef CUSTOM_TRAMPOLINE
|
129
|
+
static void attached_method_invoke(ffi_cif* cif, void* retval, METHOD_PARAMS parameters, void* user_data);
|
130
|
+
|
131
|
+
static ffi_type* methodHandleParamTypes[] = {
|
132
|
+
&ffi_type_sint,
|
133
|
+
&ffi_type_pointer,
|
134
|
+
&ffi_type_ulong,
|
135
|
+
};
|
136
|
+
|
137
|
+
static ffi_cif mh_cif;
|
138
|
+
|
139
|
+
static bool
|
140
|
+
prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize)
|
141
|
+
{
|
142
|
+
ffi_status ffiStatus;
|
143
|
+
|
144
|
+
#if defined(USE_RAW)
|
145
|
+
ffiStatus = ffi_prep_raw_closure(code, &mh_cif, attached_method_invoke, closure);
|
146
|
+
#else
|
147
|
+
ffiStatus = ffi_prep_closure(code, &mh_cif, attached_method_invoke, closure);
|
148
|
+
#endif
|
149
|
+
if (ffiStatus != FFI_OK) {
|
150
|
+
snprintf(errmsg, errmsgsize, "ffi_prep_closure failed. status=%#x", ffiStatus);
|
151
|
+
return false;
|
152
|
+
}
|
153
|
+
|
154
|
+
return true;
|
155
|
+
}
|
156
|
+
|
157
|
+
|
158
|
+
static int
|
159
|
+
trampoline_size(void)
|
160
|
+
{
|
161
|
+
return sizeof(METHOD_CLOSURE);
|
162
|
+
}
|
163
|
+
|
164
|
+
/*
|
165
|
+
* attached_method_vinvoke is used functions with more than 6 parameters, or
|
166
|
+
* with struct param or return values
|
167
|
+
*/
|
168
|
+
static void
|
169
|
+
attached_method_invoke(ffi_cif* cif, void* mretval, METHOD_PARAMS parameters, void* user_data)
|
170
|
+
{
|
171
|
+
Closure* handle = (Closure *) user_data;
|
172
|
+
FunctionType* fnInfo = (FunctionType *) handle->info;
|
173
|
+
|
174
|
+
#ifdef USE_RAW
|
175
|
+
int argc = parameters[0].sint;
|
176
|
+
VALUE* argv = *(VALUE **) ¶meters[1];
|
177
|
+
#else
|
178
|
+
int argc = *(ffi_sarg *) parameters[0];
|
179
|
+
VALUE* argv = *(VALUE **) parameters[1];
|
180
|
+
#endif
|
181
|
+
|
182
|
+
*(VALUE *) mretval = (*fnInfo->invoke)(argc, argv, handle->function, fnInfo);
|
183
|
+
}
|
184
|
+
|
185
|
+
#endif
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
#if defined(CUSTOM_TRAMPOLINE)
|
190
|
+
#if defined(__x86_64__)
|
191
|
+
|
192
|
+
static VALUE custom_trampoline(int argc, VALUE* argv, VALUE self, Closure*);
|
193
|
+
|
194
|
+
#define TRAMPOLINE_CTX_MAGIC (0xfee1deadcafebabe)
|
195
|
+
#define TRAMPOLINE_FUN_MAGIC (0xfeedfacebeeff00d)
|
196
|
+
|
197
|
+
/*
|
198
|
+
* This is a hand-coded trampoline to speedup entry from ruby to the FFI translation
|
199
|
+
* layer for x86_64 arches.
|
200
|
+
*
|
201
|
+
* Since a ruby function has exactly 3 arguments, and the first 6 arguments are
|
202
|
+
* passed in registers for x86_64, we can tack on a context pointer by simply
|
203
|
+
* putting a value in %rcx, then jumping to the C trampoline code.
|
204
|
+
*
|
205
|
+
* This results in approx a 30% speedup for x86_64 FFI dispatch
|
206
|
+
*/
|
207
|
+
asm(
|
208
|
+
".text\n\t"
|
209
|
+
".globl ffi_trampoline\n\t"
|
210
|
+
".globl _ffi_trampoline\n\t"
|
211
|
+
"ffi_trampoline:\n\t"
|
212
|
+
"_ffi_trampoline:\n\t"
|
213
|
+
"movabsq $0xfee1deadcafebabe, %rcx\n\t"
|
214
|
+
"movabsq $0xfeedfacebeeff00d, %r11\n\t"
|
215
|
+
"jmpq *%r11\n\t"
|
216
|
+
".globl ffi_trampoline_end\n\t"
|
217
|
+
"ffi_trampoline_end:\n\t"
|
218
|
+
".globl _ffi_trampoline_end\n\t"
|
219
|
+
"_ffi_trampoline_end:\n\t"
|
220
|
+
);
|
221
|
+
|
222
|
+
static VALUE
|
223
|
+
custom_trampoline(int argc, VALUE* argv, VALUE self, Closure* handle)
|
224
|
+
{
|
225
|
+
FunctionType* fnInfo = (FunctionType *) handle->info;
|
226
|
+
return (*fnInfo->invoke)(argc, argv, handle->function, fnInfo);
|
227
|
+
}
|
228
|
+
|
229
|
+
#elif defined(__i386__) && 0
|
230
|
+
|
231
|
+
static VALUE custom_trampoline(caddr_t args, Closure*);
|
232
|
+
#define TRAMPOLINE_CTX_MAGIC (0xfee1dead)
|
233
|
+
#define TRAMPOLINE_FUN_MAGIC (0xbeefcafe)
|
234
|
+
|
235
|
+
/*
|
236
|
+
* This is a hand-coded trampoline to speedup entry from ruby to the FFI translation
|
237
|
+
* layer for i386 arches.
|
238
|
+
*
|
239
|
+
* This does not make a discernable difference vs a raw closure, so for now,
|
240
|
+
* it is not enabled.
|
241
|
+
*/
|
242
|
+
asm(
|
243
|
+
".text\n\t"
|
244
|
+
".globl ffi_trampoline\n\t"
|
245
|
+
".globl _ffi_trampoline\n\t"
|
246
|
+
"ffi_trampoline:\n\t"
|
247
|
+
"_ffi_trampoline:\n\t"
|
248
|
+
"subl $12, %esp\n\t"
|
249
|
+
"leal 16(%esp), %eax\n\t"
|
250
|
+
"movl %eax, (%esp)\n\t"
|
251
|
+
"movl $0xfee1dead, 4(%esp)\n\t"
|
252
|
+
"movl $0xbeefcafe, %eax\n\t"
|
253
|
+
"call *%eax\n\t"
|
254
|
+
"addl $12, %esp\n\t"
|
255
|
+
"ret\n\t"
|
256
|
+
".globl ffi_trampoline_end\n\t"
|
257
|
+
"ffi_trampoline_end:\n\t"
|
258
|
+
".globl _ffi_trampoline_end\n\t"
|
259
|
+
"_ffi_trampoline_end:\n\t"
|
260
|
+
);
|
261
|
+
|
262
|
+
static VALUE
|
263
|
+
custom_trampoline(caddr_t args, Closure* handle)
|
264
|
+
{
|
265
|
+
FunctionType* fnInfo = (FunctionType *) handle->info;
|
266
|
+
return (*fnInfo->invoke)(*(int *) args, *(VALUE **) (args + 4), handle->function, fnInfo);
|
267
|
+
}
|
268
|
+
|
269
|
+
#endif /* __x86_64__ else __i386__ */
|
270
|
+
|
271
|
+
extern void ffi_trampoline(int argc, VALUE* argv, VALUE self);
|
272
|
+
extern void ffi_trampoline_end(void);
|
273
|
+
static int trampoline_offsets(int *, int *);
|
274
|
+
|
275
|
+
static int trampoline_ctx_offset, trampoline_func_offset;
|
276
|
+
|
277
|
+
static int
|
278
|
+
trampoline_offset(int off, const long value)
|
279
|
+
{
|
280
|
+
caddr_t ptr;
|
281
|
+
for (ptr = (caddr_t) &ffi_trampoline + off; ptr < (caddr_t) &ffi_trampoline_end; ++ptr) {
|
282
|
+
if (*(long *) ptr == value) {
|
283
|
+
return ptr - (caddr_t) &ffi_trampoline;
|
284
|
+
}
|
285
|
+
}
|
286
|
+
|
287
|
+
return -1;
|
288
|
+
}
|
289
|
+
|
290
|
+
static int
|
291
|
+
trampoline_offsets(int* ctxOffset, int* fnOffset)
|
292
|
+
{
|
293
|
+
*ctxOffset = trampoline_offset(0, TRAMPOLINE_CTX_MAGIC);
|
294
|
+
if (*ctxOffset == -1) {
|
295
|
+
return -1;
|
296
|
+
}
|
297
|
+
|
298
|
+
*fnOffset = trampoline_offset(0, TRAMPOLINE_FUN_MAGIC);
|
299
|
+
if (*fnOffset == -1) {
|
300
|
+
return -1;
|
301
|
+
}
|
302
|
+
|
303
|
+
return 0;
|
304
|
+
}
|
305
|
+
|
306
|
+
static bool
|
307
|
+
prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize)
|
308
|
+
{
|
309
|
+
caddr_t ptr = (caddr_t) code;
|
310
|
+
|
311
|
+
memcpy(ptr, &ffi_trampoline, trampoline_size());
|
312
|
+
// Patch the context and function addresses into the stub code
|
313
|
+
*(intptr_t *)(ptr + trampoline_ctx_offset) = (intptr_t) closure;
|
314
|
+
*(intptr_t *)(ptr + trampoline_func_offset) = (intptr_t) custom_trampoline;
|
315
|
+
|
316
|
+
return true;
|
317
|
+
}
|
318
|
+
|
319
|
+
static int
|
320
|
+
trampoline_size(void)
|
321
|
+
{
|
322
|
+
return (caddr_t) &ffi_trampoline_end - (caddr_t) &ffi_trampoline;
|
323
|
+
}
|
324
|
+
|
325
|
+
#endif /* CUSTOM_TRAMPOLINE */
|
326
|
+
|
327
|
+
|
328
|
+
void
|
329
|
+
rbffi_MethodHandle_Init(VALUE module)
|
330
|
+
{
|
331
|
+
defaultClosurePool = rbffi_ClosurePool_New(trampoline_size(), prep_trampoline, NULL);
|
332
|
+
|
333
|
+
#if defined(CUSTOM_TRAMPOLINE)
|
334
|
+
if (trampoline_offsets(&trampoline_ctx_offset, &trampoline_func_offset) != 0) {
|
335
|
+
rb_raise(rb_eFatal, "Could not locate offsets in trampoline code");
|
336
|
+
}
|
337
|
+
#else
|
338
|
+
ffi_status ffiStatus = ffi_prep_cif(&mh_cif, FFI_DEFAULT_ABI, 3, &ffi_type_ulong,
|
339
|
+
methodHandleParamTypes);
|
340
|
+
if (ffiStatus != FFI_OK) {
|
341
|
+
rb_raise(rb_eFatal, "ffi_prep_cif failed. status=%#x", ffiStatus);
|
342
|
+
}
|
343
|
+
|
344
|
+
#endif
|
345
|
+
}
|
346
|
+
|