ffi 1.15.5 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +118 -0
  4. data/Gemfile +10 -3
  5. data/README.md +4 -3
  6. data/Rakefile +25 -10
  7. data/ext/ffi_c/AbstractMemory.c +99 -74
  8. data/ext/ffi_c/AbstractMemory.h +3 -2
  9. data/ext/ffi_c/ArrayType.c +51 -15
  10. data/ext/ffi_c/ArrayType.h +1 -0
  11. data/ext/ffi_c/Buffer.c +90 -33
  12. data/ext/ffi_c/Call.c +29 -12
  13. data/ext/ffi_c/Call.h +3 -2
  14. data/ext/ffi_c/DynamicLibrary.c +90 -27
  15. data/ext/ffi_c/Function.c +244 -98
  16. data/ext/ffi_c/Function.h +1 -0
  17. data/ext/ffi_c/FunctionInfo.c +81 -25
  18. data/ext/ffi_c/LastError.c +29 -11
  19. data/ext/ffi_c/MappedType.c +66 -23
  20. data/ext/ffi_c/MappedType.h +0 -2
  21. data/ext/ffi_c/MemoryPointer.c +36 -9
  22. data/ext/ffi_c/MethodHandle.c +3 -1
  23. data/ext/ffi_c/Pointer.c +82 -40
  24. data/ext/ffi_c/Pointer.h +1 -0
  25. data/ext/ffi_c/Struct.c +166 -84
  26. data/ext/ffi_c/Struct.h +7 -4
  27. data/ext/ffi_c/StructByValue.c +48 -16
  28. data/ext/ffi_c/StructLayout.c +130 -61
  29. data/ext/ffi_c/Type.c +120 -51
  30. data/ext/ffi_c/Type.h +3 -1
  31. data/ext/ffi_c/Types.c +8 -2
  32. data/ext/ffi_c/Types.h +0 -1
  33. data/ext/ffi_c/Variadic.c +71 -26
  34. data/ext/ffi_c/compat.h +22 -22
  35. data/ext/ffi_c/extconf.rb +19 -2
  36. data/ext/ffi_c/ffi.c +4 -0
  37. data/ext/ffi_c/libffi/.allow-ai-service +0 -0
  38. data/ext/ffi_c/libffi/.appveyor/site.exp +16 -0
  39. data/ext/ffi_c/libffi/.appveyor/unix-noexec.exp +7 -0
  40. data/ext/ffi_c/libffi/.appveyor.yml +27 -9
  41. data/ext/ffi_c/libffi/.ci/build-cross-in-container.sh +18 -0
  42. data/ext/ffi_c/libffi/{.travis → .ci}/build-in-container.sh +4 -6
  43. data/ext/ffi_c/libffi/.ci/build.sh +124 -0
  44. data/ext/ffi_c/libffi/{.travis → .ci}/install.sh +14 -7
  45. data/ext/ffi_c/libffi/.ci/msvs-detect +1103 -0
  46. data/ext/ffi_c/libffi/{.travis → .ci}/site.exp +5 -3
  47. data/ext/ffi_c/libffi/.circleci/config.yml +156 -0
  48. data/ext/ffi_c/libffi/.github/workflows/build.yml +479 -0
  49. data/ext/ffi_c/libffi/.github/workflows/emscripten.yml +172 -0
  50. data/ext/ffi_c/libffi/.gitignore +10 -2
  51. data/ext/ffi_c/libffi/LICENSE +1 -1
  52. data/ext/ffi_c/libffi/Makefile.am +12 -5
  53. data/ext/ffi_c/libffi/Makefile.in +118 -51
  54. data/ext/ffi_c/libffi/README.md +150 -105
  55. data/ext/ffi_c/libffi/acinclude.m4 +10 -112
  56. data/ext/ffi_c/libffi/compile +348 -0
  57. data/ext/ffi_c/libffi/config.guess +623 -556
  58. data/ext/ffi_c/libffi/config.sub +75 -34
  59. data/ext/ffi_c/libffi/configure +4571 -3830
  60. data/ext/ffi_c/libffi/configure.ac +64 -28
  61. data/ext/ffi_c/libffi/configure.host +26 -7
  62. data/ext/ffi_c/libffi/doc/Makefile.in +9 -6
  63. data/ext/ffi_c/libffi/doc/libffi.texi +82 -33
  64. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  65. data/ext/ffi_c/libffi/fficonfig.h.in +12 -47
  66. data/ext/ffi_c/libffi/generate-darwin-source-and-headers.py +163 -52
  67. data/ext/ffi_c/libffi/include/Makefile.am +1 -1
  68. data/ext/ffi_c/libffi/include/Makefile.in +10 -9
  69. data/ext/ffi_c/libffi/include/ffi.h.in +55 -60
  70. data/ext/ffi_c/libffi/include/ffi_cfi.h +21 -0
  71. data/ext/ffi_c/libffi/include/ffi_common.h +33 -2
  72. data/ext/ffi_c/libffi/include/tramp.h +45 -0
  73. data/ext/ffi_c/libffi/install-sh +92 -69
  74. data/ext/ffi_c/libffi/libffi.map.in +5 -0
  75. data/ext/ffi_c/libffi/libtool-version +2 -2
  76. data/ext/ffi_c/libffi/ltmain.sh +518 -333
  77. data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +18 -14
  78. data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +108 -72
  79. data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +76 -45
  80. data/ext/ffi_c/libffi/m4/ax_prepend_flag.m4 +51 -0
  81. data/ext/ffi_c/libffi/man/Makefile.in +9 -6
  82. data/ext/ffi_c/libffi/missing +1 -1
  83. data/ext/ffi_c/libffi/msvc_build/aarch64/aarch64_include/ffi.h +2 -2
  84. data/ext/ffi_c/libffi/msvcc.sh +1 -1
  85. data/ext/ffi_c/libffi/src/aarch64/ffi.c +172 -55
  86. data/ext/ffi_c/libffi/src/aarch64/internal.h +32 -0
  87. data/ext/ffi_c/libffi/src/aarch64/sysv.S +331 -87
  88. data/ext/ffi_c/libffi/src/arc/arcompact.S +169 -94
  89. data/ext/ffi_c/libffi/src/arc/ffi.c +325 -148
  90. data/ext/ffi_c/libffi/src/arc/ffitarget.h +14 -0
  91. data/ext/ffi_c/libffi/src/arm/ffi.c +62 -17
  92. data/ext/ffi_c/libffi/src/arm/ffitarget.h +3 -3
  93. data/ext/ffi_c/libffi/src/arm/internal.h +10 -0
  94. data/ext/ffi_c/libffi/src/arm/sysv.S +113 -42
  95. data/ext/ffi_c/libffi/src/closures.c +136 -50
  96. data/ext/ffi_c/libffi/src/debug.c +2 -2
  97. data/ext/ffi_c/libffi/src/dlmalloc.c +6 -1
  98. data/ext/ffi_c/libffi/src/ia64/ffi.c +12 -0
  99. data/ext/ffi_c/libffi/src/ia64/unix.S +20 -2
  100. data/ext/ffi_c/libffi/src/loongarch64/ffi.c +624 -0
  101. data/ext/ffi_c/libffi/src/loongarch64/ffitarget.h +82 -0
  102. data/ext/ffi_c/libffi/src/loongarch64/sysv.S +327 -0
  103. data/ext/ffi_c/libffi/src/m32r/ffi.c +31 -14
  104. data/ext/ffi_c/libffi/src/mips/ffi.c +250 -67
  105. data/ext/ffi_c/libffi/src/mips/ffitarget.h +7 -0
  106. data/ext/ffi_c/libffi/src/mips/n32.S +193 -33
  107. data/ext/ffi_c/libffi/src/mips/o32.S +61 -4
  108. data/ext/ffi_c/libffi/src/moxie/ffi.c +47 -22
  109. data/ext/ffi_c/libffi/src/or1k/ffi.c +25 -12
  110. data/ext/ffi_c/libffi/src/pa/ffi.c +32 -33
  111. data/ext/ffi_c/libffi/src/pa/ffi64.c +614 -0
  112. data/ext/ffi_c/libffi/src/pa/ffitarget.h +22 -8
  113. data/ext/ffi_c/libffi/src/pa/hpux32.S +83 -36
  114. data/ext/ffi_c/libffi/src/pa/hpux64.S +681 -0
  115. data/ext/ffi_c/libffi/src/pa/linux.S +82 -35
  116. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +36 -24
  117. data/ext/ffi_c/libffi/src/powerpc/ffi_linux64.c +1 -1
  118. data/ext/ffi_c/libffi/src/powerpc/linux64.S +2 -0
  119. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +2 -0
  120. data/ext/ffi_c/libffi/src/powerpc/t-aix +5 -0
  121. data/ext/ffi_c/libffi/src/prep_cif.c +22 -2
  122. data/ext/ffi_c/libffi/src/riscv/ffi.c +37 -4
  123. data/ext/ffi_c/libffi/src/sparc/ffi64.c +23 -1
  124. data/ext/ffi_c/libffi/src/tramp.c +716 -0
  125. data/ext/ffi_c/libffi/src/types.c +4 -6
  126. data/ext/ffi_c/libffi/src/wasm32/ffi.c +947 -0
  127. data/ext/ffi_c/libffi/src/wasm32/ffitarget.h +62 -0
  128. data/ext/ffi_c/libffi/src/x86/ffi.c +99 -37
  129. data/ext/ffi_c/libffi/src/x86/ffi64.c +67 -12
  130. data/ext/ffi_c/libffi/src/x86/ffitarget.h +9 -5
  131. data/ext/ffi_c/libffi/src/x86/ffiw64.c +44 -1
  132. data/ext/ffi_c/libffi/src/x86/internal.h +14 -0
  133. data/ext/ffi_c/libffi/src/x86/internal64.h +14 -0
  134. data/ext/ffi_c/libffi/src/x86/sysv.S +172 -38
  135. data/ext/ffi_c/libffi/src/x86/sysv_intel.S +91 -88
  136. data/ext/ffi_c/libffi/src/x86/unix64.S +96 -6
  137. data/ext/ffi_c/libffi/src/x86/win64.S +20 -7
  138. data/ext/ffi_c/libffi/src/xtensa/ffi.c +16 -8
  139. data/ext/ffi_c/libffi/src/xtensa/ffitarget.h +4 -0
  140. data/ext/ffi_c/libffi/src/xtensa/sysv.S +26 -16
  141. data/ext/ffi_c/libffi/testsuite/Makefile.am +79 -114
  142. data/ext/ffi_c/libffi/testsuite/Makefile.in +89 -121
  143. data/ext/ffi_c/libffi/testsuite/emscripten/build-tests.sh +54 -0
  144. data/ext/ffi_c/libffi/testsuite/emscripten/build.sh +63 -0
  145. data/ext/ffi_c/libffi/testsuite/emscripten/conftest.py +86 -0
  146. data/ext/ffi_c/libffi/testsuite/emscripten/node-tests.sh +48 -0
  147. data/ext/ffi_c/libffi/testsuite/emscripten/test.html +7 -0
  148. data/ext/ffi_c/libffi/testsuite/emscripten/test_libffi.py +51 -0
  149. data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +43 -21
  150. data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +2 -2
  151. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/test-call.c +1 -0
  152. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/testcases.c +5 -1
  153. data/ext/ffi_c/libffi/testsuite/libffi.call/bpo_38748.c +41 -0
  154. data/ext/ffi_c/libffi/testsuite/libffi.call/callback.c +99 -0
  155. data/ext/ffi_c/libffi/testsuite/libffi.call/callback2.c +108 -0
  156. data/ext/ffi_c/libffi/testsuite/libffi.call/callback3.c +114 -0
  157. data/ext/ffi_c/libffi/testsuite/libffi.call/callback4.c +119 -0
  158. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +28 -3
  159. data/ext/ffi_c/libffi/testsuite/libffi.call/float_va.c +3 -0
  160. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +5 -0
  161. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +4 -0
  162. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +4 -0
  163. data/ext/ffi_c/libffi/testsuite/libffi.call/s55.c +60 -0
  164. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +8 -9
  165. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen2.c +2 -2
  166. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen3.c +2 -2
  167. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen4.c +2 -2
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/struct10.c +1 -1
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_by_value_2.c +63 -0
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_by_value_3.c +65 -0
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_by_value_3f.c +65 -0
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_by_value_4.c +67 -0
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_by_value_4f.c +67 -0
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_by_value_big.c +93 -0
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_by_value_small.c +61 -0
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_return_2H.c +63 -0
  177. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_return_8H.c +90 -0
  178. data/ext/ffi_c/libffi/testsuite/libffi.call/va_1.c +1 -119
  179. data/ext/ffi_c/libffi/testsuite/libffi.call/va_2.c +220 -0
  180. data/ext/ffi_c/libffi/testsuite/libffi.call/va_3.c +154 -0
  181. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct1.c +13 -0
  182. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct2.c +11 -0
  183. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct3.c +15 -0
  184. data/ext/ffi_c/libffi/testsuite/libffi.closures/closure_fn0.c +3 -2
  185. data/ext/ffi_c/libffi/testsuite/libffi.closures/closure_fn1.c +2 -0
  186. data/ext/ffi_c/libffi/testsuite/libffi.closures/closure_fn2.c +2 -0
  187. data/ext/ffi_c/libffi/testsuite/libffi.closures/closure_fn3.c +21 -1
  188. data/ext/ffi_c/libffi/testsuite/libffi.closures/closure_fn4.c +2 -0
  189. data/ext/ffi_c/libffi/testsuite/libffi.closures/closure_fn5.c +2 -0
  190. data/ext/ffi_c/libffi/testsuite/libffi.closures/closure_fn6.c +2 -0
  191. data/ext/ffi_c/libffi/testsuite/libffi.closures/closure_loc_fn0.c +7 -6
  192. data/ext/ffi_c/libffi/testsuite/libffi.closures/closure_simple.c +6 -0
  193. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_12byte.c +18 -0
  194. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_16byte.c +22 -0
  195. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_18byte.c +24 -0
  196. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_19byte.c +29 -0
  197. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_1_1byte.c +4 -0
  198. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_20byte.c +19 -1
  199. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_20byte1.c +21 -1
  200. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_24byte.c +35 -3
  201. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_2byte.c +13 -0
  202. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_3_1byte.c +19 -0
  203. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_3byte1.c +13 -0
  204. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_3byte2.c +13 -0
  205. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_3float.c +18 -0
  206. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_4_1byte.c +22 -0
  207. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_4byte.c +13 -0
  208. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_5_1_byte.c +29 -1
  209. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_5byte.c +19 -1
  210. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_64byte.c +24 -0
  211. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_6_1_byte.c +28 -1
  212. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_6byte.c +24 -2
  213. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_7_1_byte.c +39 -1
  214. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_7byte.c +25 -1
  215. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_8byte.c +14 -0
  216. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_9byte1.c +14 -1
  217. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_9byte2.c +14 -2
  218. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_double.c +19 -1
  219. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_float.c +19 -1
  220. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_longdouble.c +20 -1
  221. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_longdouble_split.c +40 -25
  222. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_longdouble_split2.c +40 -3
  223. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_pointer.c +19 -1
  224. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_sint16.c +18 -1
  225. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_sint32.c +18 -3
  226. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_sint64.c +18 -1
  227. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_uint16.c +18 -1
  228. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_uint32.c +19 -1
  229. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_align_uint64.c +19 -1
  230. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_dbls_struct.c +3 -1
  231. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_double_va.c +9 -1
  232. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_float.c +4 -0
  233. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_longdouble.c +11 -1
  234. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_longdouble_va.c +22 -3
  235. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_schar.c +5 -1
  236. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_sshort.c +6 -1
  237. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_sshortchar.c +9 -1
  238. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_uchar.c +9 -1
  239. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_ushort.c +6 -2
  240. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_ushortchar.c +9 -1
  241. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_pointer.c +5 -0
  242. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_pointer_stack.c +10 -0
  243. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_schar.c +3 -0
  244. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_sint.c +2 -0
  245. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_sshort.c +3 -0
  246. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_struct_va1.c +11 -0
  247. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_uchar.c +3 -0
  248. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_uint.c +4 -0
  249. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_uint_va.c +4 -0
  250. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_ulong_va.c +4 -0
  251. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_ulonglong.c +2 -0
  252. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_ushort.c +3 -0
  253. data/ext/ffi_c/libffi/testsuite/libffi.closures/ffitest.h +1 -138
  254. data/ext/ffi_c/libffi/testsuite/libffi.closures/huge_struct.c +21 -21
  255. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct.c +32 -9
  256. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct1.c +1 -1
  257. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct10.c +12 -0
  258. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct11.c +21 -5
  259. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct12.c +86 -0
  260. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct13.c +115 -0
  261. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct2.c +10 -1
  262. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct3.c +10 -1
  263. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct4.c +9 -0
  264. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct5.c +9 -0
  265. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct6.c +11 -0
  266. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct7.c +9 -0
  267. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct8.c +11 -0
  268. data/ext/ffi_c/libffi/testsuite/libffi.closures/nested_struct9.c +11 -0
  269. data/ext/ffi_c/libffi/testsuite/libffi.closures/single_entry_structs1.c +86 -0
  270. data/ext/ffi_c/libffi/testsuite/libffi.closures/single_entry_structs2.c +102 -0
  271. data/ext/ffi_c/libffi/testsuite/libffi.closures/single_entry_structs3.c +101 -0
  272. data/ext/ffi_c/libffi/testsuite/libffi.closures/stret_medium.c +1 -1
  273. data/ext/ffi_c/libffi/testsuite/libffi.closures/stret_medium2.c +1 -1
  274. data/ext/ffi_c/libffi/testsuite/libffi.closures/testclosure.c +6 -1
  275. data/ext/ffi_c/libffi/testsuite/libffi.closures/unwindtest.cc +2 -1
  276. data/ext/ffi_c/libffi/testsuite/libffi.closures/unwindtest_ffi_call.cc +1 -0
  277. data/ext/ffi_c/libffi.bsd.mk +2 -2
  278. data/ext/ffi_c/libffi.darwin.mk +2 -2
  279. data/ext/ffi_c/libffi.gnu.mk +2 -2
  280. data/ext/ffi_c/rbffi.h +1 -1
  281. data/ffi.gemspec +3 -3
  282. data/lib/ffi/autopointer.rb +8 -31
  283. data/lib/ffi/compat.rb +43 -0
  284. data/lib/ffi/data_converter.rb +2 -2
  285. data/lib/ffi/dynamic_library.rb +118 -0
  286. data/lib/ffi/enum.rb +18 -12
  287. data/lib/ffi/ffi.rb +3 -0
  288. data/lib/ffi/function.rb +71 -0
  289. data/lib/ffi/io.rb +2 -2
  290. data/lib/ffi/library.rb +72 -88
  291. data/lib/ffi/library_path.rb +109 -0
  292. data/lib/ffi/managedstruct.rb +1 -1
  293. data/lib/ffi/platform/aarch64-linux/types.conf +74 -3
  294. data/lib/ffi/platform/aarch64-windows/types.conf +52 -0
  295. data/lib/ffi/platform/hppa1.1-linux/types.conf +178 -0
  296. data/lib/ffi/platform/hppa2.0-linux/types.conf +178 -0
  297. data/lib/ffi/platform/loongarch64-linux/types.conf +141 -0
  298. data/lib/ffi/platform/sw_64-linux/types.conf +141 -0
  299. data/lib/ffi/platform.rb +15 -13
  300. data/lib/ffi/pointer.rb +6 -6
  301. data/lib/ffi/struct.rb +6 -5
  302. data/lib/ffi/struct_layout.rb +3 -3
  303. data/lib/ffi/struct_layout_builder.rb +9 -9
  304. data/lib/ffi/types.rb +65 -37
  305. data/lib/ffi/variadic.rb +19 -8
  306. data/lib/ffi/version.rb +1 -1
  307. data/samples/hello_ractor.rb +11 -0
  308. data/samples/qsort_ractor.rb +28 -0
  309. data/sig/ffi/abstract_memory.rbs +165 -0
  310. data/sig/ffi/auto_pointer.rbs +27 -0
  311. data/sig/ffi/buffer.rbs +18 -0
  312. data/sig/ffi/data_converter.rbs +10 -0
  313. data/sig/ffi/dynamic_library.rbs +9 -0
  314. data/sig/ffi/enum.rbs +38 -0
  315. data/sig/ffi/function.rbs +39 -0
  316. data/sig/ffi/library.rbs +42 -0
  317. data/sig/ffi/native_type.rbs +86 -0
  318. data/sig/ffi/pointer.rbs +42 -0
  319. data/sig/ffi/struct.rbs +76 -0
  320. data/sig/ffi/struct_by_reference.rbs +11 -0
  321. data/sig/ffi/struct_by_value.rbs +7 -0
  322. data/sig/ffi/struct_layout.rbs +9 -0
  323. data/sig/ffi/struct_layout_builder.rbs +5 -0
  324. data/sig/ffi/type.rbs +39 -0
  325. data/sig/ffi.rbs +26 -0
  326. data.tar.gz.sig +0 -0
  327. metadata +122 -28
  328. metadata.gz.sig +1 -0
  329. data/ext/ffi_c/libffi/.travis/build-cross-in-container.sh +0 -14
  330. data/ext/ffi_c/libffi/.travis/build.sh +0 -142
  331. data/ext/ffi_c/libffi/.travis.yml +0 -83
  332. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_uchar_va.c +0 -44
  333. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_ushort_va.c +0 -44
  334. /data/ext/ffi_c/libffi/{.travis → .ci}/ar-lib +0 -0
  335. /data/ext/ffi_c/libffi/{.travis → .ci}/bfin-sim.exp +0 -0
  336. /data/ext/ffi_c/libffi/{.travis → .ci}/compile +0 -0
  337. /data/ext/ffi_c/libffi/{.travis → .ci}/m32r-sim.exp +0 -0
  338. /data/ext/ffi_c/libffi/{.travis → .ci}/moxie-sim.exp +0 -0
  339. /data/ext/ffi_c/libffi/{.travis → .ci}/or1k-sim.exp +0 -0
  340. /data/ext/ffi_c/libffi/{.travis → .ci}/powerpc-eabisim.exp +0 -0
  341. /data/ext/ffi_c/libffi/{.travis → .ci}/wine-sim.exp +0 -0
  342. /data/ext/ffi_c/libffi/testsuite/libffi.call/{pyobjc-tc.c → pyobjc_tc.c} +0 -0
  343. /data/lib/ffi/platform/{sparc64-linux → sparcv9-linux}/types.conf +0 -0
data/ext/ffi_c/Function.c CHANGED
@@ -42,6 +42,10 @@
42
42
  #include <ruby.h>
43
43
  #include <ruby/thread.h>
44
44
 
45
+ #if HAVE_RB_EXT_RACTOR_SAFE
46
+ #include <ruby/ractor.h>
47
+ #endif
48
+
45
49
  #include <ffi.h>
46
50
  #if defined(HAVE_NATIVETHREAD) && !defined(_WIN32)
47
51
  #include <pthread.h>
@@ -65,6 +69,9 @@
65
69
  #include "MethodHandle.h"
66
70
  #include "Function.h"
67
71
 
72
+ #define DEFER_ASYNC_CALLBACK 1
73
+
74
+ struct async_cb_dispatcher;
68
75
  typedef struct Function_ {
69
76
  Pointer base;
70
77
  FunctionType* info;
@@ -73,10 +80,15 @@ typedef struct Function_ {
73
80
  Closure* closure;
74
81
  VALUE rbProc;
75
82
  VALUE rbFunctionInfo;
83
+ #if defined(DEFER_ASYNC_CALLBACK)
84
+ struct async_cb_dispatcher *dispatcher;
85
+ #endif
76
86
  } Function;
77
87
 
78
- static void function_mark(Function *);
79
- static void function_free(Function *);
88
+ static void function_mark(void *data);
89
+ static void function_compact(void *data);
90
+ static void function_free(void *data);
91
+ static size_t function_memsize(const void *data);
80
92
  static VALUE function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc);
81
93
  static void callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data);
82
94
  static bool callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize);
@@ -84,9 +96,6 @@ static void* callback_with_gvl(void* data);
84
96
  static VALUE invoke_callback(VALUE data);
85
97
  static VALUE save_callback_exception(VALUE data, VALUE exc);
86
98
 
87
- #define DEFER_ASYNC_CALLBACK 1
88
-
89
-
90
99
  #if defined(DEFER_ASYNC_CALLBACK)
91
100
  static VALUE async_cb_event(void *);
92
101
  static VALUE async_cb_call(void *);
@@ -95,11 +104,21 @@ static VALUE async_cb_call(void *);
95
104
  extern int ruby_thread_has_gvl_p(void);
96
105
  extern int ruby_native_thread_p(void);
97
106
 
98
- VALUE rbffi_FunctionClass = Qnil;
107
+ static const rb_data_type_t function_data_type = {
108
+ .wrap_struct_name = "FFI::Function",
109
+ .function = {
110
+ .dmark = function_mark,
111
+ .dfree = function_free,
112
+ .dsize = function_memsize,
113
+ ffi_compact_callback( function_compact )
114
+ },
115
+ .parent = &rbffi_pointer_data_type,
116
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
117
+ // macro to update VALUE references, as to trigger write barriers.
118
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | FFI_RUBY_TYPED_FROZEN_SHAREABLE
119
+ };
99
120
 
100
- #if defined(DEFER_ASYNC_CALLBACK)
101
- static VALUE async_cb_thread = Qnil;
102
- #endif
121
+ VALUE rbffi_FunctionClass = Qnil;
103
122
 
104
123
  static ID id_call = 0, id_to_native = 0, id_from_native = 0, id_cbtable = 0, id_cb_ref = 0;
105
124
 
@@ -110,7 +129,10 @@ struct gvl_callback {
110
129
  bool done;
111
130
  rbffi_frame_t *frame;
112
131
  #if defined(DEFER_ASYNC_CALLBACK)
132
+ struct async_cb_dispatcher *dispatcher;
113
133
  struct gvl_callback* next;
134
+
135
+ /* Signal when the callback has finished and retval is set */
114
136
  # ifndef _WIN32
115
137
  pthread_cond_t async_cond;
116
138
  pthread_mutex_t async_mutex;
@@ -122,16 +144,78 @@ struct gvl_callback {
122
144
 
123
145
 
124
146
  #if defined(DEFER_ASYNC_CALLBACK)
125
- static struct gvl_callback* async_cb_list = NULL;
147
+ struct async_cb_dispatcher {
148
+ /* the Ractor-local dispatcher thread */
149
+ VALUE thread;
150
+
151
+ /* single linked list of pending callbacks */
152
+ struct gvl_callback* async_cb_list;
153
+
154
+ /* Signal new entries in async_cb_list */
126
155
  # ifndef _WIN32
127
- static pthread_mutex_t async_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
128
- static pthread_cond_t async_cb_cond = PTHREAD_COND_INITIALIZER;
156
+ pthread_mutex_t async_cb_mutex;
157
+ pthread_cond_t async_cb_cond;
129
158
  # else
130
- static HANDLE async_cb_cond;
131
- static CRITICAL_SECTION async_cb_lock;
159
+ HANDLE async_cb_cond;
160
+ CRITICAL_SECTION async_cb_lock;
132
161
  # endif
133
- #endif
162
+ };
134
163
 
164
+ #if HAVE_RB_EXT_RACTOR_SAFE
165
+ static void
166
+ async_cb_dispatcher_mark(void *ptr)
167
+ {
168
+ struct async_cb_dispatcher *ctx = (struct async_cb_dispatcher *)ptr;
169
+ if (ctx) {
170
+ rb_gc_mark(ctx->thread);
171
+ }
172
+ }
173
+
174
+ static void
175
+ async_cb_dispatcher_free(void *ptr)
176
+ {
177
+ struct async_cb_dispatcher *ctx = (struct async_cb_dispatcher *)ptr;
178
+ if (ctx) {
179
+ xfree(ctx);
180
+ }
181
+ }
182
+
183
+ struct rb_ractor_local_storage_type async_cb_dispatcher_key_type = {
184
+ async_cb_dispatcher_mark,
185
+ async_cb_dispatcher_free,
186
+ };
187
+
188
+ static rb_ractor_local_key_t async_cb_dispatcher_key;
189
+
190
+ static struct async_cb_dispatcher *
191
+ async_cb_dispatcher_get(void)
192
+ {
193
+ struct async_cb_dispatcher *ctx = (struct async_cb_dispatcher *)rb_ractor_local_storage_ptr(async_cb_dispatcher_key);
194
+ return ctx;
195
+ }
196
+
197
+ static void
198
+ async_cb_dispatcher_set(struct async_cb_dispatcher *ctx)
199
+ {
200
+ rb_ractor_local_storage_ptr_set(async_cb_dispatcher_key, ctx);
201
+ }
202
+ #else
203
+ // for ruby 2.x
204
+ static struct async_cb_dispatcher *async_cb_dispatcher = NULL;
205
+
206
+ static struct async_cb_dispatcher *
207
+ async_cb_dispatcher_get(void)
208
+ {
209
+ return async_cb_dispatcher;
210
+ }
211
+
212
+ static void
213
+ async_cb_dispatcher_set(struct async_cb_dispatcher *ctx)
214
+ {
215
+ async_cb_dispatcher = ctx;
216
+ }
217
+ #endif
218
+ #endif
135
219
 
136
220
  static VALUE
137
221
  function_allocate(VALUE klass)
@@ -139,28 +223,39 @@ function_allocate(VALUE klass)
139
223
  Function *fn;
140
224
  VALUE obj;
141
225
 
142
- obj = Data_Make_Struct(klass, Function, function_mark, function_free, fn);
226
+ obj = TypedData_Make_Struct(klass, Function, &function_data_type, fn);
143
227
 
144
228
  fn->base.memory.flags = MEM_RD;
145
- fn->base.rbParent = Qnil;
146
- fn->rbProc = Qnil;
147
- fn->rbFunctionInfo = Qnil;
229
+ RB_OBJ_WRITE(obj, &fn->base.rbParent, Qnil);
230
+ RB_OBJ_WRITE(obj, &fn->rbProc, Qnil);
231
+ RB_OBJ_WRITE(obj, &fn->rbFunctionInfo, Qnil);
148
232
  fn->autorelease = true;
149
233
 
150
234
  return obj;
151
235
  }
152
236
 
153
237
  static void
154
- function_mark(Function *fn)
238
+ function_mark(void *data)
155
239
  {
156
- rb_gc_mark(fn->base.rbParent);
157
- rb_gc_mark(fn->rbProc);
158
- rb_gc_mark(fn->rbFunctionInfo);
240
+ Function *fn = (Function *)data;
241
+ rb_gc_mark_movable(fn->base.rbParent);
242
+ rb_gc_mark_movable(fn->rbProc);
243
+ rb_gc_mark_movable(fn->rbFunctionInfo);
159
244
  }
160
245
 
161
246
  static void
162
- function_free(Function *fn)
247
+ function_compact(void *data)
163
248
  {
249
+ Function *fn = (Function *)data;
250
+ ffi_gc_location(fn->base.rbParent);
251
+ ffi_gc_location(fn->rbProc);
252
+ ffi_gc_location(fn->rbFunctionInfo);
253
+ }
254
+
255
+ static void
256
+ function_free(void *data)
257
+ {
258
+ Function *fn = (Function *)data;
164
259
  if (fn->methodHandle != NULL) {
165
260
  rbffi_MethodHandle_Free(fn->methodHandle);
166
261
  }
@@ -172,6 +267,20 @@ function_free(Function *fn)
172
267
  xfree(fn);
173
268
  }
174
269
 
270
+ static size_t
271
+ function_memsize(const void *data)
272
+ {
273
+ const Function *fn = (const Function *)data;
274
+ size_t memsize = sizeof(Function);
275
+
276
+ // Would be nice to better account for MethodHandle and Closure too.
277
+ if (fn->closure) {
278
+ memsize += sizeof(Closure);
279
+ }
280
+
281
+ return memsize;
282
+ }
283
+
175
284
  /*
176
285
  * @param [Type, Symbol] return_type return type for the function
177
286
  * @param [Array<Type, Symbol>] param_types array of parameters types
@@ -254,7 +363,7 @@ rbffi_Function_ForProc(VALUE rbFunctionInfo, VALUE proc)
254
363
  /* If the first callback reference has the same function function signature, use it */
255
364
  if (cbref != Qnil && CLASS_OF(cbref) == rbffi_FunctionClass) {
256
365
  Function* fp;
257
- Data_Get_Struct(cbref, Function, fp);
366
+ TypedData_Get_Struct(cbref, Function, &function_data_type, fp);
258
367
  if (fp->rbFunctionInfo == rbFunctionInfo) {
259
368
  return cbref;
260
369
  }
@@ -287,9 +396,7 @@ static void
287
396
  after_fork_callback(void)
288
397
  {
289
398
  /* Ensure that a new dispatcher thread is started in a forked process */
290
- async_cb_thread = Qnil;
291
- pthread_mutex_init(&async_cb_mutex, NULL);
292
- pthread_cond_init(&async_cb_cond, NULL);
399
+ async_cb_dispatcher_set(NULL);
293
400
  }
294
401
  #endif
295
402
 
@@ -298,17 +405,17 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)
298
405
  {
299
406
  Function* fn = NULL;
300
407
 
301
- Data_Get_Struct(self, Function, fn);
408
+ TypedData_Get_Struct(self, Function, &function_data_type, fn);
302
409
 
303
- fn->rbFunctionInfo = rbFunctionInfo;
410
+ RB_OBJ_WRITE(self, &fn->rbFunctionInfo, rbFunctionInfo);
304
411
 
305
- Data_Get_Struct(fn->rbFunctionInfo, FunctionType, fn->info);
412
+ TypedData_Get_Struct(fn->rbFunctionInfo, FunctionType, &rbffi_fntype_data_type, fn->info);
306
413
 
307
414
  if (rb_obj_is_kind_of(rbProc, rbffi_PointerClass)) {
308
415
  Pointer* orig;
309
- Data_Get_Struct(rbProc, Pointer, orig);
416
+ TypedData_Get_Struct(rbProc, Pointer, &rbffi_pointer_data_type, orig);
310
417
  fn->base.memory = orig->memory;
311
- fn->base.rbParent = rbProc;
418
+ RB_OBJ_WRITE(self, &fn->base.rbParent, rbProc);
312
419
 
313
420
  } else if (rb_obj_is_kind_of(rbProc, rb_cProc) || rb_respond_to(rbProc, id_call)) {
314
421
  if (fn->info->closurePool == NULL) {
@@ -319,17 +426,30 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)
319
426
  }
320
427
 
321
428
  #if defined(DEFER_ASYNC_CALLBACK)
322
- if (async_cb_thread == Qnil) {
429
+ {
430
+ struct async_cb_dispatcher *ctx = async_cb_dispatcher_get();
431
+ if (ctx == NULL) {
432
+ ctx = (struct async_cb_dispatcher*)ALLOC(struct async_cb_dispatcher);
433
+ ctx->async_cb_list = NULL;
323
434
 
324
435
  #if !defined(_WIN32)
325
- if( pthread_atfork(NULL, NULL, after_fork_callback) ){
326
- rb_warn("FFI: unable to register fork callback");
327
- }
436
+ pthread_mutex_init(&ctx->async_cb_mutex, NULL);
437
+ pthread_cond_init(&ctx->async_cb_cond, NULL);
438
+ if( pthread_atfork(NULL, NULL, after_fork_callback) ){
439
+ rb_warn("FFI: unable to register fork callback");
440
+ }
441
+ #else
442
+ InitializeCriticalSection(&ctx->async_cb_lock);
443
+ ctx->async_cb_cond = CreateEvent(NULL, FALSE, FALSE, NULL);
328
444
  #endif
445
+ ctx->thread = rb_thread_create(async_cb_event, ctx);
329
446
 
330
- async_cb_thread = rb_thread_create(async_cb_event, NULL);
331
- /* Name thread, for better debugging */
332
- rb_funcall(async_cb_thread, rb_intern("name="), 1, rb_str_new2("FFI Callback Dispatcher"));
447
+ /* Name thread, for better debugging */
448
+ rb_funcall(ctx->thread, rb_intern("name="), 1, rb_str_new2("FFI Callback Dispatcher"));
449
+
450
+ async_cb_dispatcher_set(ctx);
451
+ }
452
+ fn->dispatcher = ctx;
333
453
  }
334
454
  #endif
335
455
 
@@ -344,7 +464,7 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)
344
464
  rb_obj_classname(rbProc));
345
465
  }
346
466
 
347
- fn->rbProc = rbProc;
467
+ RB_OBJ_WRITE(self, &fn->rbProc, rbProc);
348
468
 
349
469
  return self;
350
470
  }
@@ -360,7 +480,7 @@ function_call(int argc, VALUE* argv, VALUE self)
360
480
  {
361
481
  Function* fn;
362
482
 
363
- Data_Get_Struct(self, Function, fn);
483
+ TypedData_Get_Struct(self, Function, &function_data_type, fn);
364
484
 
365
485
  return (*fn->info->invoke)(argc, argv, fn->base.memory.address, fn->info);
366
486
  }
@@ -376,9 +496,9 @@ static VALUE
376
496
  function_attach(VALUE self, VALUE module, VALUE name)
377
497
  {
378
498
  Function* fn;
379
- char var[1024];
380
499
 
381
- Data_Get_Struct(self, Function, fn);
500
+ StringValue(name);
501
+ TypedData_Get_Struct(self, Function, &function_data_type, fn);
382
502
 
383
503
  if (fn->info->parameterCount == -1) {
384
504
  rb_raise(rb_eRuntimeError, "cannot attach variadic functions");
@@ -394,12 +514,6 @@ function_attach(VALUE self, VALUE module, VALUE name)
394
514
  fn->methodHandle = rbffi_MethodHandle_Alloc(fn->info, fn->base.memory.address);
395
515
  }
396
516
 
397
- /*
398
- * Stash the Function in a module variable so it does not get garbage collected
399
- */
400
- snprintf(var, sizeof(var), "@@%s", StringValueCStr(name));
401
- rb_cv_set(module, var, self);
402
-
403
517
  rb_define_singleton_method(module, StringValueCStr(name),
404
518
  rbffi_MethodHandle_CodeAddress(fn->methodHandle), -1);
405
519
 
@@ -421,7 +535,8 @@ function_set_autorelease(VALUE self, VALUE autorelease)
421
535
  {
422
536
  Function* fn;
423
537
 
424
- Data_Get_Struct(self, Function, fn);
538
+ rb_check_frozen(self);
539
+ TypedData_Get_Struct(self, Function, &function_data_type, fn);
425
540
 
426
541
  fn->autorelease = RTEST(autorelease);
427
542
 
@@ -433,11 +548,21 @@ function_autorelease_p(VALUE self)
433
548
  {
434
549
  Function* fn;
435
550
 
436
- Data_Get_Struct(self, Function, fn);
551
+ TypedData_Get_Struct(self, Function, &function_data_type, fn);
437
552
 
438
553
  return fn->autorelease ? Qtrue : Qfalse;
439
554
  }
440
555
 
556
+ static VALUE
557
+ function_type(VALUE self)
558
+ {
559
+ Function* fn;
560
+
561
+ TypedData_Get_Struct(self, Function, &function_data_type, fn);
562
+
563
+ return fn->rbFunctionInfo;
564
+ }
565
+
441
566
  /*
442
567
  * call-seq: free
443
568
  * @return [self]
@@ -448,7 +573,7 @@ function_release(VALUE self)
448
573
  {
449
574
  Function* fn;
450
575
 
451
- Data_Get_Struct(self, Function, fn);
576
+ TypedData_Get_Struct(self, Function, &function_data_type, fn);
452
577
 
453
578
  if (fn->closure == NULL) {
454
579
  rb_raise(rb_eRuntimeError, "cannot free function which was not allocated");
@@ -463,6 +588,7 @@ function_release(VALUE self)
463
588
  static void
464
589
  callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
465
590
  {
591
+ Function* fn;
466
592
  struct gvl_callback cb = { 0 };
467
593
 
468
594
  cb.closure = (Closure *) user_data;
@@ -470,6 +596,7 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
470
596
  cb.parameters = parameters;
471
597
  cb.done = false;
472
598
  cb.frame = rbffi_frame_current();
599
+ fn = (Function *) cb.closure->info;
473
600
 
474
601
  if (cb.frame != NULL) cb.frame->exc = Qnil;
475
602
 
@@ -482,18 +609,19 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
482
609
  #if defined(DEFER_ASYNC_CALLBACK) && !defined(_WIN32)
483
610
  } else {
484
611
  bool empty = false;
612
+ struct async_cb_dispatcher *ctx = fn->dispatcher;
485
613
 
486
614
  pthread_mutex_init(&cb.async_mutex, NULL);
487
615
  pthread_cond_init(&cb.async_cond, NULL);
488
616
 
489
- /* Now signal the async callback thread */
490
- pthread_mutex_lock(&async_cb_mutex);
491
- empty = async_cb_list == NULL;
492
- cb.next = async_cb_list;
493
- async_cb_list = &cb;
617
+ /* Now signal the async callback dispatcher thread */
618
+ pthread_mutex_lock(&ctx->async_cb_mutex);
619
+ empty = ctx->async_cb_list == NULL;
620
+ cb.next = ctx->async_cb_list;
621
+ ctx->async_cb_list = &cb;
494
622
 
495
- pthread_cond_signal(&async_cb_cond);
496
- pthread_mutex_unlock(&async_cb_mutex);
623
+ pthread_cond_signal(&ctx->async_cb_cond);
624
+ pthread_mutex_unlock(&ctx->async_cb_mutex);
497
625
 
498
626
  /* Wait for the thread executing the ruby callback to signal it is done */
499
627
  pthread_mutex_lock(&cb.async_mutex);
@@ -507,17 +635,18 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
507
635
  #elif defined(DEFER_ASYNC_CALLBACK) && defined(_WIN32)
508
636
  } else {
509
637
  bool empty = false;
638
+ struct async_cb_dispatcher *ctx = fn->dispatcher;
510
639
 
511
640
  cb.async_event = CreateEvent(NULL, FALSE, FALSE, NULL);
512
641
 
513
- /* Now signal the async callback thread */
514
- EnterCriticalSection(&async_cb_lock);
515
- empty = async_cb_list == NULL;
516
- cb.next = async_cb_list;
517
- async_cb_list = &cb;
518
- LeaveCriticalSection(&async_cb_lock);
642
+ /* Now signal the async callback dispatcher thread */
643
+ EnterCriticalSection(&ctx->async_cb_lock);
644
+ empty = ctx->async_cb_list == NULL;
645
+ cb.next = ctx->async_cb_list;
646
+ ctx->async_cb_list = &cb;
647
+ LeaveCriticalSection(&ctx->async_cb_lock);
519
648
 
520
- SetEvent(async_cb_cond);
649
+ SetEvent(ctx->async_cb_cond);
521
650
 
522
651
  /* Wait for the thread executing the ruby callback to signal it is done */
523
652
  WaitForSingleObject(cb.async_event, INFINITE);
@@ -528,6 +657,7 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
528
657
 
529
658
  #if defined(DEFER_ASYNC_CALLBACK)
530
659
  struct async_wait {
660
+ struct async_cb_dispatcher *dispatcher;
531
661
  void* cb;
532
662
  bool stop;
533
663
  };
@@ -536,9 +666,10 @@ static void * async_cb_wait(void *);
536
666
  static void async_cb_stop(void *);
537
667
 
538
668
  static VALUE
539
- async_cb_event(void* unused)
669
+ async_cb_event(void* ptr)
540
670
  {
541
- struct async_wait w = { 0 };
671
+ struct async_cb_dispatcher *ctx = (struct async_cb_dispatcher *)ptr;
672
+ struct async_wait w = { ctx };
542
673
 
543
674
  w.stop = false;
544
675
  while (!w.stop) {
@@ -559,23 +690,24 @@ static void *
559
690
  async_cb_wait(void *data)
560
691
  {
561
692
  struct async_wait* w = (struct async_wait *) data;
693
+ struct async_cb_dispatcher *ctx = w->dispatcher;
562
694
 
563
695
  w->cb = NULL;
564
696
 
565
- EnterCriticalSection(&async_cb_lock);
697
+ EnterCriticalSection(&ctx->async_cb_lock);
566
698
 
567
- while (!w->stop && async_cb_list == NULL) {
568
- LeaveCriticalSection(&async_cb_lock);
569
- WaitForSingleObject(async_cb_cond, INFINITE);
570
- EnterCriticalSection(&async_cb_lock);
699
+ while (!w->stop && ctx->async_cb_list == NULL) {
700
+ LeaveCriticalSection(&ctx->async_cb_lock);
701
+ WaitForSingleObject(ctx->async_cb_cond, INFINITE);
702
+ EnterCriticalSection(&ctx->async_cb_lock);
571
703
  }
572
704
 
573
- if (async_cb_list != NULL) {
574
- w->cb = async_cb_list;
575
- async_cb_list = async_cb_list->next;
705
+ if (ctx->async_cb_list != NULL) {
706
+ w->cb = ctx->async_cb_list;
707
+ ctx->async_cb_list = ctx->async_cb_list->next;
576
708
  }
577
709
 
578
- LeaveCriticalSection(&async_cb_lock);
710
+ LeaveCriticalSection(&ctx->async_cb_lock);
579
711
 
580
712
  return NULL;
581
713
  }
@@ -584,11 +716,12 @@ static void
584
716
  async_cb_stop(void *data)
585
717
  {
586
718
  struct async_wait* w = (struct async_wait *) data;
719
+ struct async_cb_dispatcher *ctx = w->dispatcher;
587
720
 
588
- EnterCriticalSection(&async_cb_lock);
721
+ EnterCriticalSection(&ctx->async_cb_lock);
589
722
  w->stop = true;
590
- LeaveCriticalSection(&async_cb_lock);
591
- SetEvent(async_cb_cond);
723
+ LeaveCriticalSection(&ctx->async_cb_lock);
724
+ SetEvent(ctx->async_cb_cond);
592
725
  }
593
726
 
594
727
  #else
@@ -596,21 +729,22 @@ static void *
596
729
  async_cb_wait(void *data)
597
730
  {
598
731
  struct async_wait* w = (struct async_wait *) data;
732
+ struct async_cb_dispatcher *ctx = w->dispatcher;
599
733
 
600
734
  w->cb = NULL;
601
735
 
602
- pthread_mutex_lock(&async_cb_mutex);
736
+ pthread_mutex_lock(&ctx->async_cb_mutex);
603
737
 
604
- while (!w->stop && async_cb_list == NULL) {
605
- pthread_cond_wait(&async_cb_cond, &async_cb_mutex);
738
+ while (!w->stop && ctx->async_cb_list == NULL) {
739
+ pthread_cond_wait(&ctx->async_cb_cond, &ctx->async_cb_mutex);
606
740
  }
607
741
 
608
- if (async_cb_list != NULL) {
609
- w->cb = async_cb_list;
610
- async_cb_list = async_cb_list->next;
742
+ if (ctx->async_cb_list != NULL) {
743
+ w->cb = ctx->async_cb_list;
744
+ ctx->async_cb_list = ctx->async_cb_list->next;
611
745
  }
612
746
 
613
- pthread_mutex_unlock(&async_cb_mutex);
747
+ pthread_mutex_unlock(&ctx->async_cb_mutex);
614
748
 
615
749
  return NULL;
616
750
  }
@@ -619,11 +753,12 @@ static void
619
753
  async_cb_stop(void *data)
620
754
  {
621
755
  struct async_wait* w = (struct async_wait *) data;
756
+ struct async_cb_dispatcher *ctx = w->dispatcher;
622
757
 
623
- pthread_mutex_lock(&async_cb_mutex);
758
+ pthread_mutex_lock(&ctx->async_cb_mutex);
624
759
  w->stop = true;
625
- pthread_cond_signal(&async_cb_cond);
626
- pthread_mutex_unlock(&async_cb_mutex);
760
+ pthread_cond_signal(&ctx->async_cb_cond);
761
+ pthread_mutex_unlock(&ctx->async_cb_mutex);
627
762
  }
628
763
  #endif
629
764
 
@@ -796,7 +931,9 @@ invoke_callback(VALUE data)
796
931
  break;
797
932
  case NATIVE_POINTER:
798
933
  if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
799
- *((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
934
+ AbstractMemory* memory;
935
+ TypedData_Get_Struct(rbReturnValue, AbstractMemory, &rbffi_abstract_memory_data_type, memory);
936
+ *((void **) retval) = memory->address;
800
937
  } else {
801
938
  /* Default to returning NULL if not a value pointer object. handles nil case as well */
802
939
  *((void **) retval) = NULL;
@@ -809,15 +946,20 @@ invoke_callback(VALUE data)
809
946
 
810
947
  case NATIVE_FUNCTION:
811
948
  if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
949
+ AbstractMemory* memory;
950
+ TypedData_Get_Struct(rbReturnValue, AbstractMemory, &rbffi_abstract_memory_data_type, memory);
812
951
 
813
- *((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
952
+ *((void **) retval) = memory->address;
814
953
 
815
954
  } else if (rb_obj_is_kind_of(rbReturnValue, rb_cProc) || rb_respond_to(rbReturnValue, id_call)) {
816
955
  VALUE function;
956
+ AbstractMemory* memory;
817
957
 
818
958
  function = rbffi_Function_ForProc(rbReturnType, rbReturnValue);
819
959
 
820
- *((void **) retval) = ((AbstractMemory *) DATA_PTR(function))->address;
960
+ TypedData_Get_Struct(function, AbstractMemory, &rbffi_abstract_memory_data_type, memory);
961
+
962
+ *((void **) retval) = memory->address;
821
963
  } else {
822
964
  *((void **) retval) = NULL;
823
965
  }
@@ -825,7 +967,11 @@ invoke_callback(VALUE data)
825
967
 
826
968
  case NATIVE_STRUCT:
827
969
  if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_StructClass)) {
828
- AbstractMemory* memory = ((Struct *) DATA_PTR(rbReturnValue))->pointer;
970
+ Struct* s;
971
+ AbstractMemory* memory;
972
+
973
+ TypedData_Get_Struct(rbReturnValue, Struct, &rbffi_struct_data_type, s);
974
+ memory = s->pointer;
829
975
 
830
976
  if (memory->address != NULL) {
831
977
  memcpy(retval, memory->address, returnType->ffiType->size);
@@ -891,6 +1037,7 @@ rbffi_Function_Init(VALUE moduleFFI)
891
1037
  rb_define_method(rbffi_FunctionClass, "attach", function_attach, 2);
892
1038
  rb_define_method(rbffi_FunctionClass, "free", function_release, 0);
893
1039
  rb_define_method(rbffi_FunctionClass, "autorelease=", function_set_autorelease, 1);
1040
+ rb_define_private_method(rbffi_FunctionClass, "type", function_type, 0);
894
1041
  /*
895
1042
  * call-seq: autorelease
896
1043
  * @return [Boolean]
@@ -910,8 +1057,7 @@ rbffi_Function_Init(VALUE moduleFFI)
910
1057
  id_cb_ref = rb_intern("@__ffi_callback__");
911
1058
  id_to_native = rb_intern("to_native");
912
1059
  id_from_native = rb_intern("from_native");
913
- #if defined(_WIN32)
914
- InitializeCriticalSection(&async_cb_lock);
915
- async_cb_cond = CreateEvent(NULL, FALSE, FALSE, NULL);
1060
+ #if defined(DEFER_ASYNC_CALLBACK) && defined(HAVE_RB_EXT_RACTOR_SAFE)
1061
+ async_cb_dispatcher_key = rb_ractor_local_storage_ptr_newkey(&async_cb_dispatcher_key_type);
916
1062
  #endif
917
1063
  }
data/ext/ffi_c/Function.h CHANGED
@@ -68,6 +68,7 @@ struct FunctionType_ {
68
68
  bool hasStruct;
69
69
  };
70
70
 
71
+ extern const rb_data_type_t rbffi_fntype_data_type;
71
72
  extern VALUE rbffi_FunctionTypeClass, rbffi_FunctionClass;
72
73
 
73
74
  void rbffi_Function_Init(VALUE moduleFFI);