ffi 0.2.0 → 0.3.0
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/README.rdoc +19 -0
- data/Rakefile +65 -55
- data/ext/{AbstractMemory.c → ffi_c/AbstractMemory.c} +67 -40
- data/ext/{AbstractMemory.h → ffi_c/AbstractMemory.h} +10 -8
- data/ext/{AutoPointer.c → ffi_c/AutoPointer.c} +17 -8
- data/ext/{AutoPointer.h → ffi_c/AutoPointer.h} +0 -0
- data/ext/ffi_c/Buffer.c +136 -0
- data/ext/{Callback.c → ffi_c/Callback.c} +60 -35
- data/ext/{Callback.h → ffi_c/Callback.h} +1 -7
- data/ext/{Invoker.c → ffi_c/Invoker.c} +472 -102
- data/ext/ffi_c/MemoryPointer.c +146 -0
- data/ext/{MemoryPointer.h → ffi_c/MemoryPointer.h} +2 -7
- data/ext/ffi_c/NativeLibrary.c +149 -0
- data/ext/{NativeLibrary.h → ffi_c/NativeLibrary.h} +0 -0
- data/ext/ffi_c/NullPointer.c +104 -0
- data/ext/{Platform.c → ffi_c/Platform.c} +0 -0
- data/ext/{Platform.h → ffi_c/Platform.h} +0 -7
- data/ext/{Pointer.c → ffi_c/Pointer.c} +35 -15
- data/ext/{Pointer.h → ffi_c/Pointer.h} +4 -2
- data/ext/ffi_c/Struct.c +542 -0
- data/ext/ffi_c/Struct.h +26 -0
- data/ext/ffi_c/Types.c +76 -0
- data/ext/{Types.h → ffi_c/Types.h} +23 -28
- data/ext/{compat.h → ffi_c/compat.h} +2 -2
- data/ext/{extconf.rb → ffi_c/extconf.rb} +12 -7
- data/ext/ffi_c/ffi.c +99 -0
- data/ext/ffi_c/ffi.mk +23 -0
- data/ext/{libffi.darwin.mk → ffi_c/libffi.darwin.mk} +0 -0
- data/ext/ffi_c/libffi.mk +11 -0
- data/ext/{libffi → ffi_c/libffi}/ChangeLog +0 -0
- data/ext/{libffi → ffi_c/libffi}/ChangeLog.libffi +0 -0
- data/ext/{libffi → ffi_c/libffi}/ChangeLog.libgcj +0 -0
- data/ext/{libffi → ffi_c/libffi}/ChangeLog.v1 +0 -0
- data/ext/{libffi → ffi_c/libffi}/LICENSE +0 -0
- data/ext/{libffi → ffi_c/libffi}/Makefile.am +0 -0
- data/ext/{libffi → ffi_c/libffi}/Makefile.in +0 -0
- data/ext/{libffi → ffi_c/libffi}/README +0 -0
- data/ext/{libffi → ffi_c/libffi}/TODO +0 -0
- data/ext/{libffi → ffi_c/libffi}/acinclude.m4 +0 -0
- data/ext/{libffi → ffi_c/libffi}/aclocal.m4 +0 -0
- data/ext/{libffi → ffi_c/libffi}/compile +0 -0
- data/ext/{libffi → ffi_c/libffi}/config.guess +0 -0
- data/ext/{libffi → ffi_c/libffi}/config.sub +0 -0
- data/ext/{libffi → ffi_c/libffi}/configure +0 -0
- data/ext/{libffi → ffi_c/libffi}/configure.ac +0 -0
- data/ext/{libffi → ffi_c/libffi}/configure.host +0 -0
- data/ext/{libffi → ffi_c/libffi}/depcomp +0 -0
- data/ext/{libffi → ffi_c/libffi}/doc/libffi.info +0 -0
- data/ext/{libffi → ffi_c/libffi}/doc/libffi.texi +0 -0
- data/ext/{libffi → ffi_c/libffi}/doc/stamp-vti +0 -0
- data/ext/{libffi → ffi_c/libffi}/doc/version.texi +0 -0
- data/ext/{libffi → ffi_c/libffi}/fficonfig.h.in +0 -0
- data/ext/{libffi → ffi_c/libffi}/include/Makefile.am +0 -0
- data/ext/{libffi → ffi_c/libffi}/include/Makefile.in +0 -0
- data/ext/{libffi → ffi_c/libffi}/include/ffi.h.in +0 -0
- data/ext/{libffi → ffi_c/libffi}/include/ffi_common.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/install-sh +0 -0
- data/ext/{libffi → ffi_c/libffi}/libffi.pc.in +0 -0
- data/ext/{libffi → ffi_c/libffi}/libtool-version +0 -0
- data/ext/{libffi → ffi_c/libffi}/ltcf-c.sh +0 -0
- data/ext/{libffi → ffi_c/libffi}/ltcf-cxx.sh +0 -0
- data/ext/{libffi → ffi_c/libffi}/ltcf-gcj.sh +0 -0
- data/ext/{libffi → ffi_c/libffi}/ltconfig +0 -0
- data/ext/{libffi → ffi_c/libffi}/ltmain.sh +0 -0
- data/ext/{libffi → ffi_c/libffi}/man/Makefile.am +0 -0
- data/ext/{libffi → ffi_c/libffi}/man/Makefile.in +0 -0
- data/ext/{libffi → ffi_c/libffi}/man/ffi.3 +0 -0
- data/ext/{libffi → ffi_c/libffi}/man/ffi_call.3 +0 -0
- data/ext/{libffi → ffi_c/libffi}/man/ffi_prep_cif.3 +0 -0
- data/ext/{libffi → ffi_c/libffi}/mdate-sh +0 -0
- data/ext/{libffi → ffi_c/libffi}/missing +0 -0
- data/ext/{libffi → ffi_c/libffi}/mkinstalldirs +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/alpha/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/alpha/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/alpha/osf.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/arm/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/arm/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/arm/sysv.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/closures.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/cris/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/cris/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/cris/sysv.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/debug.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/dlmalloc.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/frv/eabi.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/frv/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/frv/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/ia64/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/ia64/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/ia64/ia64_flags.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/ia64/unix.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/java_raw_api.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/m32r/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/m32r/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/m32r/sysv.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/m68k/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/m68k/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/m68k/sysv.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/mips/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/mips/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/mips/n32.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/mips/o32.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/pa/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/pa/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/pa/hpux32.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/pa/linux.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/aix.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/aix_closure.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/asm.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/darwin.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/darwin_closure.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/ffi_darwin.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/linux64.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/linux64_closure.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/ppc_closure.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/powerpc/sysv.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/prep_cif.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/raw_api.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/s390/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/s390/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/s390/sysv.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sh/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sh/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sh/sysv.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sh64/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sh64/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sh64/sysv.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sparc/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sparc/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sparc/v8.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/sparc/v9.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/types.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/x86/darwin.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/x86/darwin64.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/x86/ffi.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/x86/ffi64.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/x86/ffitarget.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/x86/freebsd.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/x86/sysv.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/x86/unix64.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/src/x86/win32.S +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/Makefile.am +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/Makefile.in +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/config/default.exp +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/lib/libffi-dg.exp +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/lib/target-libpath.exp +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/lib/wrapper.exp +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/call.exp +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn0.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn2.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn3.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn4.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn5.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_fn6.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/closure_stdcall.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_12byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_16byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_18byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_19byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_1_1byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_20byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_20byte1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_24byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_2byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_3_1byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_3byte1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_3byte2.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_4_1byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_4byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_5_1_byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_5byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_64byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_6_1_byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_6byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_7_1_byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_7byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_8byte.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_9byte1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_9byte2.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_double.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_float.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_longdouble.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_pointer.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_sint16.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_sint32.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_sint64.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_uint16.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_uint32.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_align_uint64.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_double.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_float.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_schar.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_sshort.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_sshortchar.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_uchar.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_ushort.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_multi_ushortchar.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_schar.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_sint.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_sshort.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_uchar.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_uint.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_ulonglong.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/cls_ushort.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/ffitest.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float2.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float3.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/float4.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/many.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/many_win32.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/negint.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct10.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct2.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct3.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct4.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct5.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct6.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct7.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct8.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/nested_struct9.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/problem1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/promotion.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/pyobjc-tc.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_dbl.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_dbl1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_dbl2.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_fl.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_fl1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_fl2.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_fl3.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_ldl.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_ll.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_ll1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_sc.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_sl.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_uc.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/return_ul.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/strlen.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/strlen_win32.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct1.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct2.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct3.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct4.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct5.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct6.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct7.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct8.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.call/struct9.c +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.special/ffitestcxx.h +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.special/special.exp +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.special/unwindtest.cc +0 -0
- data/ext/{libffi → ffi_c/libffi}/testsuite/libffi.special/unwindtest_ffi_call.cc +0 -0
- data/ext/{libffi → ffi_c/libffi}/texinfo.tex +0 -0
- data/ext/{rbffi.h → ffi_c/rbffi.h} +1 -8
- data/lib/ffi/autopointer.rb +7 -7
- data/lib/ffi/buffer.rb +0 -25
- data/lib/ffi/ffi.rb +1 -0
- data/lib/ffi/library.rb +103 -37
- data/lib/ffi/memorypointer.rb +25 -28
- data/lib/ffi/platform.rb +2 -2
- data/lib/ffi/pointer.rb +21 -7
- data/lib/ffi/struct.rb +161 -179
- data/lib/ffi/types.rb +3 -3
- data/lib/ffi/union.rb +17 -0
- data/nbproject/configurations.xml +98 -88
- data/samples/hello.rb +1 -2
- data/samples/sample_helper.rb +6 -0
- data/{specs → spec/ffi}/buffer_spec.rb +0 -0
- data/{specs → spec/ffi}/callback_spec.rb +114 -89
- data/{specs → spec/ffi}/errno_spec.rb +0 -0
- data/spec/ffi/library_spec.rb +144 -0
- data/{specs → spec/ffi}/managed_struct_spec.rb +12 -1
- data/{specs → spec/ffi}/number_spec.rb +34 -16
- data/{specs → spec/ffi}/pointer_spec.rb +46 -2
- data/{specs → spec/ffi}/rbx/attach_function_spec.rb +2 -1
- data/{specs → spec/ffi}/rbx/memory_pointer_spec.rb +19 -19
- data/{specs → spec/ffi}/rbx/spec_helper.rb +0 -0
- data/{specs → spec/ffi}/rbx/struct_spec.rb +0 -0
- data/spec/ffi/spec_helper.rb +13 -0
- data/{specs → spec/ffi}/string_spec.rb +8 -0
- data/spec/ffi/struct_spec.rb +453 -0
- data/{specs → spec/ffi}/typedef_spec.rb +3 -3
- data/spec/ffi/union_spec.rb +60 -0
- data/{specs → spec/ffi}/variadic_spec.rb +0 -0
- data/spec/spec.opts +4 -0
- metadata +356 -334
- data/README +0 -0
- data/ext/Buffer.c +0 -98
- data/ext/MemoryPointer.c +0 -99
- data/ext/NativeLibrary.c +0 -90
- data/ext/Types.c +0 -76
- data/ext/ffi.c +0 -64
- data/ext/ffi.mk +0 -24
- data/ext/libffi.mk +0 -10
- data/gen/Rakefile +0 -12
- data/specs/library_spec.rb +0 -55
- data/specs/spec_helper.rb +0 -9
- data/specs/struct_spec.rb +0 -223
@@ -19,17 +19,25 @@ static void autoptr_mark(AutoPointer* ptr);
|
|
19
19
|
static void autoptr_free(AutoPointer* ptr);
|
20
20
|
|
21
21
|
static VALUE
|
22
|
-
|
22
|
+
autoptr_allocate(VALUE klass)
|
23
23
|
{
|
24
24
|
AutoPointer* p;
|
25
|
-
|
26
|
-
|
25
|
+
VALUE obj = Data_Make_Struct(klass, AutoPointer, autoptr_mark, autoptr_free, p);
|
26
|
+
p->parent = Qnil;
|
27
|
+
return obj;
|
28
|
+
}
|
29
|
+
|
30
|
+
static VALUE
|
31
|
+
autoptr_set_parent(VALUE self, VALUE parent)
|
32
|
+
{
|
33
|
+
AutoPointer* p;
|
34
|
+
AbstractMemory* ptr = rb_FFI_AbstractMemory_cast(parent, rb_FFI_Pointer_class);
|
27
35
|
|
28
|
-
|
29
|
-
ptr = (AbstractMemory *) DATA_PTR(other);
|
36
|
+
Data_Get_Struct(self, AutoPointer, p);
|
30
37
|
p->memory = *ptr;
|
31
|
-
p->parent =
|
32
|
-
|
38
|
+
p->parent = parent;
|
39
|
+
|
40
|
+
return self;
|
33
41
|
}
|
34
42
|
|
35
43
|
static void
|
@@ -50,5 +58,6 @@ rb_FFI_AutoPointer_Init()
|
|
50
58
|
{
|
51
59
|
VALUE moduleFFI = rb_define_module("FFI");
|
52
60
|
rb_FFI_AutoPointer_class = classAutoPointer = rb_define_class_under(moduleFFI, "AutoPointer", rb_FFI_Pointer_class);
|
53
|
-
|
61
|
+
rb_define_alloc_func(classAutoPointer, autoptr_allocate);
|
62
|
+
rb_define_protected_method(classAutoPointer, "parent=", autoptr_set_parent, 1);
|
54
63
|
}
|
File without changes
|
data/ext/ffi_c/Buffer.c
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
#include <stdbool.h>
|
2
|
+
#include <stdint.h>
|
3
|
+
#include <limits.h>
|
4
|
+
#include <ruby.h>
|
5
|
+
#include "rbffi.h"
|
6
|
+
#include "AbstractMemory.h"
|
7
|
+
|
8
|
+
typedef struct Buffer {
|
9
|
+
AbstractMemory memory;
|
10
|
+
char* storage; /* start of malloc area */
|
11
|
+
int type_size;
|
12
|
+
VALUE parent;
|
13
|
+
} Buffer;
|
14
|
+
|
15
|
+
static VALUE buffer_allocate(VALUE klass);
|
16
|
+
static VALUE buffer_initialize(int argc, VALUE* argv, VALUE self);
|
17
|
+
static void buffer_release(Buffer* ptr);
|
18
|
+
static void buffer_mark(Buffer* ptr);
|
19
|
+
static VALUE buffer_free(VALUE self);
|
20
|
+
|
21
|
+
static VALUE classBuffer = Qnil;
|
22
|
+
#define BUFFER(obj) ((Buffer *) rb_FFI_AbstractMemory_cast((obj), classBuffer))
|
23
|
+
|
24
|
+
static VALUE
|
25
|
+
buffer_allocate(VALUE klass)
|
26
|
+
{
|
27
|
+
Buffer* buffer;
|
28
|
+
return Data_Make_Struct(klass, Buffer, buffer_mark, buffer_release, buffer);
|
29
|
+
}
|
30
|
+
|
31
|
+
static VALUE
|
32
|
+
buffer_initialize(int argc, VALUE* argv, VALUE self)
|
33
|
+
{
|
34
|
+
VALUE size = Qnil, count = Qnil, clear = Qnil;
|
35
|
+
Buffer* p;
|
36
|
+
unsigned long msize;
|
37
|
+
void* memory;
|
38
|
+
int nargs;
|
39
|
+
|
40
|
+
nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
|
41
|
+
msize = rb_FFI_type_size(size) * (nargs > 1 ? NUM2LONG(count) : 1);
|
42
|
+
memory = malloc(msize + 7);
|
43
|
+
if (memory == NULL) {
|
44
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", msize);
|
45
|
+
}
|
46
|
+
Data_Get_Struct(self, Buffer, p);
|
47
|
+
p->storage = memory;
|
48
|
+
p->memory.size = msize;
|
49
|
+
/* ensure the memory is aligned on at least a 8 byte boundary */
|
50
|
+
p->memory.address = (void *) (((uintptr_t) memory + 0x7) & (uintptr_t) ~0x7UL);
|
51
|
+
p->parent = Qnil;
|
52
|
+
if (nargs > 2 && RTEST(clear) && p->memory.size > 0) {
|
53
|
+
memset(p->memory.address, 0, p->memory.size);
|
54
|
+
}
|
55
|
+
if (rb_block_given_p()) {
|
56
|
+
return rb_rescue(rb_yield, self, buffer_free, self);
|
57
|
+
}
|
58
|
+
return self;
|
59
|
+
}
|
60
|
+
|
61
|
+
static VALUE
|
62
|
+
buffer_alloc_inout(int argc, VALUE* argv, VALUE klass)
|
63
|
+
{
|
64
|
+
return buffer_initialize(argc, argv, buffer_allocate(klass));
|
65
|
+
}
|
66
|
+
|
67
|
+
static VALUE
|
68
|
+
buffer_plus(VALUE self, VALUE offset)
|
69
|
+
{
|
70
|
+
Buffer* ptr = BUFFER(self);
|
71
|
+
Buffer* p;
|
72
|
+
VALUE retval;
|
73
|
+
long off = NUM2LONG(offset);
|
74
|
+
|
75
|
+
checkBounds(&ptr->memory, off, 1);
|
76
|
+
retval = Data_Make_Struct(classBuffer, Buffer, buffer_mark, buffer_release, p);
|
77
|
+
p->memory.address = ptr->memory.address + off;;
|
78
|
+
p->memory.size = ptr->memory.size - off;
|
79
|
+
p->parent = self;
|
80
|
+
return retval;
|
81
|
+
}
|
82
|
+
|
83
|
+
static VALUE
|
84
|
+
buffer_inspect(VALUE self)
|
85
|
+
{
|
86
|
+
char tmp[100];
|
87
|
+
snprintf(tmp, sizeof(tmp), "#<Buffer size=%ld>", BUFFER(self)->memory.size);
|
88
|
+
return rb_str_new2(tmp);
|
89
|
+
}
|
90
|
+
|
91
|
+
/* Only used to free the buffer if the yield in the initializer throws an exception */
|
92
|
+
static VALUE
|
93
|
+
buffer_free(VALUE self)
|
94
|
+
{
|
95
|
+
Buffer* ptr = BUFFER(self);
|
96
|
+
if (ptr->parent == Qnil && ptr->storage != NULL) {
|
97
|
+
free(ptr->storage);
|
98
|
+
ptr->storage = NULL;
|
99
|
+
}
|
100
|
+
return self;
|
101
|
+
}
|
102
|
+
|
103
|
+
static void
|
104
|
+
buffer_release(Buffer* ptr)
|
105
|
+
{
|
106
|
+
if (ptr->parent == Qnil && ptr->storage != NULL) {
|
107
|
+
free(ptr->storage);
|
108
|
+
ptr->storage = NULL;
|
109
|
+
}
|
110
|
+
xfree(ptr);
|
111
|
+
}
|
112
|
+
|
113
|
+
static void
|
114
|
+
buffer_mark(Buffer* ptr)
|
115
|
+
{
|
116
|
+
if (ptr->parent != Qnil) {
|
117
|
+
rb_gc_mark(ptr->parent);
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
void
|
122
|
+
rb_FFI_Buffer_Init()
|
123
|
+
{
|
124
|
+
VALUE moduleFFI = rb_define_module("FFI");
|
125
|
+
classBuffer = rb_define_class_under(moduleFFI, "Buffer", rb_FFI_AbstractMemory_class);
|
126
|
+
rb_define_alloc_func(classBuffer, buffer_allocate);
|
127
|
+
|
128
|
+
rb_define_singleton_method(classBuffer, "alloc_inout", buffer_alloc_inout, -1);
|
129
|
+
rb_define_singleton_method(classBuffer, "alloc_out", buffer_alloc_inout, -1);
|
130
|
+
rb_define_singleton_method(classBuffer, "alloc_in", buffer_alloc_inout, -1);
|
131
|
+
|
132
|
+
rb_define_method(classBuffer, "initialize", buffer_initialize, -1);
|
133
|
+
rb_define_method(classBuffer, "inspect", buffer_inspect, 0);
|
134
|
+
rb_define_method(classBuffer, "+", buffer_plus, 1);
|
135
|
+
}
|
136
|
+
|
@@ -1,6 +1,8 @@
|
|
1
1
|
#include <sys/param.h>
|
2
2
|
#include <sys/types.h>
|
3
|
-
#
|
3
|
+
#ifndef _WIN32
|
4
|
+
# include <sys/mman.h>
|
5
|
+
#endif
|
4
6
|
#include <ruby.h>
|
5
7
|
#include <ffi.h>
|
6
8
|
#include "AbstractMemory.h"
|
@@ -26,7 +28,7 @@ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
|
|
26
28
|
|
27
29
|
static VALUE classCallbackInfo = Qnil;
|
28
30
|
static VALUE classNativeCallback = Qnil;
|
29
|
-
static ID callID = Qnil;
|
31
|
+
static ID callID = Qnil, cbTableID = Qnil;
|
30
32
|
|
31
33
|
VALUE rb_FFI_CallbackInfo_class = Qnil;
|
32
34
|
|
@@ -55,7 +57,7 @@ CallbackInfo_new(VALUE klass, VALUE rbReturnType, VALUE rbParamTypes)
|
|
55
57
|
if (cbInfo->ffiReturnType == NULL) {
|
56
58
|
rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType);
|
57
59
|
}
|
58
|
-
#
|
60
|
+
#if defined(_WIN32) && defined(notyet)
|
59
61
|
cbInfo->abi = (flags & STDCALL) ? FFI_STDCALL : FFI_DEFAULT_ABI;
|
60
62
|
#else
|
61
63
|
cbInfo->abi = FFI_DEFAULT_ABI;
|
@@ -126,41 +128,41 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
|
|
126
128
|
for (i = 0; i < cbInfo->parameterCount; ++i) {
|
127
129
|
VALUE param;
|
128
130
|
switch (cbInfo->parameterTypes[i]) {
|
129
|
-
case
|
131
|
+
case NATIVE_INT8:
|
130
132
|
param = INT2NUM(*(int8_t *) parameters[i]);
|
131
133
|
break;
|
132
|
-
case
|
133
|
-
param = UINT2NUM(*(
|
134
|
+
case NATIVE_UINT8:
|
135
|
+
param = UINT2NUM(*(uint8_t *) parameters[i]);
|
134
136
|
break;
|
135
|
-
case
|
137
|
+
case NATIVE_INT16:
|
136
138
|
param = INT2NUM(*(int16_t *) parameters[i]);
|
137
139
|
break;
|
138
|
-
case
|
139
|
-
param = UINT2NUM(*(
|
140
|
+
case NATIVE_UINT16:
|
141
|
+
param = UINT2NUM(*(uint16_t *) parameters[i]);
|
140
142
|
break;
|
141
|
-
case
|
143
|
+
case NATIVE_INT32:
|
142
144
|
param = INT2NUM(*(int32_t *) parameters[i]);
|
143
145
|
break;
|
144
|
-
case
|
145
|
-
param = UINT2NUM(*(
|
146
|
+
case NATIVE_UINT32:
|
147
|
+
param = UINT2NUM(*(uint32_t *) parameters[i]);
|
146
148
|
break;
|
147
|
-
case
|
149
|
+
case NATIVE_INT64:
|
148
150
|
param = LL2NUM(*(int64_t *) parameters[i]);
|
149
151
|
break;
|
150
|
-
case
|
151
|
-
param = ULL2NUM(*(
|
152
|
+
case NATIVE_UINT64:
|
153
|
+
param = ULL2NUM(*(uint64_t *) parameters[i]);
|
152
154
|
break;
|
153
|
-
case
|
155
|
+
case NATIVE_FLOAT32:
|
154
156
|
param = rb_float_new(*(float *) parameters[i]);
|
155
157
|
break;
|
156
|
-
case
|
158
|
+
case NATIVE_FLOAT64:
|
157
159
|
param = rb_float_new(*(double *) parameters[i]);
|
158
160
|
break;
|
159
|
-
case
|
161
|
+
case NATIVE_STRING:
|
160
162
|
param = rb_tainted_str_new2(*(char **) parameters[i]);
|
161
163
|
break;
|
162
|
-
case
|
163
|
-
param = rb_FFI_Pointer_new(*(
|
164
|
+
case NATIVE_POINTER:
|
165
|
+
param = rb_FFI_Pointer_new(*(void **) parameters[i]);
|
164
166
|
break;
|
165
167
|
default:
|
166
168
|
param = Qnil;
|
@@ -172,30 +174,35 @@ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user
|
|
172
174
|
if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
|
173
175
|
memset(retval, 0, cbInfo->ffiReturnType->size);
|
174
176
|
} else switch (cbInfo->returnType) {
|
175
|
-
case
|
176
|
-
case
|
177
|
-
case
|
178
|
-
*((
|
177
|
+
case NATIVE_INT8:
|
178
|
+
case NATIVE_INT16:
|
179
|
+
case NATIVE_INT32:
|
180
|
+
*((ffi_sarg *) retval) = NUM2INT(rbReturnValue);
|
179
181
|
break;
|
180
|
-
case
|
181
|
-
case
|
182
|
-
case
|
183
|
-
*((
|
182
|
+
case NATIVE_UINT8:
|
183
|
+
case NATIVE_UINT16:
|
184
|
+
case NATIVE_UINT32:
|
185
|
+
*((ffi_arg *) retval) = NUM2UINT(rbReturnValue);
|
184
186
|
break;
|
185
|
-
case
|
187
|
+
case NATIVE_INT64:
|
186
188
|
*((int64_t *) retval) = NUM2LL(rbReturnValue);
|
187
189
|
break;
|
188
|
-
case
|
189
|
-
*((
|
190
|
+
case NATIVE_UINT64:
|
191
|
+
*((uint64_t *) retval) = NUM2ULL(rbReturnValue);
|
190
192
|
break;
|
191
|
-
case
|
193
|
+
case NATIVE_FLOAT32:
|
192
194
|
*((float *) retval) = (float) NUM2DBL(rbReturnValue);
|
193
195
|
break;
|
194
|
-
case
|
196
|
+
case NATIVE_FLOAT64:
|
195
197
|
*((double *) retval) = NUM2DBL(rbReturnValue);
|
196
198
|
break;
|
197
|
-
case
|
198
|
-
|
199
|
+
case NATIVE_POINTER:
|
200
|
+
if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rb_FFI_Pointer_class)) {
|
201
|
+
*((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
|
202
|
+
} else {
|
203
|
+
// Default to returning NULL if not a value pointer object. handles nil case as well
|
204
|
+
*((void **) retval) = NULL;
|
205
|
+
}
|
199
206
|
break;
|
200
207
|
default:
|
201
208
|
break;
|
@@ -228,6 +235,23 @@ rb_FFI_NativeCallback_new(VALUE rbCallbackInfo, VALUE rbProc)
|
|
228
235
|
return Data_Wrap_Struct(classNativeCallback, native_callback_mark, native_callback_free, closure);
|
229
236
|
}
|
230
237
|
|
238
|
+
VALUE
|
239
|
+
rb_FFI_NativeCallback_for_proc(VALUE proc, VALUE cbInfo)
|
240
|
+
{
|
241
|
+
VALUE callback;
|
242
|
+
VALUE cbTable = RTEST(rb_ivar_defined(proc, cbTableID)) ? rb_ivar_get(proc, cbTableID) : Qnil;
|
243
|
+
if (cbTable == Qnil) {
|
244
|
+
cbTable = rb_hash_new();
|
245
|
+
rb_ivar_set(proc, cbTableID, cbTable);
|
246
|
+
}
|
247
|
+
callback = rb_hash_aref(cbTable, cbInfo);
|
248
|
+
if (callback != Qnil) {
|
249
|
+
return callback;
|
250
|
+
}
|
251
|
+
callback = rb_FFI_NativeCallback_new(cbInfo, proc);
|
252
|
+
rb_hash_aset(cbTable, cbInfo, callback);
|
253
|
+
return callback;
|
254
|
+
}
|
231
255
|
#if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
|
232
256
|
/*
|
233
257
|
* versions of ffi_closure_alloc, ffi_closure_free and ffi_prep_closure_loc for older
|
@@ -275,4 +299,5 @@ rb_FFI_Callback_Init()
|
|
275
299
|
rb_define_singleton_method(classCallbackInfo, "new", CallbackInfo_new, 2);
|
276
300
|
classNativeCallback = rb_define_class_under(moduleFFI, "NativeCallback", rb_cObject);
|
277
301
|
callID = rb_intern("call");
|
302
|
+
cbTableID = rb_intern("@__ffi_callback_table__");
|
278
303
|
}
|
@@ -1,10 +1,3 @@
|
|
1
|
-
/*
|
2
|
-
* File: Callback.h
|
3
|
-
* Author: wayne
|
4
|
-
*
|
5
|
-
* Created on September 11, 2008, 10:01 AM
|
6
|
-
*/
|
7
|
-
|
8
1
|
#ifndef _CALLBACK_H
|
9
2
|
#define _CALLBACK_H
|
10
3
|
|
@@ -38,6 +31,7 @@ typedef struct {
|
|
38
31
|
|
39
32
|
extern VALUE rb_FFI_CallbackInfo_class;
|
40
33
|
extern VALUE rb_FFI_NativeCallback_new(VALUE, VALUE);
|
34
|
+
extern VALUE rb_FFI_NativeCallback_for_proc(VALUE proc, VALUE cbInfo);
|
41
35
|
|
42
36
|
#ifdef __cplusplus
|
43
37
|
}
|
@@ -1,12 +1,17 @@
|
|
1
|
+
#include <sys/param.h>
|
1
2
|
#include <sys/types.h>
|
3
|
+
#ifndef _WIN32
|
4
|
+
# include <sys/mman.h>
|
5
|
+
#endif
|
2
6
|
#include <stdio.h>
|
3
7
|
#include <stdint.h>
|
4
|
-
#include <
|
8
|
+
#include <stdbool.h>
|
9
|
+
#include <unistd.h>
|
5
10
|
#include <errno.h>
|
6
11
|
#include <ruby.h>
|
7
12
|
|
8
13
|
#include <ffi.h>
|
9
|
-
#
|
14
|
+
#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
|
10
15
|
# include <pthread.h>
|
11
16
|
#endif
|
12
17
|
#include "rbffi.h"
|
@@ -14,11 +19,23 @@
|
|
14
19
|
|
15
20
|
#include "AbstractMemory.h"
|
16
21
|
#include "Pointer.h"
|
22
|
+
#include "Struct.h"
|
17
23
|
#include "Platform.h"
|
18
24
|
#include "Callback.h"
|
19
25
|
#include "Types.h"
|
20
26
|
|
21
|
-
|
27
|
+
#if defined(__i386__) && !defined(_WIN32) && !defined(__WIN32__)
|
28
|
+
# define USE_RAW
|
29
|
+
#endif
|
30
|
+
#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
|
31
|
+
# define USE_PTHREAD_LOCAL
|
32
|
+
#endif
|
33
|
+
#define MAX_FIXED_ARITY (3)
|
34
|
+
|
35
|
+
typedef struct MethodHandle MethodHandle;
|
36
|
+
typedef struct Invoker Invoker;
|
37
|
+
|
38
|
+
struct Invoker {
|
22
39
|
VALUE library;
|
23
40
|
void* function;
|
24
41
|
ffi_cif cif;
|
@@ -30,11 +47,36 @@ typedef struct Invoker {
|
|
30
47
|
int callbackCount;
|
31
48
|
VALUE* callbackParameters;
|
32
49
|
ffi_abi abi;
|
33
|
-
|
50
|
+
MethodHandle* methodHandle;
|
51
|
+
};
|
52
|
+
#ifdef USE_RAW
|
53
|
+
# define METHOD_CLOSURE ffi_raw_closure
|
54
|
+
#else
|
55
|
+
# define METHOD_CLOSURE ffi_closure
|
56
|
+
#endif
|
57
|
+
typedef struct MethodHandlePool MethodHandlePool;
|
58
|
+
struct MethodHandle {
|
59
|
+
Invoker* invoker;
|
60
|
+
int arity;
|
61
|
+
METHOD_CLOSURE* closure;
|
62
|
+
void* code;
|
63
|
+
ffi_cif cif;
|
64
|
+
struct MethodHandlePool* pool;
|
65
|
+
MethodHandle* next;
|
66
|
+
};
|
67
|
+
#if !defined(_WIN32) && !defined(__WIN32__)
|
68
|
+
struct MethodHandlePool {
|
69
|
+
#ifdef HAVE_NATIVETHREAD
|
70
|
+
pthread_mutex_t mutex;
|
71
|
+
#endif
|
72
|
+
MethodHandle* list;
|
73
|
+
};
|
74
|
+
#endif /* _WIN32 */
|
34
75
|
typedef struct ThreadData {
|
35
76
|
int td_errno;
|
36
77
|
} ThreadData;
|
37
|
-
static VALUE
|
78
|
+
static VALUE invoker_allocate(VALUE klass);
|
79
|
+
static VALUE invoker_initialize(VALUE self, VALUE library, VALUE function, VALUE parameterTypes,
|
38
80
|
VALUE returnType, VALUE convention);
|
39
81
|
static void invoker_mark(Invoker *);
|
40
82
|
static void invoker_free(Invoker *);
|
@@ -42,20 +84,32 @@ static VALUE invoker_call(int argc, VALUE* argv, VALUE self);
|
|
42
84
|
static VALUE invoker_call0(VALUE self);
|
43
85
|
static VALUE invoker_arity(VALUE self);
|
44
86
|
static void* callback_param(VALUE proc, VALUE cbinfo);
|
87
|
+
#ifdef USE_RAW
|
88
|
+
static void attached_method_invoke(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data);
|
89
|
+
static void attached_method_vinvoke(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data);
|
90
|
+
#else
|
91
|
+
#ifndef _WIN32
|
92
|
+
static void attached_method_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data);
|
93
|
+
#endif /* _WIN32 */
|
94
|
+
static void attached_method_vinvoke(ffi_cif* cif, void* retval, void** parameters, void* user_data);
|
95
|
+
#endif
|
96
|
+
static MethodHandle* method_handle_alloc(int arity);
|
97
|
+
static void method_handle_free(MethodHandle *);
|
98
|
+
|
45
99
|
static inline ThreadData* thread_data_get(void);
|
100
|
+
|
101
|
+
#ifndef _WIN32
|
102
|
+
static int PageSize;
|
103
|
+
#endif
|
46
104
|
static VALUE classInvoker = Qnil, classVariadicInvoker = Qnil;
|
47
|
-
static ID
|
105
|
+
static ID to_ptr;
|
48
106
|
|
49
|
-
#
|
107
|
+
#if defined(USE_PTHREAD_LOCAL)
|
50
108
|
static pthread_key_t threadDataKey;
|
51
109
|
#endif
|
52
110
|
|
53
111
|
#define threadData (thread_data_get())
|
54
112
|
|
55
|
-
#if defined(__i386__)
|
56
|
-
# define USE_RAW
|
57
|
-
#endif
|
58
|
-
|
59
113
|
#ifdef USE_RAW
|
60
114
|
# ifndef __i386__
|
61
115
|
# error "RAW argument packing only supported on i386"
|
@@ -79,21 +133,26 @@ static pthread_key_t threadDataKey;
|
|
79
133
|
#endif /* USE_RAW */
|
80
134
|
|
81
135
|
#ifdef USE_RAW
|
82
|
-
# define ADJ(p, a) ((p) = (FFIStorage*) (((
|
136
|
+
# define ADJ(p, a) ((p) = (FFIStorage*) (((char *) p) + a##_ADJ))
|
83
137
|
#else
|
84
138
|
# define ADJ(p, a) (++(p))
|
85
139
|
#endif
|
86
140
|
|
141
|
+
static VALUE
|
142
|
+
invoker_allocate(VALUE klass)
|
143
|
+
{
|
144
|
+
Invoker *invoker;
|
145
|
+
return Data_Make_Struct(klass, Invoker, invoker_mark, invoker_free, invoker);
|
146
|
+
}
|
87
147
|
|
88
148
|
static VALUE
|
89
|
-
|
149
|
+
invoker_initialize(VALUE self, VALUE library, VALUE function, VALUE parameterTypes,
|
90
150
|
VALUE returnType, VALUE convention)
|
91
151
|
{
|
92
152
|
Invoker* invoker = NULL;
|
93
153
|
ffi_type* ffiReturnType;
|
94
154
|
ffi_abi abi;
|
95
155
|
ffi_status ffiStatus;
|
96
|
-
VALUE retval = Qnil;
|
97
156
|
int i;
|
98
157
|
|
99
158
|
Check_Type(parameterTypes, T_ARRAY);
|
@@ -101,10 +160,10 @@ invoker_new(VALUE klass, VALUE library, VALUE function, VALUE parameterTypes,
|
|
101
160
|
Check_Type(convention, T_STRING);
|
102
161
|
Check_Type(library, T_DATA);
|
103
162
|
Check_Type(function, T_DATA);
|
104
|
-
|
105
|
-
|
163
|
+
|
164
|
+
Data_Get_Struct(self, Invoker, invoker);
|
106
165
|
invoker->library = library;
|
107
|
-
invoker->function = (
|
166
|
+
invoker->function = rb_FFI_AbstractMemory_cast(function, rb_FFI_Pointer_class)->address;
|
108
167
|
invoker->paramCount = RARRAY_LEN(parameterTypes);
|
109
168
|
invoker->paramTypes = ALLOC_N(NativeType, invoker->paramCount);
|
110
169
|
invoker->ffiParamTypes = ALLOC_N(ffi_type *, invoker->paramCount);
|
@@ -115,7 +174,7 @@ invoker_new(VALUE klass, VALUE library, VALUE function, VALUE parameterTypes,
|
|
115
174
|
invoker->callbackParameters = REALLOC_N(invoker->callbackParameters, VALUE,
|
116
175
|
invoker->callbackCount + 1);
|
117
176
|
invoker->callbackParameters[invoker->callbackCount++] = entry;
|
118
|
-
invoker->paramTypes[i] =
|
177
|
+
invoker->paramTypes[i] = NATIVE_CALLBACK;
|
119
178
|
invoker->ffiParamTypes[i] = &ffi_type_pointer;
|
120
179
|
} else {
|
121
180
|
int paramType = FIX2INT(entry);
|
@@ -131,8 +190,8 @@ invoker_new(VALUE klass, VALUE library, VALUE function, VALUE parameterTypes,
|
|
131
190
|
if (ffiReturnType == NULL) {
|
132
191
|
rb_raise(rb_eArgError, "Invalid return type");
|
133
192
|
}
|
134
|
-
#
|
135
|
-
abi = strcmp(
|
193
|
+
#if defined(_WIN32) || defined(__WIN32__)
|
194
|
+
abi = strcmp(StringValueCStr(convention), "stdcall") == 0 ? FFI_STDCALL : FFI_DEFAULT_ABI;
|
136
195
|
#else
|
137
196
|
abi = FFI_DEFAULT_ABI;
|
138
197
|
#endif
|
@@ -148,8 +207,9 @@ invoker_new(VALUE klass, VALUE library, VALUE function, VALUE parameterTypes,
|
|
148
207
|
default:
|
149
208
|
rb_raise(rb_eArgError, "Unknown FFI error");
|
150
209
|
}
|
151
|
-
|
152
|
-
|
210
|
+
invoker->methodHandle = method_handle_alloc(invoker->callbackCount < 1 ? invoker->paramCount : -1);
|
211
|
+
invoker->methodHandle->invoker = invoker;
|
212
|
+
return self;
|
153
213
|
}
|
154
214
|
|
155
215
|
static VALUE
|
@@ -165,9 +225,9 @@ variadic_invoker_new(VALUE klass, VALUE library, VALUE function, VALUE returnTyp
|
|
165
225
|
|
166
226
|
retval = Data_Make_Struct(klass, Invoker, invoker_mark, invoker_free, invoker);
|
167
227
|
invoker->library = library;
|
168
|
-
invoker->function = (
|
169
|
-
#
|
170
|
-
invoker->abi = strcmp(
|
228
|
+
invoker->function = rb_FFI_AbstractMemory_cast(function, rb_FFI_Pointer_class)->address;
|
229
|
+
#if defined(_WIN32) || defined(__WIN32__)
|
230
|
+
invoker->abi = strcmp(StringValueCStr(convention), "stdcall") == 0 ? FFI_STDCALL : FFI_DEFAULT_ABI;
|
171
231
|
#else
|
172
232
|
invoker->abi = FFI_DEFAULT_ABI;
|
173
233
|
#endif
|
@@ -176,9 +236,201 @@ variadic_invoker_new(VALUE klass, VALUE library, VALUE function, VALUE returnTyp
|
|
176
236
|
return retval;
|
177
237
|
}
|
178
238
|
|
239
|
+
static ffi_type* methodHandleParamTypes[MAX_FIXED_ARITY + 2];
|
240
|
+
static ffi_type* methodHandleVarargParamTypes[]= {
|
241
|
+
&ffi_type_sint,
|
242
|
+
&ffi_type_pointer,
|
243
|
+
NULL,
|
244
|
+
};
|
245
|
+
|
246
|
+
#if defined(_WIN32) || defined(__WIN32__)
|
247
|
+
static MethodHandle*
|
248
|
+
method_handle_alloc(int arity)
|
249
|
+
{
|
250
|
+
char errmsg[1024];
|
251
|
+
ffi_type* ffiReturnType = (sizeof (VALUE) == sizeof (long))
|
252
|
+
? &ffi_type_ulong : &ffi_type_uint64;
|
253
|
+
int ffiParamCount, ffiStatus;
|
254
|
+
MethodHandle* method = NULL;
|
255
|
+
ffi_type** ffiParamTypes;
|
256
|
+
void (*fn)(ffi_cif* cif, void* retval, void** parameters, void* user_data);
|
257
|
+
|
258
|
+
ffiParamCount = 3;
|
259
|
+
ffiParamTypes = methodHandleVarargParamTypes;
|
260
|
+
fn = attached_method_vinvoke;
|
261
|
+
method = ALLOC_N(MethodHandle, 1);
|
262
|
+
memset(method, 0, sizeof(*method));
|
263
|
+
method->arity = -1;
|
264
|
+
ffiStatus = ffi_prep_cif(&method->cif, FFI_DEFAULT_ABI, ffiParamCount,
|
265
|
+
ffiReturnType, ffiParamTypes);
|
266
|
+
if (ffiStatus != FFI_OK) {
|
267
|
+
snprintf(errmsg, sizeof (errmsg), "ffi_prep_cif failed. status=%#x", ffiStatus);
|
268
|
+
goto error;
|
269
|
+
}
|
270
|
+
method->closure = ffi_closure_alloc(sizeof(*method->closure), &method->code);
|
271
|
+
if (method->closure == NULL) {
|
272
|
+
snprintf(errmsg, sizeof(errmsg), "ffi_closure_alloc failed");
|
273
|
+
goto error;
|
274
|
+
}
|
275
|
+
ffiStatus = ffi_prep_closure_loc(method->closure, &method->cif, fn, method, method->code);
|
276
|
+
if (ffiStatus != FFI_OK) {
|
277
|
+
snprintf(errmsg, sizeof (errmsg), "ffi_prep_closure failed. status=%#x", ffiStatus);
|
278
|
+
goto error;
|
279
|
+
}
|
280
|
+
return method;
|
281
|
+
error:
|
282
|
+
if (method != NULL) {
|
283
|
+
if (method->closure != NULL) {
|
284
|
+
ffi_closure_free(method->closure);
|
285
|
+
}
|
286
|
+
xfree(method);
|
287
|
+
}
|
288
|
+
rb_raise(rb_eRuntimeError, "%s", errmsg);
|
289
|
+
}
|
290
|
+
static void
|
291
|
+
method_handle_free(MethodHandle* method)
|
292
|
+
{
|
293
|
+
if (method->closure != NULL) {
|
294
|
+
ffi_closure_free(method->closure);
|
295
|
+
}
|
296
|
+
xfree(method);
|
297
|
+
}
|
298
|
+
#else
|
299
|
+
static MethodHandlePool methodHandlePool[MAX_FIXED_ARITY + 1], defaultMethodHandlePool;
|
300
|
+
|
301
|
+
#if defined(HAVE_NATIVETHREAD) && !defined(_WIN32)
|
302
|
+
# define pool_lock(p) pthread_mutex_lock(&(p)->mutex)
|
303
|
+
# define pool_unlock(p) pthread_mutex_unlock(&(p)->mutex)
|
304
|
+
#else
|
305
|
+
# define pool_lock(p)
|
306
|
+
# define pool_unlock(p)
|
307
|
+
#endif
|
308
|
+
static MethodHandle*
|
309
|
+
method_handle_alloc(int arity)
|
310
|
+
{
|
311
|
+
MethodHandle* method, *list = NULL;
|
312
|
+
MethodHandlePool* pool;
|
313
|
+
ffi_type** ffiParamTypes;
|
314
|
+
ffi_type* ffiReturnType;
|
315
|
+
caddr_t page;
|
316
|
+
int ffiParamCount, ffiStatus;
|
317
|
+
int nclosures, closureSize, methodArity;
|
318
|
+
int i;
|
319
|
+
#ifdef USE_RAW
|
320
|
+
void (*fn)(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data);
|
321
|
+
#else
|
322
|
+
void (*fn)(ffi_cif* cif, void* retval, void** parameters, void* user_data);
|
323
|
+
#endif
|
324
|
+
|
325
|
+
|
326
|
+
pool = (arity >= 0 && arity <= MAX_FIXED_ARITY) ? &methodHandlePool[arity] : &defaultMethodHandlePool;
|
327
|
+
pool_lock(pool);
|
328
|
+
if (pool->list != NULL) {
|
329
|
+
method = pool->list;
|
330
|
+
pool->list = pool->list->next;
|
331
|
+
pool_unlock(pool);
|
332
|
+
return method;
|
333
|
+
}
|
334
|
+
ffiReturnType = (sizeof (VALUE) == sizeof (long))
|
335
|
+
? &ffi_type_ulong : &ffi_type_uint64;
|
336
|
+
closureSize = roundup(sizeof(METHOD_CLOSURE), 8);
|
337
|
+
nclosures = PageSize / closureSize;
|
338
|
+
page = mmap(NULL, PageSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
339
|
+
if (page == (caddr_t) -1) {
|
340
|
+
pool_unlock(pool);
|
341
|
+
rb_raise(rb_eRuntimeError, "mmap failed. errno=%d (%s)", errno, strerror(errno));
|
342
|
+
}
|
343
|
+
|
344
|
+
/* figure out whichh function to bounce the execution through */
|
345
|
+
if (arity >= 0 && arity <= MAX_FIXED_ARITY) {
|
346
|
+
ffiParamCount = arity + 1;
|
347
|
+
ffiParamTypes = methodHandleParamTypes;
|
348
|
+
fn = attached_method_invoke;
|
349
|
+
methodArity = arity;
|
350
|
+
} else {
|
351
|
+
ffiParamCount = 3;
|
352
|
+
ffiParamTypes = methodHandleVarargParamTypes;
|
353
|
+
fn = attached_method_vinvoke;
|
354
|
+
methodArity = -1;
|
355
|
+
}
|
356
|
+
|
357
|
+
for (i = 0; i < nclosures; ++i) {
|
358
|
+
char errmsg[256];
|
359
|
+
method = calloc(1, sizeof(MethodHandle));
|
360
|
+
if (method == NULL) {
|
361
|
+
snprintf(errmsg, sizeof(errmsg), "malloc failed: %s", strerror(errno));
|
362
|
+
goto error;
|
363
|
+
}
|
364
|
+
method->next = list;
|
365
|
+
list = method;
|
366
|
+
method->pool = pool;
|
367
|
+
method->code = method->closure = (METHOD_CLOSURE *) (page + (i * closureSize));
|
368
|
+
|
369
|
+
ffiStatus = ffi_prep_cif(&method->cif, FFI_DEFAULT_ABI, ffiParamCount,
|
370
|
+
ffiReturnType, ffiParamTypes);
|
371
|
+
if (ffiStatus != FFI_OK) {
|
372
|
+
snprintf(errmsg, sizeof(errmsg), "ffi_prep_cif failed. status=%#x", ffiStatus);
|
373
|
+
goto error;
|
374
|
+
}
|
375
|
+
|
376
|
+
#ifdef USE_RAW
|
377
|
+
ffiStatus = ffi_prep_raw_closure(method->closure, &method->cif, fn, method);
|
378
|
+
#else
|
379
|
+
ffiStatus = ffi_prep_closure(method->closure, &method->cif, fn, method);
|
380
|
+
#endif
|
381
|
+
if (ffiStatus != FFI_OK) {
|
382
|
+
snprintf(errmsg, sizeof(errmsg), "ffi_prep_closure failed. status=%#x", ffiStatus);
|
383
|
+
goto error;
|
384
|
+
}
|
385
|
+
method->arity = methodArity;
|
386
|
+
continue;
|
387
|
+
error:
|
388
|
+
while (list != NULL) {
|
389
|
+
method = list;
|
390
|
+
list = list->next;
|
391
|
+
free(method);
|
392
|
+
}
|
393
|
+
munmap(page, PageSize);
|
394
|
+
pool_unlock(pool);
|
395
|
+
rb_raise(rb_eRuntimeError, "%s", errmsg);
|
396
|
+
}
|
397
|
+
mprotect(page, PageSize, PROT_READ | PROT_EXEC);
|
398
|
+
|
399
|
+
/* take the first member of the list for this handle */
|
400
|
+
method = list;
|
401
|
+
list = list->next;
|
402
|
+
|
403
|
+
/* now add the new block of MethodHandles to the pool */
|
404
|
+
if (list != NULL) {
|
405
|
+
list->next = pool->list;
|
406
|
+
pool->list = list;
|
407
|
+
}
|
408
|
+
pool_unlock(pool);
|
409
|
+
return method;
|
410
|
+
}
|
411
|
+
static void
|
412
|
+
method_handle_free(MethodHandle* method)
|
413
|
+
{
|
414
|
+
MethodHandlePool* pool = method->pool;
|
415
|
+
pool_lock(pool);
|
416
|
+
method->next = pool->list;
|
417
|
+
pool->list = method;
|
418
|
+
pool_unlock(pool);
|
419
|
+
}
|
420
|
+
#endif /* _WIN32 */
|
421
|
+
|
179
422
|
typedef union {
|
180
|
-
|
181
|
-
|
423
|
+
#if BYTE_ORDER == LITTLE_ENDIAN
|
424
|
+
signed int s8, s16, s32;
|
425
|
+
unsigned int u8, u16, u32;
|
426
|
+
#else
|
427
|
+
signed char s8;
|
428
|
+
unsigned char u8;
|
429
|
+
signed short s16;
|
430
|
+
unsigned short u16;
|
431
|
+
signed int s32;
|
432
|
+
unsigned int u32;
|
433
|
+
#endif
|
182
434
|
signed long long i64;
|
183
435
|
unsigned long long u64;
|
184
436
|
void* ptr;
|
@@ -250,32 +502,32 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
|
|
250
502
|
ffiValues[i] = param;
|
251
503
|
|
252
504
|
switch (paramTypes[i]) {
|
253
|
-
case
|
254
|
-
param->
|
505
|
+
case NATIVE_INT8:
|
506
|
+
param->s8 = getSignedInt(argv[argidx++], type, -128, 127, "char");
|
255
507
|
ADJ(param, INT8);
|
256
508
|
break;
|
257
|
-
case
|
258
|
-
param->
|
509
|
+
case NATIVE_INT16:
|
510
|
+
param->s16 = getSignedInt(argv[argidx++], type, -0x8000, 0x7fff, "short");
|
259
511
|
ADJ(param, INT16);
|
260
512
|
break;
|
261
|
-
case
|
262
|
-
param->
|
513
|
+
case NATIVE_INT32:
|
514
|
+
param->s32 = getSignedInt(argv[argidx++], type, -0x80000000, 0x7fffffff, "int");
|
263
515
|
ADJ(param, INT32);
|
264
516
|
break;
|
265
|
-
case
|
266
|
-
param->
|
517
|
+
case NATIVE_UINT8:
|
518
|
+
param->u8 = getUnsignedInt(argv[argidx++], type, 0xff, "unsigned char");
|
267
519
|
ADJ(param, INT8);
|
268
520
|
break;
|
269
|
-
case
|
270
|
-
param->
|
521
|
+
case NATIVE_UINT16:
|
522
|
+
param->u16 = getUnsignedInt(argv[argidx++], type, 0xffff, "unsigned short");
|
271
523
|
ADJ(param, INT16);
|
272
524
|
break;
|
273
|
-
case
|
525
|
+
case NATIVE_UINT32:
|
274
526
|
/* Special handling/checking for unsigned 32 bit integers */
|
275
|
-
param->
|
527
|
+
param->u32 = getUnsignedInt32(argv[argidx++], type);
|
276
528
|
ADJ(param, INT32);
|
277
529
|
break;
|
278
|
-
case
|
530
|
+
case NATIVE_INT64:
|
279
531
|
if (type != T_FIXNUM && type != T_BIGNUM) {
|
280
532
|
rb_raise(rb_eTypeError, "Expected an Integer parameter");
|
281
533
|
}
|
@@ -283,15 +535,15 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
|
|
283
535
|
ADJ(param, INT64);
|
284
536
|
++argidx;
|
285
537
|
break;
|
286
|
-
case
|
538
|
+
case NATIVE_UINT64:
|
287
539
|
if (type != T_FIXNUM && type != T_BIGNUM) {
|
288
540
|
rb_raise(rb_eTypeError, "Expected an Integer parameter");
|
289
541
|
}
|
290
|
-
param->
|
542
|
+
param->u64 = NUM2ULL(argv[argidx]);
|
291
543
|
ADJ(param, INT64);
|
292
544
|
++argidx;
|
293
545
|
break;
|
294
|
-
case
|
546
|
+
case NATIVE_FLOAT32:
|
295
547
|
if (type != T_FLOAT && type != T_FIXNUM) {
|
296
548
|
rb_raise(rb_eTypeError, "Expected a Float parameter");
|
297
549
|
}
|
@@ -299,7 +551,7 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
|
|
299
551
|
ADJ(param, FLOAT32);
|
300
552
|
++argidx;
|
301
553
|
break;
|
302
|
-
case
|
554
|
+
case NATIVE_FLOAT64:
|
303
555
|
if (type != T_FLOAT && type != T_FIXNUM) {
|
304
556
|
rb_raise(rb_eTypeError, "Expected a Float parameter");
|
305
557
|
}
|
@@ -307,12 +559,12 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
|
|
307
559
|
ADJ(param, FLOAT64);
|
308
560
|
++argidx;
|
309
561
|
break;
|
310
|
-
case
|
562
|
+
case NATIVE_STRING:
|
311
563
|
if (type == T_STRING) {
|
312
564
|
if (rb_safe_level() >= 1 && OBJ_TAINTED(argv[argidx])) {
|
313
565
|
rb_raise(rb_eSecurityError, "Unsafe string parameter");
|
314
566
|
}
|
315
|
-
param->ptr =
|
567
|
+
param->ptr = StringValueCStr(argv[argidx]);
|
316
568
|
} else if (type == T_NIL) {
|
317
569
|
param->ptr = NULL;
|
318
570
|
} else {
|
@@ -321,12 +573,15 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
|
|
321
573
|
ADJ(param, ADDRESS);
|
322
574
|
++argidx;
|
323
575
|
break;
|
324
|
-
case
|
325
|
-
case
|
326
|
-
case
|
327
|
-
case
|
328
|
-
if (rb_obj_is_kind_of(argv[argidx], rb_FFI_AbstractMemory_class)
|
576
|
+
case NATIVE_POINTER:
|
577
|
+
case NATIVE_BUFFER_IN:
|
578
|
+
case NATIVE_BUFFER_OUT:
|
579
|
+
case NATIVE_BUFFER_INOUT:
|
580
|
+
if (type == T_DATA && rb_obj_is_kind_of(argv[argidx], rb_FFI_AbstractMemory_class)) {
|
329
581
|
param->ptr = ((AbstractMemory *) DATA_PTR(argv[argidx]))->address;
|
582
|
+
} else if (type == T_DATA && rb_obj_is_kind_of(argv[argidx], rb_FFI_Struct_class)) {
|
583
|
+
AbstractMemory* memory = ((Struct *) DATA_PTR(argv[argidx]))->pointer;
|
584
|
+
param->ptr = memory != NULL ? memory->address : NULL;
|
330
585
|
} else if (type == T_STRING) {
|
331
586
|
if (rb_safe_level() >= 1 && OBJ_TAINTED(argv[argidx])) {
|
332
587
|
rb_raise(rb_eSecurityError, "Unsafe string parameter");
|
@@ -336,7 +591,7 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
|
|
336
591
|
param->ptr = NULL;
|
337
592
|
} else if (rb_respond_to(argv[argidx], to_ptr)) {
|
338
593
|
VALUE ptr = rb_funcall2(argv[argidx], to_ptr, 0, NULL);
|
339
|
-
if (rb_obj_is_kind_of(ptr,
|
594
|
+
if (rb_obj_is_kind_of(ptr, rb_FFI_AbstractMemory_class) && TYPE(ptr) == T_DATA) {
|
340
595
|
param->ptr = ((AbstractMemory *) DATA_PTR(ptr))->address;
|
341
596
|
} else {
|
342
597
|
rb_raise(rb_eArgError, "to_ptr returned an invalid pointer");
|
@@ -348,7 +603,7 @@ ffi_arg_setup(const Invoker* invoker, int argc, VALUE* argv, NativeType* paramTy
|
|
348
603
|
ADJ(param, ADDRESS);
|
349
604
|
++argidx;
|
350
605
|
break;
|
351
|
-
case
|
606
|
+
case NATIVE_CALLBACK:
|
352
607
|
if (callbackProc != Qnil) {
|
353
608
|
param->ptr = callback_param(callbackProc, invoker->callbackParameters[cbidx++]);
|
354
609
|
} else {
|
@@ -371,7 +626,11 @@ ffi_invoke(ffi_cif* cif, void* function, NativeType returnType, void** ffiValues
|
|
371
626
|
#else
|
372
627
|
ffi_call(cif, FFI_FN(function), &retval, ffiValues);
|
373
628
|
#endif
|
629
|
+
#if defined(_WIN32) || defined(__WIN32__)
|
630
|
+
threadData->td_errno = GetLastError();
|
631
|
+
#else
|
374
632
|
threadData->td_errno = errno;
|
633
|
+
#endif
|
375
634
|
return rb_FFI_NativeValueToRuby(returnType, &retval);
|
376
635
|
}
|
377
636
|
static VALUE
|
@@ -386,6 +645,18 @@ invoker_call(int argc, VALUE* argv, VALUE self)
|
|
386
645
|
return ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
|
387
646
|
}
|
388
647
|
|
648
|
+
static inline VALUE
|
649
|
+
invoker_callN(VALUE self, int argc, VALUE* argv)
|
650
|
+
{
|
651
|
+
Invoker* invoker;
|
652
|
+
FFIStorage params[3];
|
653
|
+
void* ffiValues[3];
|
654
|
+
|
655
|
+
Data_Get_Struct(self, Invoker, invoker);
|
656
|
+
ffi_arg_setup(invoker, argc, argv, invoker->paramTypes, params, ffiValues);
|
657
|
+
return ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
|
658
|
+
}
|
659
|
+
|
389
660
|
static VALUE
|
390
661
|
invoker_call0(VALUE self)
|
391
662
|
{
|
@@ -400,41 +671,102 @@ invoker_call0(VALUE self)
|
|
400
671
|
static VALUE
|
401
672
|
invoker_call1(VALUE self, VALUE arg1)
|
402
673
|
{
|
403
|
-
|
404
|
-
void* ffiValues[1];
|
405
|
-
FFIStorage params[1];
|
406
|
-
|
407
|
-
Data_Get_Struct(self, Invoker, invoker);
|
408
|
-
ffi_arg_setup(invoker, 1, &arg1, invoker->paramTypes, params, ffiValues);
|
409
|
-
return ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
|
674
|
+
return invoker_callN(self, 1, &arg1);
|
410
675
|
}
|
411
676
|
|
412
677
|
static VALUE
|
413
678
|
invoker_call2(VALUE self, VALUE arg1, VALUE arg2)
|
414
679
|
{
|
415
|
-
Invoker* invoker;
|
416
|
-
void* ffiValues[2];
|
417
|
-
FFIStorage params[2];
|
418
680
|
VALUE argv[] = { arg1, arg2 };
|
419
|
-
|
420
|
-
Data_Get_Struct(self, Invoker, invoker);
|
421
|
-
ffi_arg_setup(invoker, 2, argv, invoker->paramTypes, params, ffiValues);
|
422
|
-
return ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
|
681
|
+
return invoker_callN(self, 2, argv);
|
423
682
|
}
|
424
683
|
|
425
684
|
static VALUE
|
426
685
|
invoker_call3(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3)
|
427
686
|
{
|
428
|
-
Invoker* invoker;
|
429
|
-
void* ffiValues[3];
|
430
|
-
FFIStorage params[3];
|
431
687
|
VALUE argv[] = { arg1, arg2, arg3 };
|
688
|
+
return invoker_callN(self, 3, argv);
|
689
|
+
}
|
432
690
|
|
433
|
-
|
434
|
-
|
435
|
-
|
691
|
+
#ifdef USE_RAW
|
692
|
+
static void
|
693
|
+
attached_method_invoke(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data)
|
694
|
+
{
|
695
|
+
MethodHandle* handle = (MethodHandle *) user_data;
|
696
|
+
Invoker* invoker = handle->invoker;
|
697
|
+
void* ffiValues[MAX_FIXED_ARITY];
|
698
|
+
FFIStorage params[MAX_FIXED_ARITY];
|
699
|
+
|
700
|
+
if (invoker->paramCount > 0) {
|
701
|
+
ffi_arg_setup(invoker, invoker->paramCount, (VALUE *)¶meters[1],
|
702
|
+
invoker->paramTypes, params, ffiValues);
|
703
|
+
}
|
704
|
+
*((VALUE *) retval) = ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
|
705
|
+
}
|
706
|
+
|
707
|
+
static void
|
708
|
+
attached_method_vinvoke(ffi_cif* cif, void* retval, ffi_raw* parameters, void* user_data)
|
709
|
+
{
|
710
|
+
MethodHandle* handle = (MethodHandle *) user_data;
|
711
|
+
Invoker* invoker = handle->invoker;
|
712
|
+
void** ffiValues = ALLOCA_N(void *, invoker->paramCount);
|
713
|
+
FFIStorage* params = ALLOCA_N(FFIStorage, invoker->paramCount);
|
714
|
+
int argc = parameters[0].sint;
|
715
|
+
VALUE* argv = *(VALUE **) ¶meters[1];
|
716
|
+
|
717
|
+
ffi_arg_setup(invoker, argc, argv, invoker->paramTypes, params, ffiValues);
|
718
|
+
*((VALUE *) retval) = ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
|
719
|
+
}
|
720
|
+
|
721
|
+
#else
|
722
|
+
#ifndef _WIN32
|
723
|
+
static void
|
724
|
+
attached_method_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
|
725
|
+
{
|
726
|
+
MethodHandle* handle = (MethodHandle *) user_data;
|
727
|
+
Invoker* invoker = handle->invoker;
|
728
|
+
void* ffiValues[MAX_FIXED_ARITY];
|
729
|
+
FFIStorage params[MAX_FIXED_ARITY];
|
730
|
+
VALUE argv[MAX_FIXED_ARITY];
|
731
|
+
int i;
|
732
|
+
//printf("Attached method invoke nargs=%d paramCount=%d\n", cif->nargs, invoker->paramCount); fflush(stdout);
|
733
|
+
for (i = 0; i < invoker->paramCount; ++i) {
|
734
|
+
memcpy(&argv[i], parameters[i + 1], sizeof(argv[i]));
|
735
|
+
}
|
736
|
+
if (invoker->paramCount > 0) {
|
737
|
+
ffi_arg_setup(invoker, invoker->paramCount, argv, invoker->paramTypes, params, ffiValues);
|
738
|
+
}
|
739
|
+
*((VALUE *) retval) = ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
|
436
740
|
}
|
741
|
+
#endif /* _WIN32 */
|
742
|
+
static void
|
743
|
+
attached_method_vinvoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
|
744
|
+
{
|
745
|
+
MethodHandle* handle = (MethodHandle *) user_data;
|
746
|
+
Invoker* invoker = handle->invoker;
|
747
|
+
void** ffiValues = ALLOCA_N(void *, invoker->paramCount);
|
748
|
+
FFIStorage* params = ALLOCA_N(FFIStorage, invoker->paramCount);
|
749
|
+
int argc = *(int *) parameters[0];
|
750
|
+
VALUE* argv = *(VALUE **) parameters[1];
|
437
751
|
|
752
|
+
ffi_arg_setup(invoker, argc, argv, invoker->paramTypes, params, ffiValues);
|
753
|
+
*((VALUE *) retval) = ffi_invoke(&invoker->cif, invoker->function, invoker->returnType, ffiValues);
|
754
|
+
}
|
755
|
+
#endif
|
756
|
+
static VALUE
|
757
|
+
invoker_attach(VALUE self, VALUE module, VALUE name)
|
758
|
+
{
|
759
|
+
Invoker* invoker;
|
760
|
+
MethodHandle* handle;
|
761
|
+
char var[1024];
|
762
|
+
Data_Get_Struct(self, Invoker, invoker);
|
763
|
+
handle = invoker->methodHandle;
|
764
|
+
rb_define_module_function(module, StringValuePtr(name),
|
765
|
+
handle->code, handle->arity);
|
766
|
+
snprintf(var, sizeof(var), "@@%s", StringValueCStr(name));
|
767
|
+
rb_cv_set(module, var, self);
|
768
|
+
return self;
|
769
|
+
}
|
438
770
|
static VALUE
|
439
771
|
invoker_arity(VALUE self)
|
440
772
|
{
|
@@ -470,6 +802,9 @@ invoker_free(Invoker *invoker)
|
|
470
802
|
xfree(invoker->callbackParameters);
|
471
803
|
invoker->callbackParameters = NULL;
|
472
804
|
}
|
805
|
+
if (invoker->methodHandle != NULL) {
|
806
|
+
method_handle_free(invoker->methodHandle);
|
807
|
+
}
|
473
808
|
xfree(invoker);
|
474
809
|
}
|
475
810
|
}
|
@@ -503,18 +838,18 @@ variadic_invoker_call(VALUE self, VALUE parameterTypes, VALUE parameterValues)
|
|
503
838
|
VALUE entry = rb_ary_entry(parameterTypes, i);
|
504
839
|
int paramType = FIX2INT(entry);
|
505
840
|
switch (paramType) {
|
506
|
-
case
|
507
|
-
case
|
508
|
-
case
|
509
|
-
paramType =
|
841
|
+
case NATIVE_INT8:
|
842
|
+
case NATIVE_INT16:
|
843
|
+
case NATIVE_INT32:
|
844
|
+
paramType = NATIVE_INT32;
|
510
845
|
break;
|
511
|
-
case
|
512
|
-
case
|
513
|
-
case
|
514
|
-
paramType =
|
846
|
+
case NATIVE_UINT8:
|
847
|
+
case NATIVE_UINT16:
|
848
|
+
case NATIVE_UINT32:
|
849
|
+
paramType = NATIVE_UINT32;
|
515
850
|
break;
|
516
|
-
case
|
517
|
-
paramType =
|
851
|
+
case NATIVE_FLOAT32:
|
852
|
+
paramType = NATIVE_FLOAT64;
|
518
853
|
break;
|
519
854
|
}
|
520
855
|
paramTypes[i] = paramType;
|
@@ -547,21 +882,15 @@ variadic_invoker_call(VALUE self, VALUE parameterTypes, VALUE parameterValues)
|
|
547
882
|
static void*
|
548
883
|
callback_param(VALUE proc, VALUE cbInfo)
|
549
884
|
{
|
550
|
-
VALUE callback;
|
551
|
-
|
552
|
-
|
553
|
-
cbTable = rb_hash_new();
|
554
|
-
rb_ivar_set(proc, cbTableID, cbTable);
|
885
|
+
VALUE callback ;
|
886
|
+
if (proc == Qnil) {
|
887
|
+
return NULL ;
|
555
888
|
}
|
556
|
-
callback =
|
557
|
-
if (callback != Qnil) {
|
558
|
-
return ((NativeCallback *) DATA_PTR(callback))->code;
|
559
|
-
}
|
560
|
-
callback = rb_FFI_NativeCallback_new(cbInfo, proc);
|
561
|
-
rb_hash_aset(cbTable, cbInfo, callback);
|
889
|
+
callback = rb_FFI_NativeCallback_for_proc(proc, cbInfo);
|
562
890
|
return ((NativeCallback *) DATA_PTR(callback))->code;
|
563
891
|
}
|
564
|
-
|
892
|
+
|
893
|
+
#if defined(USE_PTHREAD_LOCAL)
|
565
894
|
static ThreadData*
|
566
895
|
thread_data_init()
|
567
896
|
{
|
@@ -570,6 +899,7 @@ thread_data_init()
|
|
570
899
|
pthread_setspecific(threadDataKey, td);
|
571
900
|
return td;
|
572
901
|
}
|
902
|
+
|
573
903
|
static inline ThreadData*
|
574
904
|
thread_data_get()
|
575
905
|
{
|
@@ -582,13 +912,31 @@ thread_data_free(void *ptr)
|
|
582
912
|
{
|
583
913
|
xfree(ptr);
|
584
914
|
}
|
585
|
-
|
586
|
-
|
915
|
+
|
916
|
+
#else
|
917
|
+
static ID thread_data_id;
|
918
|
+
|
919
|
+
static ThreadData*
|
920
|
+
thread_data_init()
|
921
|
+
{
|
922
|
+
ThreadData* td;
|
923
|
+
VALUE obj;
|
924
|
+
obj = Data_Make_Struct(rb_cObject, ThreadData, NULL, -1, td);
|
925
|
+
rb_thread_local_aset(rb_thread_current(), thread_data_id, obj);
|
926
|
+
return td;
|
927
|
+
}
|
928
|
+
|
587
929
|
static inline ThreadData*
|
588
930
|
thread_data_get()
|
589
931
|
{
|
590
|
-
|
932
|
+
VALUE obj = rb_thread_local_aref(rb_thread_current(), thread_data_id);
|
933
|
+
|
934
|
+
if (obj != Qnil && TYPE(obj) == T_DATA) {
|
935
|
+
return (ThreadData *) DATA_PTR(obj);
|
936
|
+
}
|
937
|
+
return thread_data_init();
|
591
938
|
}
|
939
|
+
|
592
940
|
#endif
|
593
941
|
static VALUE
|
594
942
|
get_last_error(VALUE self)
|
@@ -604,25 +952,47 @@ set_last_error(VALUE self, VALUE error)
|
|
604
952
|
void
|
605
953
|
rb_FFI_Invoker_Init()
|
606
954
|
{
|
955
|
+
ffi_type* ffiValueType;
|
956
|
+
int i;
|
607
957
|
VALUE moduleFFI = rb_define_module("FFI");
|
608
958
|
VALUE moduleError = rb_define_module_under(moduleFFI, "LastError");
|
609
959
|
classInvoker = rb_define_class_under(moduleFFI, "Invoker", rb_cObject);
|
610
|
-
|
960
|
+
rb_define_alloc_func(classInvoker, invoker_allocate);
|
961
|
+
rb_define_method(classInvoker, "initialize", invoker_initialize, 5);
|
611
962
|
rb_define_method(classInvoker, "call", invoker_call, -1);
|
612
963
|
rb_define_method(classInvoker, "call0", invoker_call0, 0);
|
613
964
|
rb_define_method(classInvoker, "call1", invoker_call1, 1);
|
614
965
|
rb_define_method(classInvoker, "call2", invoker_call2, 2);
|
615
966
|
rb_define_method(classInvoker, "call3", invoker_call3, 3);
|
616
967
|
rb_define_method(classInvoker, "arity", invoker_arity, 0);
|
968
|
+
rb_define_method(classInvoker, "attach", invoker_attach, 2);
|
617
969
|
classVariadicInvoker = rb_define_class_under(moduleFFI, "VariadicInvoker", rb_cObject);
|
618
970
|
rb_define_singleton_method(classVariadicInvoker, "__new", variadic_invoker_new, 4);
|
619
971
|
rb_define_method(classVariadicInvoker, "invoke", variadic_invoker_call, 2);
|
620
|
-
cbTableID = rb_intern("__ffi_callback_table__");
|
621
972
|
to_ptr = rb_intern("to_ptr");
|
622
973
|
|
623
974
|
rb_define_module_function(moduleError, "error", get_last_error, 0);
|
624
975
|
rb_define_module_function(moduleError, "error=", set_last_error, 1);
|
625
|
-
|
976
|
+
|
977
|
+
ffiValueType = (sizeof (VALUE) == sizeof (long))
|
978
|
+
? &ffi_type_ulong : &ffi_type_uint64;
|
979
|
+
for (i = 0; i <= MAX_FIXED_ARITY + 1; ++i) {
|
980
|
+
methodHandleParamTypes[i] = ffiValueType;
|
981
|
+
}
|
982
|
+
methodHandleVarargParamTypes[2] = ffiValueType;
|
983
|
+
|
984
|
+
#ifndef _WIN32
|
985
|
+
PageSize = sysconf(_SC_PAGESIZE);
|
986
|
+
#endif /* _WIN32 */
|
987
|
+
|
988
|
+
#if defined(USE_PTHREAD_LOCAL)
|
626
989
|
pthread_key_create(&threadDataKey, thread_data_free);
|
627
|
-
|
990
|
+
for (i = 0; i < 4; ++i) {
|
991
|
+
pthread_mutex_init(&methodHandlePool[i].mutex, NULL);
|
992
|
+
}
|
993
|
+
pthread_mutex_init(&defaultMethodHandlePool.mutex, NULL);
|
994
|
+
#else
|
995
|
+
thread_data_id = rb_intern("ffi_thread_local_data");
|
996
|
+
#endif /* USE_PTHREAD_LOCAL */
|
997
|
+
|
628
998
|
}
|