ffi 0.1.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.

Files changed (279) hide show
  1. data/LICENSE +51 -0
  2. data/README +0 -0
  3. data/Rakefile +90 -0
  4. data/ext/AbstractMemory.c +254 -0
  5. data/ext/AbstractMemory.h +36 -0
  6. data/ext/Buffer.c +94 -0
  7. data/ext/Callback.c +240 -0
  8. data/ext/Callback.h +47 -0
  9. data/ext/Invoker.c +269 -0
  10. data/ext/MemoryPointer.c +164 -0
  11. data/ext/MemoryPointer.h +25 -0
  12. data/ext/Platform.c +41 -0
  13. data/ext/Platform.h +23 -0
  14. data/ext/Types.c +65 -0
  15. data/ext/Types.h +51 -0
  16. data/ext/extconf.rb +13 -0
  17. data/ext/ffi.c +54 -0
  18. data/ext/ffi.mk +24 -0
  19. data/ext/libffi.darwin.mk +44 -0
  20. data/ext/libffi.mk +10 -0
  21. data/ext/libffi/ChangeLog +3243 -0
  22. data/ext/libffi/ChangeLog.libffi +347 -0
  23. data/ext/libffi/ChangeLog.libgcj +40 -0
  24. data/ext/libffi/ChangeLog.v1 +764 -0
  25. data/ext/libffi/LICENSE +21 -0
  26. data/ext/libffi/Makefile.am +177 -0
  27. data/ext/libffi/Makefile.in +1640 -0
  28. data/ext/libffi/README +328 -0
  29. data/ext/libffi/TODO +1 -0
  30. data/ext/libffi/acinclude.m4 +92 -0
  31. data/ext/libffi/aclocal.m4 +7516 -0
  32. data/ext/libffi/compile +142 -0
  33. data/ext/libffi/config.guess +1516 -0
  34. data/ext/libffi/config.sub +1626 -0
  35. data/ext/libffi/configure +24414 -0
  36. data/ext/libffi/configure.ac +365 -0
  37. data/ext/libffi/configure.host +11 -0
  38. data/ext/libffi/depcomp +584 -0
  39. data/ext/libffi/doc/libffi.info +533 -0
  40. data/ext/libffi/doc/libffi.texi +541 -0
  41. data/ext/libffi/doc/stamp-vti +4 -0
  42. data/ext/libffi/doc/version.texi +4 -0
  43. data/ext/libffi/fficonfig.h.in +160 -0
  44. data/ext/libffi/include/Makefile.am +9 -0
  45. data/ext/libffi/include/Makefile.in +422 -0
  46. data/ext/libffi/include/ffi.h.in +393 -0
  47. data/ext/libffi/include/ffi_common.h +98 -0
  48. data/ext/libffi/install-sh +323 -0
  49. data/ext/libffi/libffi.pc.in +10 -0
  50. data/ext/libffi/libtool-version +29 -0
  51. data/ext/libffi/ltcf-c.sh +861 -0
  52. data/ext/libffi/ltcf-cxx.sh +1069 -0
  53. data/ext/libffi/ltcf-gcj.sh +700 -0
  54. data/ext/libffi/ltconfig +2862 -0
  55. data/ext/libffi/ltmain.sh +6930 -0
  56. data/ext/libffi/man/Makefile.am +8 -0
  57. data/ext/libffi/man/Makefile.in +395 -0
  58. data/ext/libffi/man/ffi.3 +31 -0
  59. data/ext/libffi/man/ffi_call.3 +103 -0
  60. data/ext/libffi/man/ffi_prep_cif.3 +66 -0
  61. data/ext/libffi/mdate-sh +201 -0
  62. data/ext/libffi/missing +353 -0
  63. data/ext/libffi/mkinstalldirs +158 -0
  64. data/ext/libffi/src/alpha/ffi.c +284 -0
  65. data/ext/libffi/src/alpha/ffitarget.h +48 -0
  66. data/ext/libffi/src/alpha/osf.S +366 -0
  67. data/ext/libffi/src/arm/ffi.c +309 -0
  68. data/ext/libffi/src/arm/ffitarget.h +49 -0
  69. data/ext/libffi/src/arm/sysv.S +299 -0
  70. data/ext/libffi/src/closures.c +596 -0
  71. data/ext/libffi/src/cris/ffi.c +383 -0
  72. data/ext/libffi/src/cris/ffitarget.h +51 -0
  73. data/ext/libffi/src/cris/sysv.S +215 -0
  74. data/ext/libffi/src/debug.c +59 -0
  75. data/ext/libffi/src/dlmalloc.c +5099 -0
  76. data/ext/libffi/src/frv/eabi.S +128 -0
  77. data/ext/libffi/src/frv/ffi.c +292 -0
  78. data/ext/libffi/src/frv/ffitarget.h +61 -0
  79. data/ext/libffi/src/ia64/ffi.c +580 -0
  80. data/ext/libffi/src/ia64/ffitarget.h +50 -0
  81. data/ext/libffi/src/ia64/ia64_flags.h +40 -0
  82. data/ext/libffi/src/ia64/unix.S +560 -0
  83. data/ext/libffi/src/java_raw_api.c +359 -0
  84. data/ext/libffi/src/m32r/ffi.c +232 -0
  85. data/ext/libffi/src/m32r/ffitarget.h +48 -0
  86. data/ext/libffi/src/m32r/sysv.S +121 -0
  87. data/ext/libffi/src/m68k/ffi.c +278 -0
  88. data/ext/libffi/src/m68k/ffitarget.h +49 -0
  89. data/ext/libffi/src/m68k/sysv.S +234 -0
  90. data/ext/libffi/src/mips/ffi.c +926 -0
  91. data/ext/libffi/src/mips/ffitarget.h +202 -0
  92. data/ext/libffi/src/mips/n32.S +534 -0
  93. data/ext/libffi/src/mips/o32.S +381 -0
  94. data/ext/libffi/src/pa/ffi.c +709 -0
  95. data/ext/libffi/src/pa/ffitarget.h +77 -0
  96. data/ext/libffi/src/pa/hpux32.S +368 -0
  97. data/ext/libffi/src/pa/linux.S +357 -0
  98. data/ext/libffi/src/powerpc/aix.S +225 -0
  99. data/ext/libffi/src/powerpc/aix_closure.S +247 -0
  100. data/ext/libffi/src/powerpc/asm.h +125 -0
  101. data/ext/libffi/src/powerpc/darwin.S +245 -0
  102. data/ext/libffi/src/powerpc/darwin_closure.S +317 -0
  103. data/ext/libffi/src/powerpc/ffi.c +1429 -0
  104. data/ext/libffi/src/powerpc/ffi_darwin.c +800 -0
  105. data/ext/libffi/src/powerpc/ffitarget.h +118 -0
  106. data/ext/libffi/src/powerpc/linux64.S +187 -0
  107. data/ext/libffi/src/powerpc/linux64_closure.S +236 -0
  108. data/ext/libffi/src/powerpc/ppc_closure.S +327 -0
  109. data/ext/libffi/src/powerpc/sysv.S +230 -0
  110. data/ext/libffi/src/prep_cif.c +174 -0
  111. data/ext/libffi/src/raw_api.c +254 -0
  112. data/ext/libffi/src/s390/ffi.c +780 -0
  113. data/ext/libffi/src/s390/ffitarget.h +60 -0
  114. data/ext/libffi/src/s390/sysv.S +434 -0
  115. data/ext/libffi/src/sh/ffi.c +716 -0
  116. data/ext/libffi/src/sh/ffitarget.h +49 -0
  117. data/ext/libffi/src/sh/sysv.S +850 -0
  118. data/ext/libffi/src/sh64/ffi.c +453 -0
  119. data/ext/libffi/src/sh64/ffitarget.h +53 -0
  120. data/ext/libffi/src/sh64/sysv.S +530 -0
  121. data/ext/libffi/src/sparc/ffi.c +610 -0
  122. data/ext/libffi/src/sparc/ffitarget.h +66 -0
  123. data/ext/libffi/src/sparc/v8.S +272 -0
  124. data/ext/libffi/src/sparc/v9.S +307 -0
  125. data/ext/libffi/src/types.c +77 -0
  126. data/ext/libffi/src/x86/darwin.S +443 -0
  127. data/ext/libffi/src/x86/darwin64.S +416 -0
  128. data/ext/libffi/src/x86/ffi.c +475 -0
  129. data/ext/libffi/src/x86/ffi64.c +572 -0
  130. data/ext/libffi/src/x86/ffitarget.h +90 -0
  131. data/ext/libffi/src/x86/freebsd.S +458 -0
  132. data/ext/libffi/src/x86/sysv.S +437 -0
  133. data/ext/libffi/src/x86/unix64.S +418 -0
  134. data/ext/libffi/src/x86/win32.S +391 -0
  135. data/ext/libffi/testsuite/Makefile.am +71 -0
  136. data/ext/libffi/testsuite/Makefile.in +447 -0
  137. data/ext/libffi/testsuite/config/default.exp +1 -0
  138. data/ext/libffi/testsuite/lib/libffi-dg.exp +289 -0
  139. data/ext/libffi/testsuite/lib/target-libpath.exp +263 -0
  140. data/ext/libffi/testsuite/lib/wrapper.exp +45 -0
  141. data/ext/libffi/testsuite/libffi.call/call.exp +36 -0
  142. data/ext/libffi/testsuite/libffi.call/closure_fn0.c +97 -0
  143. data/ext/libffi/testsuite/libffi.call/closure_fn1.c +89 -0
  144. data/ext/libffi/testsuite/libffi.call/closure_fn2.c +89 -0
  145. data/ext/libffi/testsuite/libffi.call/closure_fn3.c +90 -0
  146. data/ext/libffi/testsuite/libffi.call/closure_fn4.c +97 -0
  147. data/ext/libffi/testsuite/libffi.call/closure_fn5.c +99 -0
  148. data/ext/libffi/testsuite/libffi.call/closure_fn6.c +98 -0
  149. data/ext/libffi/testsuite/libffi.call/closure_stdcall.c +72 -0
  150. data/ext/libffi/testsuite/libffi.call/cls_12byte.c +102 -0
  151. data/ext/libffi/testsuite/libffi.call/cls_16byte.c +103 -0
  152. data/ext/libffi/testsuite/libffi.call/cls_18byte.c +104 -0
  153. data/ext/libffi/testsuite/libffi.call/cls_19byte.c +110 -0
  154. data/ext/libffi/testsuite/libffi.call/cls_1_1byte.c +97 -0
  155. data/ext/libffi/testsuite/libffi.call/cls_20byte.c +99 -0
  156. data/ext/libffi/testsuite/libffi.call/cls_20byte1.c +101 -0
  157. data/ext/libffi/testsuite/libffi.call/cls_24byte.c +121 -0
  158. data/ext/libffi/testsuite/libffi.call/cls_2byte.c +98 -0
  159. data/ext/libffi/testsuite/libffi.call/cls_3_1byte.c +103 -0
  160. data/ext/libffi/testsuite/libffi.call/cls_3byte1.c +98 -0
  161. data/ext/libffi/testsuite/libffi.call/cls_3byte2.c +98 -0
  162. data/ext/libffi/testsuite/libffi.call/cls_4_1byte.c +106 -0
  163. data/ext/libffi/testsuite/libffi.call/cls_4byte.c +98 -0
  164. data/ext/libffi/testsuite/libffi.call/cls_5_1_byte.c +117 -0
  165. data/ext/libffi/testsuite/libffi.call/cls_5byte.c +106 -0
  166. data/ext/libffi/testsuite/libffi.call/cls_64byte.c +132 -0
  167. data/ext/libffi/testsuite/libffi.call/cls_6_1_byte.c +121 -0
  168. data/ext/libffi/testsuite/libffi.call/cls_6byte.c +107 -0
  169. data/ext/libffi/testsuite/libffi.call/cls_7_1_byte.c +125 -0
  170. data/ext/libffi/testsuite/libffi.call/cls_7byte.c +105 -0
  171. data/ext/libffi/testsuite/libffi.call/cls_8byte.c +96 -0
  172. data/ext/libffi/testsuite/libffi.call/cls_9byte1.c +98 -0
  173. data/ext/libffi/testsuite/libffi.call/cls_9byte2.c +99 -0
  174. data/ext/libffi/testsuite/libffi.call/cls_align_double.c +101 -0
  175. data/ext/libffi/testsuite/libffi.call/cls_align_float.c +99 -0
  176. data/ext/libffi/testsuite/libffi.call/cls_align_longdouble.c +100 -0
  177. data/ext/libffi/testsuite/libffi.call/cls_align_pointer.c +101 -0
  178. data/ext/libffi/testsuite/libffi.call/cls_align_sint16.c +99 -0
  179. data/ext/libffi/testsuite/libffi.call/cls_align_sint32.c +99 -0
  180. data/ext/libffi/testsuite/libffi.call/cls_align_sint64.c +99 -0
  181. data/ext/libffi/testsuite/libffi.call/cls_align_uint16.c +99 -0
  182. data/ext/libffi/testsuite/libffi.call/cls_align_uint32.c +99 -0
  183. data/ext/libffi/testsuite/libffi.call/cls_align_uint64.c +100 -0
  184. data/ext/libffi/testsuite/libffi.call/cls_double.c +51 -0
  185. data/ext/libffi/testsuite/libffi.call/cls_float.c +51 -0
  186. data/ext/libffi/testsuite/libffi.call/cls_multi_schar.c +82 -0
  187. data/ext/libffi/testsuite/libffi.call/cls_multi_sshort.c +82 -0
  188. data/ext/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +94 -0
  189. data/ext/libffi/testsuite/libffi.call/cls_multi_uchar.c +99 -0
  190. data/ext/libffi/testsuite/libffi.call/cls_multi_ushort.c +82 -0
  191. data/ext/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +94 -0
  192. data/ext/libffi/testsuite/libffi.call/cls_schar.c +52 -0
  193. data/ext/libffi/testsuite/libffi.call/cls_sint.c +50 -0
  194. data/ext/libffi/testsuite/libffi.call/cls_sshort.c +50 -0
  195. data/ext/libffi/testsuite/libffi.call/cls_uchar.c +50 -0
  196. data/ext/libffi/testsuite/libffi.call/cls_uint.c +51 -0
  197. data/ext/libffi/testsuite/libffi.call/cls_ulonglong.c +54 -0
  198. data/ext/libffi/testsuite/libffi.call/cls_ushort.c +51 -0
  199. data/ext/libffi/testsuite/libffi.call/ffitest.h +86 -0
  200. data/ext/libffi/testsuite/libffi.call/float.c +59 -0
  201. data/ext/libffi/testsuite/libffi.call/float1.c +58 -0
  202. data/ext/libffi/testsuite/libffi.call/float2.c +57 -0
  203. data/ext/libffi/testsuite/libffi.call/float3.c +72 -0
  204. data/ext/libffi/testsuite/libffi.call/float4.c +62 -0
  205. data/ext/libffi/testsuite/libffi.call/many.c +69 -0
  206. data/ext/libffi/testsuite/libffi.call/many_win32.c +63 -0
  207. data/ext/libffi/testsuite/libffi.call/negint.c +53 -0
  208. data/ext/libffi/testsuite/libffi.call/nested_struct.c +160 -0
  209. data/ext/libffi/testsuite/libffi.call/nested_struct1.c +169 -0
  210. data/ext/libffi/testsuite/libffi.call/nested_struct10.c +141 -0
  211. data/ext/libffi/testsuite/libffi.call/nested_struct2.c +118 -0
  212. data/ext/libffi/testsuite/libffi.call/nested_struct3.c +119 -0
  213. data/ext/libffi/testsuite/libffi.call/nested_struct4.c +119 -0
  214. data/ext/libffi/testsuite/libffi.call/nested_struct5.c +120 -0
  215. data/ext/libffi/testsuite/libffi.call/nested_struct6.c +139 -0
  216. data/ext/libffi/testsuite/libffi.call/nested_struct7.c +119 -0
  217. data/ext/libffi/testsuite/libffi.call/nested_struct8.c +139 -0
  218. data/ext/libffi/testsuite/libffi.call/nested_struct9.c +139 -0
  219. data/ext/libffi/testsuite/libffi.call/problem1.c +98 -0
  220. data/ext/libffi/testsuite/libffi.call/promotion.c +59 -0
  221. data/ext/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
  222. data/ext/libffi/testsuite/libffi.call/return_dbl.c +35 -0
  223. data/ext/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
  224. data/ext/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
  225. data/ext/libffi/testsuite/libffi.call/return_fl.c +35 -0
  226. data/ext/libffi/testsuite/libffi.call/return_fl1.c +36 -0
  227. data/ext/libffi/testsuite/libffi.call/return_fl2.c +49 -0
  228. data/ext/libffi/testsuite/libffi.call/return_fl3.c +42 -0
  229. data/ext/libffi/testsuite/libffi.call/return_ldl.c +34 -0
  230. data/ext/libffi/testsuite/libffi.call/return_ll.c +41 -0
  231. data/ext/libffi/testsuite/libffi.call/return_ll1.c +42 -0
  232. data/ext/libffi/testsuite/libffi.call/return_sc.c +36 -0
  233. data/ext/libffi/testsuite/libffi.call/return_sl.c +38 -0
  234. data/ext/libffi/testsuite/libffi.call/return_uc.c +38 -0
  235. data/ext/libffi/testsuite/libffi.call/return_ul.c +38 -0
  236. data/ext/libffi/testsuite/libffi.call/strlen.c +44 -0
  237. data/ext/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
  238. data/ext/libffi/testsuite/libffi.call/struct1.c +65 -0
  239. data/ext/libffi/testsuite/libffi.call/struct2.c +67 -0
  240. data/ext/libffi/testsuite/libffi.call/struct3.c +59 -0
  241. data/ext/libffi/testsuite/libffi.call/struct4.c +63 -0
  242. data/ext/libffi/testsuite/libffi.call/struct5.c +65 -0
  243. data/ext/libffi/testsuite/libffi.call/struct6.c +64 -0
  244. data/ext/libffi/testsuite/libffi.call/struct7.c +74 -0
  245. data/ext/libffi/testsuite/libffi.call/struct8.c +80 -0
  246. data/ext/libffi/testsuite/libffi.call/struct9.c +67 -0
  247. data/ext/libffi/testsuite/libffi.special/ffitestcxx.h +86 -0
  248. data/ext/libffi/testsuite/libffi.special/special.exp +38 -0
  249. data/ext/libffi/testsuite/libffi.special/unwindtest.cc +123 -0
  250. data/ext/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
  251. data/ext/libffi/texinfo.tex +7482 -0
  252. data/ext/rbffi.h +32 -0
  253. data/lib/ffi.rb +2 -0
  254. data/lib/ffi/buffer.rb +25 -0
  255. data/lib/ffi/callback.rb +10 -0
  256. data/lib/ffi/ffi.rb +259 -0
  257. data/lib/ffi/memorypointer.rb +169 -0
  258. data/lib/ffi/platform.rb +75 -0
  259. data/lib/ffi/struct.rb +263 -0
  260. data/nbproject/Makefile-Default.mk +54 -0
  261. data/nbproject/Makefile-impl.mk +123 -0
  262. data/nbproject/configurations.xml +169 -0
  263. data/nbproject/private/configurations.xml +22 -0
  264. data/nbproject/private/private.xml +7 -0
  265. data/nbproject/project.properties +0 -0
  266. data/nbproject/project.xml +11 -0
  267. data/samples/getlogin.rb +7 -0
  268. data/samples/getpid.rb +7 -0
  269. data/samples/gettimeofday.rb +13 -0
  270. data/samples/hello.rb +7 -0
  271. data/samples/qsort.rb +20 -0
  272. data/specs/buffer_spec.rb +141 -0
  273. data/specs/callback_spec.rb +31 -0
  274. data/specs/rbx/attach_function_spec.rb +26 -0
  275. data/specs/rbx/memory_pointer_spec.rb +108 -0
  276. data/specs/rbx/spec_helper.rb +1 -0
  277. data/specs/rbx/struct_spec.rb +13 -0
  278. data/specs/spec_helper.rb +2 -0
  279. metadata +359 -0
@@ -0,0 +1,240 @@
1
+ #include <sys/types.h>
2
+ #include <ruby.h>
3
+ #include "MemoryPointer.h"
4
+ #include "AbstractMemory.h"
5
+ #include "Callback.h"
6
+ #include "Types.h"
7
+ #include "rbffi.h"
8
+
9
+
10
+
11
+ static void callback_mark(CallbackInfo *);
12
+ static void callback_free(CallbackInfo *);
13
+
14
+ static VALUE classCallback = Qnil;
15
+ static VALUE classNativeCallback = Qnil;
16
+ static ID callID = Qnil;
17
+
18
+ //static VALUE classCallbackImpl = Qnil;
19
+ VALUE rb_FFI_Callback_class = Qnil;
20
+
21
+ static VALUE
22
+ callback_new(VALUE self, VALUE rbReturnType, VALUE rbParamTypes)
23
+ {
24
+ CallbackInfo *cbInfo = ALLOC(CallbackInfo);
25
+ int paramCount = RARRAY_LEN(rbParamTypes);
26
+ ffi_status status;
27
+ int i;
28
+
29
+ cbInfo->parameterCount = paramCount;
30
+ cbInfo->parameterTypes = calloc(paramCount, sizeof(NativeType));
31
+ cbInfo->ffiParameterTypes = calloc(paramCount, sizeof(ffi_type *));
32
+ if (cbInfo->parameterTypes == NULL || cbInfo->ffiParameterTypes == NULL) {
33
+ callback_free(cbInfo);
34
+ rb_raise(rb_eNoMemError, "Failed to allocate native memory");
35
+ }
36
+ for (i = 0; i < paramCount; ++i) {
37
+ cbInfo->parameterTypes[i] = FIX2INT(rb_ary_entry(rbParamTypes, i));
38
+ cbInfo->ffiParameterTypes[i] = rb_FFI_NativeTypeToFFI(cbInfo->parameterTypes[i]);
39
+ if (cbInfo->ffiParameterTypes[i] == NULL) {
40
+ callback_free(cbInfo);
41
+ rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]);
42
+ }
43
+ }
44
+ cbInfo->returnType = FIX2INT(rbReturnType);
45
+ cbInfo->ffiReturnType = rb_FFI_NativeTypeToFFI(cbInfo->returnType);
46
+ if (cbInfo->ffiReturnType == NULL) {
47
+ callback_free(cbInfo);
48
+ rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType);
49
+ }
50
+ #ifdef _WIN32
51
+ cbInfo->abi = (flags & STDCALL) ? FFI_STDCALL : FFI_DEFAULT_ABI;
52
+ #else
53
+ cbInfo->abi = FFI_DEFAULT_ABI;
54
+ #endif
55
+ status = ffi_prep_cif(&cbInfo->ffi_cif, cbInfo->abi, cbInfo->parameterCount,
56
+ cbInfo->ffiReturnType, cbInfo->ffiParameterTypes);
57
+ switch (status) {
58
+ case FFI_BAD_ABI:
59
+ callback_free(cbInfo);
60
+ rb_raise(rb_eArgError, "Invalid ABI specified");
61
+ case FFI_BAD_TYPEDEF:
62
+ callback_free(cbInfo);
63
+ rb_raise(rb_eArgError, "Invalid argument type specified");
64
+ case FFI_OK:
65
+ break;
66
+ default:
67
+ callback_free(cbInfo);
68
+ rb_raise(rb_eArgError, "Unknown FFI error");
69
+ }
70
+ return Data_Wrap_Struct(classCallback, callback_mark, callback_free, cbInfo);
71
+ }
72
+
73
+ static void
74
+ callback_mark(CallbackInfo* cbinfo)
75
+ {
76
+ }
77
+
78
+ static void
79
+ callback_free(CallbackInfo* cbInfo)
80
+ {
81
+ if (cbInfo != NULL) {
82
+ if (cbInfo->parameterTypes != NULL) {
83
+ free(cbInfo->parameterTypes);
84
+ }
85
+ if (cbInfo->ffiParameterTypes != NULL) {
86
+ free(cbInfo->ffiParameterTypes);
87
+ }
88
+ xfree(cbInfo);
89
+ }
90
+ }
91
+
92
+ static void
93
+ native_callback_free(NativeCallback* cb)
94
+ {
95
+ if (cb != NULL) {
96
+ if (cb->ffi_closure != NULL) {
97
+ ffi_closure_free(cb->ffi_closure);
98
+ }
99
+ }
100
+ }
101
+
102
+ static void
103
+ native_callback_mark(NativeCallback* cb)
104
+ {
105
+ rb_gc_mark(cb->rbCallbackInfo);
106
+ rb_gc_mark(cb->rbProc);
107
+ }
108
+
109
+ static void
110
+ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
111
+ {
112
+ NativeCallback* cb = (NativeCallback *) user_data;
113
+ CallbackInfo *cbInfo = cb->cbInfo;
114
+ VALUE* rbParams;
115
+ VALUE rbReturnValue;
116
+ int i;
117
+
118
+ rbParams = ALLOCA_N(VALUE, cbInfo->parameterCount);
119
+ for (i = 0; i < cbInfo->parameterCount; ++i) {
120
+ VALUE param;
121
+ switch (cbInfo->parameterTypes[i]) {
122
+ case INT8:
123
+ param = INT2FIX(*(int8_t *) parameters[i]);
124
+ break;
125
+ case UINT8:
126
+ param = UINT2NUM(*(u_int8_t *) parameters[i]);
127
+ break;
128
+ case INT16:
129
+ param = INT2FIX(*(int16_t *) parameters[i]);
130
+ break;
131
+ case UINT16:
132
+ param = UINT2NUM(*(u_int16_t *) parameters[i]);
133
+ break;
134
+ case INT32:
135
+ param = INT2FIX(*(int32_t *) parameters[i]);
136
+ break;
137
+ case UINT32:
138
+ param = UINT2NUM(*(u_int32_t *) parameters[i]);
139
+ break;
140
+ case INT64:
141
+ param = LL2NUM(*(int64_t *) parameters[i]);
142
+ break;
143
+ case UINT64:
144
+ param = ULL2NUM(*(u_int64_t *) parameters[i]);
145
+ break;
146
+ case FLOAT32:
147
+ param = rb_float_new(*(float *) parameters[i]);
148
+ break;
149
+ case FLOAT64:
150
+ param = rb_float_new(*(double *) parameters[i]);
151
+ break;
152
+ case STRING:
153
+ param = rb_str_new2(*(char **) parameters[i]);
154
+ break;
155
+ case POINTER:
156
+ param = rb_FFI_MemoryPointer_new(*(caddr_t *) parameters[i]);
157
+ break;
158
+ default:
159
+ param = Qnil;
160
+ break;
161
+ }
162
+ rbParams[i] = param;
163
+ }
164
+ rbReturnValue = rb_funcall2(cb->rbProc, callID, cbInfo->parameterCount, rbParams);
165
+ if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
166
+ memset(retval, 0, cbInfo->ffiReturnType->size);
167
+ } else switch (cbInfo->returnType) {
168
+ case INT8:
169
+ *((int8_t *) retval) = NUM2INT(rbReturnValue);
170
+ break;
171
+ case UINT8:
172
+ *((u_int8_t *) retval) = NUM2UINT(rbReturnValue);
173
+ break;
174
+ case INT16:
175
+ *((int16_t *) retval) = NUM2INT(rbReturnValue);
176
+ break;
177
+ case UINT16:
178
+ *((u_int16_t *) retval) = NUM2UINT(rbReturnValue);
179
+ break;
180
+ case INT32:
181
+ *((int32_t *) retval) = NUM2INT(rbReturnValue);
182
+ break;
183
+ case UINT32:
184
+ *((u_int32_t *) retval) = NUM2UINT(rbReturnValue);
185
+ break;
186
+ case INT64:
187
+ *((int64_t *) retval) = NUM2LL(rbReturnValue);
188
+ break;
189
+ case UINT64:
190
+ *((u_int64_t *) retval) = NUM2ULL(rbReturnValue);
191
+ break;
192
+ case FLOAT32:
193
+ *((float *) retval) = (float) NUM2DBL(rbReturnValue);
194
+ break;
195
+ case FLOAT64:
196
+ *((double *) retval) = NUM2DBL(rbReturnValue);
197
+ break;
198
+ case POINTER:
199
+ *((caddr_t *) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
200
+ break;
201
+ default:
202
+ break;
203
+ }
204
+ }
205
+
206
+ VALUE
207
+ rb_FFI_NativeCallback_new(VALUE rbCallbackInfo, VALUE rbProc)
208
+ {
209
+ NativeCallback* closure = NULL;
210
+ CallbackInfo* cbInfo = (CallbackInfo *) DATA_PTR(rbCallbackInfo);
211
+ ffi_status status;
212
+
213
+ closure = ALLOC(NativeCallback);
214
+ closure->ffi_closure = ffi_closure_alloc(sizeof(*closure->ffi_closure), &closure->code);
215
+ if (closure->ffi_closure == NULL) {
216
+ xfree(closure);
217
+ rb_raise(rb_eNoMemError, "Failed to allocate FFI native closure");
218
+ }
219
+ closure->cbInfo = cbInfo;
220
+ closure->rbProc = rbProc;
221
+ closure->rbCallbackInfo = rbCallbackInfo;
222
+ status = ffi_prep_closure_loc(closure->ffi_closure, &cbInfo->ffi_cif,
223
+ native_callback_invoke, closure, closure->code);
224
+ if (status != FFI_OK) {
225
+ ffi_closure_free(closure->ffi_closure);
226
+ xfree(closure);
227
+ rb_raise(rb_eArgError, "ffi_prep_closure_loc failed");
228
+ }
229
+ return Data_Wrap_Struct(classNativeCallback, native_callback_mark, native_callback_free, closure);
230
+ }
231
+
232
+ void
233
+ rb_FFI_Callback_Init()
234
+ {
235
+ VALUE moduleFFI = rb_define_module("FFI");
236
+ rb_FFI_Callback_class = classCallback = rb_define_class_under(moduleFFI, "Callback", rb_cObject);
237
+ rb_define_singleton_method(classCallback, "new", callback_new, 2);
238
+ classNativeCallback = rb_define_class_under(moduleFFI, "NativeCallback", rb_cObject);
239
+ callID = rb_intern("call");
240
+ }
@@ -0,0 +1,47 @@
1
+ /*
2
+ * File: Callback.h
3
+ * Author: wayne
4
+ *
5
+ * Created on September 11, 2008, 10:01 AM
6
+ */
7
+
8
+ #ifndef _CALLBACK_H
9
+ #define _CALLBACK_H
10
+
11
+ #include "Types.h"
12
+
13
+ #ifdef __cplusplus
14
+ extern "C" {
15
+ #endif
16
+ #include <ffi.h>
17
+
18
+ typedef struct {
19
+ NativeType returnType;
20
+ NativeType* parameterTypes;
21
+ ffi_type* ffiReturnType;
22
+ ffi_type** ffiParameterTypes;
23
+ ffi_cif ffi_cif;
24
+ int parameterCount;
25
+ int flags;
26
+ ffi_abi abi;
27
+ } CallbackInfo;
28
+
29
+ typedef struct {
30
+ void* code;
31
+ ffi_closure* ffi_closure;
32
+ ffi_cif ffi_cif;
33
+ int flags;
34
+ CallbackInfo* cbInfo;
35
+ VALUE rbCallbackInfo;
36
+ VALUE rbProc;
37
+ } NativeCallback;
38
+
39
+ extern VALUE rb_FFI_Callback_class;
40
+ extern VALUE rb_FFI_NativeCallback_new(VALUE, VALUE);
41
+
42
+ #ifdef __cplusplus
43
+ }
44
+ #endif
45
+
46
+ #endif /* _CALLBACK_H */
47
+
@@ -0,0 +1,269 @@
1
+ #include <sys/types.h>
2
+ #include <stdio.h>
3
+ #include <stdint.h>
4
+ #include <dlfcn.h>
5
+ #include <ruby.h>
6
+
7
+ #include <ffi.h>
8
+
9
+ #include "rbffi.h"
10
+ #include "AbstractMemory.h"
11
+ #include "MemoryPointer.h"
12
+ #include "Platform.h"
13
+ #include "Callback.h"
14
+ #include "Types.h"
15
+
16
+ typedef struct Invoker {
17
+ void* dlhandle;
18
+ void* function;
19
+ ffi_cif cif;
20
+ int paramCount;
21
+ ffi_type** ffiParamTypes;
22
+ NativeType* paramTypes;
23
+ NativeType returnType;
24
+ VALUE callbackArray;
25
+ int callbackCount;
26
+ VALUE* callbackParameters;
27
+ } Invoker;
28
+
29
+ static VALUE invoker_new(VALUE self, VALUE libname, VALUE cname, VALUE parameterTypes,
30
+ VALUE returnType, VALUE convention);
31
+ static void invoker_mark(Invoker *);
32
+ static void invoker_free(Invoker *);
33
+ static VALUE invoker_call(int argc, VALUE* argv, VALUE self);
34
+ static void* callback_param(VALUE proc, VALUE cbinfo);
35
+ static VALUE classInvoker = Qnil;
36
+ static ID cbTableID;
37
+
38
+ static VALUE
39
+ invoker_new(VALUE self, VALUE libname, VALUE cname, VALUE parameterTypes,
40
+ VALUE returnType, VALUE convention)
41
+ {
42
+ Invoker* invoker = NULL;
43
+ ffi_type* ffiReturnType;
44
+ ffi_abi abi;
45
+ ffi_status ffiStatus;
46
+ const char* errmsg = "Failed to create invoker";
47
+ int i;
48
+
49
+ Check_Type(cname, T_STRING);
50
+ Check_Type(parameterTypes, T_ARRAY);
51
+ Check_Type(returnType, T_FIXNUM);
52
+ Check_Type(convention, T_STRING);
53
+
54
+ invoker = ALLOC(Invoker);
55
+ MEMZERO(invoker, Invoker, 1);
56
+
57
+ invoker->paramCount = RARRAY(parameterTypes)->len;
58
+ invoker->paramTypes = ALLOC_N(NativeType, invoker->paramCount);
59
+ invoker->ffiParamTypes = ALLOC_N(ffi_type *, invoker->paramCount);
60
+
61
+ for (i = 0; i < invoker->paramCount; ++i) {
62
+ VALUE entry = rb_ary_entry(parameterTypes, i);
63
+ if (rb_obj_is_kind_of(entry, rb_FFI_Callback_class)) {
64
+ invoker->callbackParameters = REALLOC_N(invoker->callbackParameters, VALUE,
65
+ invoker->callbackCount + 1);
66
+ invoker->callbackParameters[invoker->callbackCount++] = entry;
67
+ invoker->paramTypes[i] = CALLBACK;
68
+ invoker->ffiParamTypes[i] = &ffi_type_pointer;
69
+ } else {
70
+ int paramType = FIX2INT(entry);
71
+ invoker->paramTypes[i] = paramType;
72
+ invoker->ffiParamTypes[i] = rb_FFI_NativeTypeToFFI(paramType);
73
+ }
74
+ if (invoker->ffiParamTypes[i] == NULL) {
75
+ errmsg = "Invalid parameter type";
76
+ goto error;
77
+ }
78
+ }
79
+ invoker->returnType = FIX2INT(returnType);
80
+ ffiReturnType = rb_FFI_NativeTypeToFFI(invoker->returnType);
81
+ if (ffiReturnType == NULL) {
82
+ errmsg = "Invalid return type";
83
+ goto error;
84
+ }
85
+ #ifdef _WIN32
86
+ abi = strcmp(StringValuePtr(convention), "stdcall") == 0 ? FFI_STDCALL : FFI_DEFAULT_ABI;
87
+ #else
88
+ abi = FFI_DEFAULT_ABI;
89
+ #endif
90
+ ffiStatus = ffi_prep_cif(&invoker->cif, abi, invoker->paramCount,
91
+ ffiReturnType, invoker->ffiParamTypes);
92
+ if (ffiStatus != FFI_OK) {
93
+ errmsg = "ffi_prep_cif failed";
94
+ goto error;
95
+ }
96
+
97
+ invoker->dlhandle = dlopen(libname != Qnil ? StringValuePtr(libname) : NULL, RTLD_LAZY);
98
+ if (invoker->dlhandle == NULL) {
99
+ errmsg = "No such library";
100
+ goto error;
101
+ }
102
+ invoker->function = dlsym(invoker->dlhandle, StringValuePtr(cname));
103
+ if (invoker->function == NULL) {
104
+ errmsg = "Could not locate function within library";
105
+ goto error;
106
+ }
107
+ return Data_Wrap_Struct(classInvoker, invoker_mark, invoker_free, invoker);
108
+ error:
109
+ if (invoker != NULL) {
110
+ if (invoker->dlhandle != NULL) {
111
+ dlclose(invoker->dlhandle);
112
+ }
113
+ if (invoker->paramTypes != NULL) {
114
+ xfree(invoker->paramTypes);
115
+ }
116
+ if (invoker->ffiParamTypes != NULL) {
117
+ xfree(invoker->ffiParamTypes);
118
+ }
119
+ xfree(invoker);
120
+ }
121
+ rb_raise(rb_eRuntimeError, errmsg);
122
+ }
123
+
124
+ static VALUE
125
+ invoker_call(int argc, VALUE* argv, VALUE self)
126
+ {
127
+ Invoker* invoker;
128
+ union {
129
+ signed long i;
130
+ unsigned long u;
131
+ signed long long i64;
132
+ unsigned long long u64;
133
+ void* ptr;
134
+ float f32;
135
+ double f64;
136
+ } params[MAX_PARAMETERS], retval;
137
+ void* ffiValues[MAX_PARAMETERS];
138
+ VALUE callbackProc = Qnil;
139
+ int i, argidx, cbidx;
140
+
141
+ Data_Get_Struct(self, Invoker, invoker);
142
+ if (argc < invoker->paramCount && invoker->callbackCount == 1 && rb_block_given_p()) {
143
+ callbackProc = rb_block_proc();
144
+ } else if (argc != invoker->paramCount) {
145
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, invoker->paramCount);
146
+ }
147
+
148
+ for (i = 0, argidx = 0, cbidx = 0; i < invoker->paramCount; ++i) {
149
+ switch (invoker->paramTypes[i]) {
150
+ case INT8:
151
+ case INT16:
152
+ case INT32:
153
+ Check_Type(argv[argidx], T_FIXNUM);
154
+ params[i].i = NUM2INT(argv[argidx]);
155
+ ++argidx;
156
+ break;
157
+ case UINT8:
158
+ case UINT16:
159
+ case UINT32:
160
+ Check_Type(argv[argidx], T_FIXNUM);
161
+ params[i].u = NUM2UINT(argv[argidx]);
162
+ ++argidx;
163
+ break;
164
+ case INT64:
165
+ Check_Type(argv[argidx], T_FIXNUM);
166
+ params[i].i64 = NUM2LL(argv[argidx]);
167
+ ++argidx;
168
+ break;
169
+ case UINT64:
170
+ Check_Type(argv[argidx], T_FIXNUM);
171
+ params[i].i64 = NUM2ULL(argv[argidx]);
172
+ ++argidx;
173
+ break;
174
+ case FLOAT32:
175
+ if (TYPE(argv[argidx]) != T_FLOAT && TYPE(argv[argidx]) != T_FIXNUM) {
176
+ Check_Type(argv[argidx], T_FLOAT);
177
+ }
178
+ params[i].f32 = (float) NUM2DBL(argv[argidx]);
179
+ ++argidx;
180
+ break;
181
+ case FLOAT64:
182
+ if (TYPE(argv[argidx]) != T_FLOAT && TYPE(argv[argidx]) != T_FIXNUM) {
183
+ Check_Type(argv[argidx], T_FLOAT);
184
+ }
185
+ params[i].f64 = NUM2DBL(argv[argidx]);
186
+ ++argidx;
187
+ break;
188
+ case STRING:
189
+ Check_Type(argv[argidx], T_STRING);
190
+ params[i].ptr = StringValuePtr(argv[argidx]);
191
+ ++argidx;
192
+ break;
193
+ case POINTER:
194
+ if (rb_obj_is_kind_of(argv[argidx], rb_FFI_AbstractMemory_class)) {
195
+ params[i].ptr = ((AbstractMemory *) DATA_PTR(argv[argidx]))->address;
196
+ } else if (TYPE(argv[argidx]) == T_STRING) {
197
+ params[i].ptr = StringValuePtr(argv[argidx]);
198
+ } else if (TYPE(argv[argidx] == T_NIL)) {
199
+ params[i].ptr = NULL;
200
+ } else if (TYPE(argv[argidx] == T_FIXNUM)) {
201
+ params[i].ptr = (void *) (uintptr_t) FIX2INT(argv[argidx]);
202
+ } else if (TYPE(argv[argidx] == T_BIGNUM)) {
203
+ params[i].ptr = (void *) (uintptr_t) NUM2ULL(argv[argidx]);
204
+ } else {
205
+ rb_raise(rb_eArgError, ":pointer argument is not a valid pointer");
206
+ }
207
+ ++argidx;
208
+ break;
209
+ case CALLBACK:
210
+ if (callbackProc != Qnil) {
211
+ params[i].ptr = callback_param(callbackProc, invoker->callbackParameters[cbidx++]);
212
+ } else {
213
+ params[i].ptr = callback_param(argv[argidx], invoker->callbackParameters[cbidx++]);
214
+ ++argidx;
215
+ }
216
+ break;
217
+ default:
218
+ rb_raise(rb_eArgError, "Invalid parameter type: %d", invoker->paramTypes[i]);
219
+ }
220
+ ffiValues[i] = &params[i];
221
+ }
222
+ ffi_call(&invoker->cif, FFI_FN(invoker->function), &retval, ffiValues);
223
+ return rb_FFI_NativeValueToRuby(invoker->returnType, &retval);
224
+ }
225
+
226
+ static void
227
+ invoker_mark(Invoker *invoker)
228
+ {
229
+ if (invoker->callbackCount > 0) {
230
+ rb_gc_mark_locations(&invoker->callbackParameters[0], &invoker->callbackParameters[invoker->callbackCount]);
231
+ }
232
+ }
233
+
234
+ static void
235
+ invoker_free(Invoker *invoker)
236
+ {
237
+ xfree(invoker->callbackParameters);
238
+ xfree(invoker->paramTypes);
239
+ xfree(invoker->ffiParamTypes);
240
+ dlclose(invoker->dlhandle);
241
+ xfree(invoker);
242
+ }
243
+
244
+ static void*
245
+ callback_param(VALUE proc, VALUE cbInfo)
246
+ {
247
+ VALUE callback;
248
+ VALUE cbTable = rb_ivar_get(proc, cbTableID);
249
+ if (!cbTable || cbTable == Qnil) {
250
+ cbTable = rb_hash_new();
251
+ rb_ivar_set(proc, cbTableID, cbTable);
252
+ }
253
+ callback = rb_hash_aref(cbTable, cbInfo);
254
+ if (callback != Qnil) {
255
+ return ((NativeCallback *) DATA_PTR(callback))->code;
256
+ }
257
+ callback = rb_FFI_NativeCallback_new(cbInfo, proc);
258
+ rb_hash_aset(cbTable, cbInfo, callback);
259
+ return ((NativeCallback *) DATA_PTR(callback))->code;
260
+ }
261
+ void
262
+ rb_FFI_Invoker_Init()
263
+ {
264
+ VALUE moduleFFI = rb_define_module("FFI");
265
+ classInvoker = rb_define_class_under(moduleFFI, "Invoker", rb_cObject);
266
+ rb_define_singleton_method(classInvoker, "new", invoker_new, 5);
267
+ rb_define_method(classInvoker, "call", invoker_call, -1);
268
+ cbTableID = rb_intern("__ffi_callback_table__");
269
+ }