ffi 1.16.3 → 1.17.1

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 (96) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +51 -0
  4. data/Gemfile +9 -2
  5. data/README.md +1 -1
  6. data/Rakefile +18 -6
  7. data/ext/ffi_c/AbstractMemory.c +39 -38
  8. data/ext/ffi_c/ArrayType.c +2 -2
  9. data/ext/ffi_c/Buffer.c +4 -4
  10. data/ext/ffi_c/Call.c +12 -6
  11. data/ext/ffi_c/Call.h +3 -2
  12. data/ext/ffi_c/DynamicLibrary.c +2 -2
  13. data/ext/ffi_c/Function.c +52 -34
  14. data/ext/ffi_c/FunctionInfo.c +1 -1
  15. data/ext/ffi_c/LastError.c +4 -4
  16. data/ext/ffi_c/MemoryPointer.c +2 -2
  17. data/ext/ffi_c/Pointer.c +14 -11
  18. data/ext/ffi_c/Struct.c +11 -4
  19. data/ext/ffi_c/StructLayout.c +13 -13
  20. data/ext/ffi_c/Type.c +17 -16
  21. data/ext/ffi_c/Types.c +7 -1
  22. data/ext/ffi_c/Types.h +0 -1
  23. data/ext/ffi_c/Variadic.c +6 -3
  24. data/ext/ffi_c/libffi/.allow-ai-service +0 -0
  25. data/ext/ffi_c/libffi/.github/workflows/build.yml +34 -15
  26. data/ext/ffi_c/libffi/.github/workflows/emscripten.yml +2 -1
  27. data/ext/ffi_c/libffi/LICENSE +1 -1
  28. data/ext/ffi_c/libffi/README.md +10 -5
  29. data/ext/ffi_c/libffi/configure +1254 -940
  30. data/ext/ffi_c/libffi/configure.ac +2 -2
  31. data/ext/ffi_c/libffi/configure.host +1 -1
  32. data/ext/ffi_c/libffi/doc/libffi.texi +1 -1
  33. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  34. data/ext/ffi_c/libffi/fficonfig.h.in +6 -6
  35. data/ext/ffi_c/libffi/include/ffi.h.in +2 -11
  36. data/ext/ffi_c/libffi/include/ffi_common.h +4 -2
  37. data/ext/ffi_c/libffi/libffi.map.in +5 -0
  38. data/ext/ffi_c/libffi/libtool-version +1 -1
  39. data/ext/ffi_c/libffi/ltmain.sh +8 -20
  40. data/ext/ffi_c/libffi/msvc_build/aarch64/aarch64_include/ffi.h +1 -1
  41. data/ext/ffi_c/libffi/src/aarch64/ffi.c +26 -13
  42. data/ext/ffi_c/libffi/src/aarch64/sysv.S +198 -46
  43. data/ext/ffi_c/libffi/src/closures.c +3 -3
  44. data/ext/ffi_c/libffi/src/debug.c +2 -2
  45. data/ext/ffi_c/libffi/src/dlmalloc.c +1 -1
  46. data/ext/ffi_c/libffi/src/loongarch64/ffi.c +3 -0
  47. data/ext/ffi_c/libffi/src/mips/ffi.c +12 -4
  48. data/ext/ffi_c/libffi/src/mips/n32.S +65 -14
  49. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +36 -24
  50. data/ext/ffi_c/libffi/src/sparc/ffi64.c +7 -1
  51. data/ext/ffi_c/libffi/src/tramp.c +1 -1
  52. data/ext/ffi_c/libffi/src/types.c +4 -6
  53. data/ext/ffi_c/libffi/src/wasm32/ffi.c +13 -0
  54. data/ext/ffi_c/libffi/src/x86/ffiw64.c +1 -1
  55. data/ext/ffi_c/libffi/testsuite/Makefile.am +79 -127
  56. data/ext/ffi_c/libffi/testsuite/Makefile.in +79 -127
  57. data/ext/ffi_c/libffi/testsuite/emscripten/conftest.py +6 -0
  58. data/ext/ffi_c/libffi/testsuite/libffi.call/callback.c +99 -0
  59. data/ext/ffi_c/libffi/testsuite/libffi.call/callback2.c +108 -0
  60. data/ext/ffi_c/libffi/testsuite/libffi.call/callback3.c +114 -0
  61. data/ext/ffi_c/libffi/testsuite/libffi.call/callback4.c +119 -0
  62. data/ext/ffi_c/libffi.darwin.mk +2 -2
  63. data/lib/ffi/autopointer.rb +1 -9
  64. data/lib/ffi/dynamic_library.rb +34 -5
  65. data/lib/ffi/enum.rb +0 -1
  66. data/lib/ffi/ffi.rb +59 -0
  67. data/lib/ffi/function.rb +1 -1
  68. data/lib/ffi/io.rb +2 -2
  69. data/lib/ffi/library.rb +23 -23
  70. data/lib/ffi/platform/aarch64-linux/types.conf +74 -3
  71. data/lib/ffi/pointer.rb +6 -6
  72. data/lib/ffi/struct.rb +4 -4
  73. data/lib/ffi/struct_layout.rb +2 -2
  74. data/lib/ffi/struct_layout_builder.rb +8 -8
  75. data/lib/ffi/types.rb +51 -49
  76. data/lib/ffi/version.rb +1 -1
  77. data/sig/ffi/abstract_memory.rbs +165 -0
  78. data/sig/ffi/auto_pointer.rbs +26 -0
  79. data/sig/ffi/buffer.rbs +18 -0
  80. data/sig/ffi/data_converter.rbs +10 -0
  81. data/sig/ffi/dynamic_library.rbs +9 -0
  82. data/sig/ffi/enum.rbs +38 -0
  83. data/sig/ffi/function.rbs +39 -0
  84. data/sig/ffi/library.rbs +42 -0
  85. data/sig/ffi/native_type.rbs +86 -0
  86. data/sig/ffi/pointer.rbs +42 -0
  87. data/sig/ffi/struct.rbs +76 -0
  88. data/sig/ffi/struct_by_reference.rbs +11 -0
  89. data/sig/ffi/struct_by_value.rbs +7 -0
  90. data/sig/ffi/struct_layout.rbs +9 -0
  91. data/sig/ffi/struct_layout_builder.rbs +5 -0
  92. data/sig/ffi/type.rbs +39 -0
  93. data/sig/ffi.rbs +26 -0
  94. data.tar.gz.sig +0 -0
  95. metadata +37 -18
  96. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5920bab18c2bfca946febdf9d31aae894569dd1a293d816631a077696f7db8fa
4
- data.tar.gz: 7aa17dd90399d15bd149573ab4b9857907028beae4f84409f76f50e9508aaba2
3
+ metadata.gz: 3a6a87ee152caf4030d9a90bedcefece7f4717639dc96443727b1e1c492db617
4
+ data.tar.gz: 722b6e07fb23b25c2ad2c2e426040e2fb3f929e6dda3c00c26ac7fbc7c7820aa
5
5
  SHA512:
6
- metadata.gz: dd42730736988cac47f45485f4a8b200c26759066fe156a89ef7736cd6ac80f404e8aaced28a8f10f9b22b43436ed3e248cb191f1c457ccabc19299b91b49174
7
- data.tar.gz: '0252969e7a324d530c1d704e2d408f1bd7283f320de90b4c98f20bb49f9d32733ac45609d78a40f821cd5335e102e80576fd446cd5de863babea041d0eb3c780'
6
+ metadata.gz: a4b65f1f9f9852a7d74c0739eb940f487a85354466b998caf4e637b20046c91a4338c389992de8d42118536624db2bbab4b4de799477af3591701e823355a69c
7
+ data.tar.gz: 6877266da6f47d6d921b8535ee63737caefeb89a937489a1c4756273b87bdcfec93f13e5c9a4dd7c7c56a680d0b1822aecf0197b9b92f778778732cf9fa6556e
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,3 +1,54 @@
1
+ 1.17.1 / 2024-12-30
2
+ -------------------
3
+
4
+ Fixed:
5
+ * #1117 Restart async callback dispatcher thread after fork.
6
+ * #1133 Add ruby-3.4 native gem.
7
+ * #1134 Fix FFI::DataConverter non-generic usage in RBS files.
8
+
9
+
10
+ 1.17.0 / 2024-06-02
11
+ -------------------
12
+
13
+ Fixed:
14
+ * Add FFI::AbstractMemory#read_array_of_string . It was defined but not exposed to Ruby nor tested. #1070
15
+
16
+
17
+ 1.17.0.rc2 / 2024-04-22
18
+ -------------------
19
+
20
+ Fixed:
21
+ * Add missing write barriers to StructLayout#initialize causing a segfault with GC.stress. #1079
22
+
23
+
24
+ 1.17.0.rc1 / 2024-04-08
25
+ -------------------
26
+
27
+ Fixed:
28
+ * Fix type definitions on `aarch64-linux`. #1067, #1066
29
+ * Use RB_TEST for `Pointer.autorelease=` . #1065
30
+ So that `false` and `nil` are treated as falsey and anything else as truthy.
31
+ * Replace Fixnum by Integer. #1064
32
+ Fixnum is no longer present in the ruby language.
33
+ * Update `FFI::NativeType` doc. #1061
34
+ * Store FFI::Type::Mapped of FFI::StrPtrConverter in global instead of custom type map
35
+ * Various documentation fixes. #1042
36
+ * Update `FFI::Pointer#==` to return `false` if a pointer is compared to a non-pointer object, which is the expected behavior. #1083
37
+ * Avoid warning about undefined wariable `@ffi_functions` #1085
38
+ * Fix a very unlikely GC bug when using a callback block. # 1089
39
+
40
+ Added:
41
+ * Provide binary gems for many platforms. #990
42
+ * Add Windows fat binary gem for Ruby-3.3
43
+ * Add RBS type definitions for many user facing parts of the FFI API. #1042
44
+ * Improve fallback search path logic. #1088
45
+ Respect LD_LIBRARY_PATH and DYLD_LIBRARY_PATH on Macos.
46
+ * Update libffi to current git master branch.
47
+
48
+ Removed:
49
+ * Remove `enum CHAR_ARRAY` which is no longer used. #1063
50
+
51
+
1
52
  1.16.3 / 2023-10-04
2
53
  -------------------
3
54
 
data/Gemfile CHANGED
@@ -1,14 +1,21 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  group :development do
4
+ gem 'bigdecimal' # necessary on ruby-3.3+
5
+ gem 'bundler', '>= 1.16', '< 3'
4
6
  gem 'rake', '~> 13.0'
5
7
  gem 'rake-compiler', '~> 1.1'
6
- gem 'rake-compiler-dock', '~> 1.0'
8
+ gem 'rake-compiler-dock', '~> 1.7.0'
7
9
  gem 'rspec', '~> 3.0'
8
- gem 'bundler', '>= 1.16', '< 3'
9
10
  end
10
11
 
11
12
  group :doc do
12
13
  gem 'kramdown'
13
14
  gem 'yard', '~> 0.9'
14
15
  end
16
+
17
+ group :type_check do
18
+ if RUBY_VERSION >= "2.6" && %w[ ruby truffleruby ].include?(RUBY_ENGINE)
19
+ gem 'rbs', '~> 3.0'
20
+ end
21
+ end
data/README.md CHANGED
@@ -114,7 +114,7 @@ The following people have submitted code, bug reports, or otherwise contributed
114
114
  * Jurij Smakov <jurij@wooyd.org>
115
115
  * KISHIMOTO, Makoto <ksmakoto@dd.iij4u.or.jp>
116
116
  * Kim Burgestrand <kim@burgestrand.se>
117
- * Lars Kanis <kanis@comcard.de>
117
+ * Lars Kanis <lars@greiz-reinsdorf.de>
118
118
  * Luc Heinrich <luc@honk-honk.com>
119
119
  * Luis Lavena <luislavena@gmail.com>
120
120
  * Matijs van Zuijlen <matijs@matijs.net>
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ BUILD_EXT_DIR = File.join(BUILD_DIR, "#{RbConfig::CONFIG['arch']}", 'ffi_c', RUB
13
13
 
14
14
  gem_spec = Bundler.load_gemspec('ffi.gemspec')
15
15
 
16
- RSpec::Core::RakeTask.new(:spec => :compile) do |config|
16
+ RSpec::Core::RakeTask.new(:spec) do |config|
17
17
  config.rspec_opts = YAML.load_file 'spec/spec.opts'
18
18
  end
19
19
 
@@ -84,10 +84,22 @@ end
84
84
  task 'gem:java' => 'java:gem'
85
85
 
86
86
  FfiGemHelper.install_tasks
87
- # Register windows gems to be pushed to rubygems.org
88
- Bundler::GemHelper.instance.cross_platforms = %w[x86-mingw32 x64-mingw-ucrt x64-mingw32]
89
- # These platforms are not yet enabled, since there are issues on musl-based distors (alpine-linux):
90
- # + %w[x86-linux x86_64-linux arm-linux aarch64-linux x86_64-darwin arm64-darwin]
87
+ # Register binary gems to be pushed to rubygems.org
88
+ Bundler::GemHelper.instance.cross_platforms = %w[
89
+ x86-mingw32
90
+ x64-mingw-ucrt
91
+ x64-mingw32
92
+ x86-linux-gnu
93
+ x86-linux-musl
94
+ x86_64-linux-gnu
95
+ x86_64-linux-musl
96
+ arm-linux-gnu
97
+ arm-linux-musl
98
+ aarch64-linux-gnu
99
+ aarch64-linux-musl
100
+ x86_64-darwin
101
+ arm64-darwin
102
+ ]
91
103
 
92
104
  if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
93
105
  require 'rake/extensiontask'
@@ -124,7 +136,7 @@ namespace "gem" do
124
136
  desc "Build the native gem for #{plat}"
125
137
  task plat => ['prepare', 'build'] do
126
138
  RakeCompilerDock.sh <<-EOT, platform: plat
127
- #{ "sudo apt-get update && sudo apt-get install -y libltdl-dev &&" if plat !~ /linux/ }
139
+ sudo apt-get update && sudo apt-get install -y libltdl-dev &&
128
140
  bundle --local &&
129
141
  rake native:#{plat} pkg/#{gem_spec.full_name}-#{plat}.gem MAKE='nice make -j`nproc`' RUBY_CC_VERSION=${RUBY_CC_VERSION/:2.4.0/}
130
142
  EOT
@@ -324,7 +324,7 @@ memory_clear(VALUE self)
324
324
  /*
325
325
  * call-seq: memory.size
326
326
  * Return memory size in bytes (alias: #total)
327
- * @return [Numeric]
327
+ * @return [Integer]
328
328
  */
329
329
  static VALUE
330
330
  memory_size(VALUE self)
@@ -340,7 +340,7 @@ memory_size(VALUE self)
340
340
  * call-seq: memory.get(type, offset)
341
341
  * Return data of given type contained in memory.
342
342
  * @param [Symbol, Type] type_name type of data to get
343
- * @param [Numeric] offset point in buffer to start from
343
+ * @param [Integer] offset point in buffer to start from
344
344
  * @return [Object]
345
345
  * @raise {ArgumentError} if type is not supported
346
346
  */
@@ -373,7 +373,7 @@ undefined_type: {
373
373
  /*
374
374
  * call-seq: memory.put(type, offset, value)
375
375
  * @param [Symbol, Type] type_name type of data to put
376
- * @param [Numeric] offset point in buffer to start from
376
+ * @param [Integer] offset point in buffer to start from
377
377
  * @return [nil]
378
378
  * @raise {ArgumentError} if type is not supported
379
379
  */
@@ -407,8 +407,8 @@ undefined_type: {
407
407
  /*
408
408
  * call-seq: memory.get_string(offset, length=nil)
409
409
  * Return string contained in memory.
410
- * @param [Numeric] offset point in buffer to start from
411
- * @param [Numeric] length string's length in bytes. If nil, a (memory size - offset) length string is returned).
410
+ * @param [Integer] offset point in buffer to start from
411
+ * @param [Integer] length string's length in bytes. If nil, a (memory size - offset) length string is returned).
412
412
  * @return [String]
413
413
  * @raise {IndexError} if +length+ is too great
414
414
  * @raise {NullPointerError} if memory not initialized
@@ -435,8 +435,8 @@ memory_get_string(int argc, VALUE* argv, VALUE self)
435
435
  /*
436
436
  * call-seq: memory.get_array_of_string(offset, count=nil)
437
437
  * Return an array of strings contained in memory.
438
- * @param [Numeric] offset point in memory to start from
439
- * @param [Numeric] count number of strings to get. If nil, return all strings
438
+ * @param [Integer] offset point in memory to start from
439
+ * @param [Integer] count number of strings to get. If nil, return all strings
440
440
  * @return [Array<String>]
441
441
  * @raise {IndexError} if +offset+ is too great
442
442
  * @raise {NullPointerError} if memory not initialized
@@ -485,7 +485,7 @@ memory_get_array_of_string(int argc, VALUE* argv, VALUE self)
485
485
  * call-seq: memory.read_array_of_string(count=nil)
486
486
  * Return an array of strings contained in memory. Same as:
487
487
  * memory.get_array_of_string(0, count)
488
- * @param [Numeric] count number of strings to get. If nil, return all strings
488
+ * @param [Integer] count number of strings to get. If nil, return all strings
489
489
  * @return [Array<String>]
490
490
  */
491
491
  static VALUE
@@ -505,7 +505,7 @@ memory_read_array_of_string(int argc, VALUE* argv, VALUE self)
505
505
 
506
506
  /*
507
507
  * call-seq: memory.put_string(offset, str)
508
- * @param [Numeric] offset
508
+ * @param [Integer] offset
509
509
  * @param [String] str
510
510
  * @return [self]
511
511
  * @raise {SecurityError} when writing unsafe string to memory
@@ -535,8 +535,8 @@ memory_put_string(VALUE self, VALUE offset, VALUE str)
535
535
  /*
536
536
  * call-seq: memory.get_bytes(offset, length)
537
537
  * Return string contained in memory.
538
- * @param [Numeric] offset point in buffer to start from
539
- * @param [Numeric] length string's length in bytes.
538
+ * @param [Integer] offset point in buffer to start from
539
+ * @param [Integer] length string's length in bytes.
540
540
  * @return [String]
541
541
  * @raise {IndexError} if +length+ is too great
542
542
  * @raise {NullPointerError} if memory not initialized
@@ -559,10 +559,10 @@ memory_get_bytes(VALUE self, VALUE offset, VALUE length)
559
559
  /*
560
560
  * call-seq: memory.put_bytes(offset, str, index=0, length=nil)
561
561
  * Put a string in memory.
562
- * @param [Numeric] offset point in buffer to start from
562
+ * @param [Integer] offset point in buffer to start from
563
563
  * @param [String] str string to put to memory
564
- * @param [Numeric] index
565
- * @param [Numeric] length string's length in bytes. If nil, a (memory size - offset) length string is returned).
564
+ * @param [Integer] index
565
+ * @param [Integer] length string's length in bytes. If nil, a (memory size - offset) length string is returned).
566
566
  * @return [self]
567
567
  * @raise {IndexError} if +length+ is too great
568
568
  * @raise {NullPointerError} if memory not initialized
@@ -601,7 +601,7 @@ memory_put_bytes(int argc, VALUE* argv, VALUE self)
601
601
 
602
602
  /*
603
603
  * call-seq: memory.read_bytes(length)
604
- * @param [Numeric] length of string to return
604
+ * @param [Integer] length of string to return
605
605
  * @return [String]
606
606
  * equivalent to :
607
607
  * memory.get_bytes(0, length)
@@ -615,8 +615,8 @@ memory_read_bytes(VALUE self, VALUE length)
615
615
  /*
616
616
  * call-seq: memory.write_bytes(str, index=0, length=nil)
617
617
  * @param [String] str string to put to memory
618
- * @param [Numeric] index
619
- * @param [Numeric] length string's length in bytes. If nil, a (memory size - offset) length string is returned).
618
+ * @param [Integer] index
619
+ * @param [Integer] length string's length in bytes. If nil, a (memory size - offset) length string is returned).
620
620
  * @return [self]
621
621
  * equivalent to :
622
622
  * memory.put_bytes(0, str, index, length)
@@ -637,7 +637,7 @@ memory_write_bytes(int argc, VALUE* argv, VALUE self)
637
637
 
638
638
  /*
639
639
  * call-seq: memory.type_size
640
- * @return [Numeric] type size in bytes
640
+ * @return [Integer] type size in bytes
641
641
  * Get the memory's type size.
642
642
  */
643
643
  static VALUE
@@ -653,7 +653,7 @@ memory_type_size(VALUE self)
653
653
  /*
654
654
  * Document-method: []
655
655
  * call-seq: memory[idx]
656
- * @param [Numeric] idx index to access in memory
656
+ * @param [Integer] idx index to access in memory
657
657
  * @return
658
658
  * Memory read accessor.
659
659
  */
@@ -861,8 +861,8 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
861
861
 
862
862
  /*
863
863
  * Document-method: put_float32
864
- * call-seq: memory.put_float32offset, value)
865
- * @param [Numeric] offset
864
+ * call-seq: memory.put_float32(offset, value)
865
+ * @param [Integer] offset
866
866
  * @param [Numeric] value
867
867
  * @return [self]
868
868
  * Put +value+ as a 32-bit float in memory at offset +offset+ (alias: #put_float).
@@ -871,7 +871,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
871
871
  /*
872
872
  * Document-method: get_float32
873
873
  * call-seq: memory.get_float32(offset)
874
- * @param [Numeric] offset
874
+ * @param [Integer] offset
875
875
  * @return [Float]
876
876
  * Get a 32-bit float from memory at offset +offset+ (alias: #get_float).
877
877
  */
@@ -902,7 +902,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
902
902
  /*
903
903
  * Document-method: put_array_of_float32
904
904
  * call-seq: memory.put_array_of_float32(offset, ary)
905
- * @param [Numeric] offset
905
+ * @param [Integer] offset
906
906
  * @param [Array<Numeric>] ary
907
907
  * @return [self]
908
908
  * Put values from +ary+ as 32-bit floats in memory from offset +offset+ (alias: #put_array_of_float).
@@ -911,8 +911,8 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
911
911
  /*
912
912
  * Document-method: get_array_of_float32
913
913
  * call-seq: memory.get_array_of_float32(offset, length)
914
- * @param [Numeric] offset
915
- * @param [Numeric] length number of Float to get
914
+ * @param [Integer] offset
915
+ * @param [Integer] length number of Float to get
916
916
  * @return [Array<Float>]
917
917
  * Get 32-bit floats in memory from offset +offset+ (alias: #get_array_of_float).
918
918
  */
@@ -931,7 +931,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
931
931
  /*
932
932
  * Document-method: read_array_of_float
933
933
  * call-seq: memory.read_array_of_float(length)
934
- * @param [Numeric] length number of Float to read
934
+ * @param [Integer] length number of Float to read
935
935
  * @return [Array<Float>]
936
936
  * Read 32-bit floats from memory.
937
937
  *
@@ -944,7 +944,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
944
944
  /*
945
945
  * Document-method: put_float64
946
946
  * call-seq: memory.put_float64(offset, value)
947
- * @param [Numeric] offset
947
+ * @param [Integer] offset
948
948
  * @param [Numeric] value
949
949
  * @return [self]
950
950
  * Put +value+ as a 64-bit float (double) in memory at offset +offset+ (alias: #put_double).
@@ -953,7 +953,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
953
953
  /*
954
954
  * Document-method: get_float64
955
955
  * call-seq: memory.get_float64(offset)
956
- * @param [Numeric] offset
956
+ * @param [Integer] offset
957
957
  * @return [Float]
958
958
  * Get a 64-bit float (double) from memory at offset +offset+ (alias: #get_double).
959
959
  */
@@ -984,7 +984,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
984
984
  /*
985
985
  * Document-method: put_array_of_float64
986
986
  * call-seq: memory.put_array_of_float64(offset, ary)
987
- * @param [Numeric] offset
987
+ * @param [Integer] offset
988
988
  * @param [Array<Numeric>] ary
989
989
  * @return [self]
990
990
  * Put values from +ary+ as 64-bit floats (doubles) in memory from offset +offset+ (alias: #put_array_of_double).
@@ -993,8 +993,8 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
993
993
  /*
994
994
  * Document-method: get_array_of_float64
995
995
  * call-seq: memory.get_array_of_float64(offset, length)
996
- * @param [Numeric] offset
997
- * @param [Numeric] length number of Float to get
996
+ * @param [Integer] offset
997
+ * @param [Integer] length number of Float to get
998
998
  * @return [Array<Float>]
999
999
  * Get 64-bit floats (doubles) in memory from offset +offset+ (alias: #get_array_of_double).
1000
1000
  */
@@ -1013,7 +1013,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
1013
1013
  /*
1014
1014
  * Document-method: read_array_of_double
1015
1015
  * call-seq: memory.read_array_of_double(length)
1016
- * @param [Numeric] length number of Float to read
1016
+ * @param [Integer] length number of Float to read
1017
1017
  * @return [Array<Float>]
1018
1018
  * Read 64-bit floats (doubles) from memory.
1019
1019
  *
@@ -1026,7 +1026,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
1026
1026
  /*
1027
1027
  * Document-method: put_pointer
1028
1028
  * call-seq: memory.put_pointer(offset, value)
1029
- * @param [Numeric] offset
1029
+ * @param [Integer] offset
1030
1030
  * @param [nil,Pointer, Integer, #to_ptr] value
1031
1031
  * @return [self]
1032
1032
  * Put +value+ in memory from +offset+..
@@ -1035,7 +1035,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
1035
1035
  /*
1036
1036
  * Document-method: get_pointer
1037
1037
  * call-seq: memory.get_pointer(offset)
1038
- * @param [Numeric] offset
1038
+ * @param [Integer] offset
1039
1039
  * @return [Pointer]
1040
1040
  * Get a {Pointer} to the memory from +offset+.
1041
1041
  */
@@ -1064,7 +1064,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
1064
1064
  /*
1065
1065
  * Document-method: put_array_of_pointer
1066
1066
  * call-seq: memory.put_array_of_pointer(offset, ary)
1067
- * @param [Numeric] offset
1067
+ * @param [Integer] offset
1068
1068
  * @param [Array<#to_ptr>] ary
1069
1069
  * @return [self]
1070
1070
  * Put an array of {Pointer} into memory from +offset+.
@@ -1073,8 +1073,8 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
1073
1073
  /*
1074
1074
  * Document-method: get_array_of_pointer
1075
1075
  * call-seq: memory.get_array_of_pointer(offset, length)
1076
- * @param [Numeric] offset
1077
- * @param [Numeric] length
1076
+ * @param [Integer] offset
1077
+ * @param [Integer] length
1078
1078
  * @return [Array<Pointer>]
1079
1079
  * Get an array of {Pointer} of length +length+ from +offset+.
1080
1080
  */
@@ -1093,7 +1093,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
1093
1093
  /*
1094
1094
  * Document-method: read_array_of_pointer
1095
1095
  * call-seq: memory.read_array_of_pointer(length)
1096
- * @param [Numeric] length
1096
+ * @param [Integer] length
1097
1097
  * @return [Array<Pointer>]
1098
1098
  * Read an array of {Pointer} of length +length+.
1099
1099
  *
@@ -1109,6 +1109,7 @@ rbffi_AbstractMemory_Init(VALUE moduleFFI)
1109
1109
  rb_define_method(classMemory, "read_bytes", memory_read_bytes, 1);
1110
1110
  rb_define_method(classMemory, "write_bytes", memory_write_bytes, -1);
1111
1111
  rb_define_method(classMemory, "get_array_of_string", memory_get_array_of_string, -1);
1112
+ rb_define_method(classMemory, "read_array_of_string", memory_read_array_of_string, -1);
1112
1113
 
1113
1114
  rb_define_method(classMemory, "get", memory_get, 2);
1114
1115
  rb_define_method(classMemory, "put", memory_put, 3);
@@ -110,7 +110,7 @@ array_type_memsize(const void *data)
110
110
  /*
111
111
  * call-seq: initialize(component_type, length)
112
112
  * @param [Type] component_type
113
- * @param [Numeric] length
113
+ * @param [Integer] length
114
114
  * @return [self]
115
115
  * A new instance of ArrayType.
116
116
  */
@@ -140,7 +140,7 @@ array_type_initialize(VALUE self, VALUE rbComponentType, VALUE rbLength)
140
140
 
141
141
  /*
142
142
  * call-seq: length
143
- * @return [Numeric]
143
+ * @return [Integer]
144
144
  * Get array's length
145
145
  */
146
146
  static VALUE
data/ext/ffi_c/Buffer.c CHANGED
@@ -114,7 +114,7 @@ buffer_release(void *data)
114
114
  /*
115
115
  * call-seq: initialize(size, count=1, clear=false)
116
116
  * @param [Integer, Symbol, #size] Type or size in bytes of a buffer cell
117
- * @param [Fixnum] count number of cell in the Buffer
117
+ * @param [Integer] count number of cell in the Buffer
118
118
  * @param [Boolean] clear if true, set the buffer to all-zero
119
119
  * @return [self]
120
120
  * @raise {NoMemoryError} if failed to allocate memory for Buffer
@@ -219,7 +219,7 @@ slice(VALUE self, long offset, long len)
219
219
 
220
220
  /*
221
221
  * call-seq: + offset
222
- * @param [Numeric] offset
222
+ * @param [Integer] offset
223
223
  * @return [Buffer] a new instance of Buffer pointing from offset until end of previous buffer.
224
224
  * Add a Buffer with an offset
225
225
  */
@@ -236,8 +236,8 @@ buffer_plus(VALUE self, VALUE rbOffset)
236
236
 
237
237
  /*
238
238
  * call-seq: slice(offset, length)
239
- * @param [Numeric] offset
240
- * @param [Numeric] length
239
+ * @param [Integer] offset
240
+ * @param [Integer] length
241
241
  * @return [Buffer] a new instance of Buffer
242
242
  * Slice an existing Buffer.
243
243
  */
data/ext/ffi_c/Call.c CHANGED
@@ -86,10 +86,11 @@ static inline void* getPointer(VALUE value, int type);
86
86
 
87
87
  static ID id_to_ptr, id_map_symbol, id_to_native;
88
88
 
89
- void
89
+ VALUE
90
90
  rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
91
91
  FFIStorage* paramStorage, void** ffiValues,
92
- VALUE* callbackParameters, int callbackCount, VALUE enums)
92
+ VALUE* callbackParameters, int callbackCount,
93
+ VALUE enums)
93
94
  {
94
95
  VALUE callbackProc = Qnil;
95
96
  FFIStorage* param = &paramStorage[0];
@@ -327,6 +328,7 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
327
328
  rb_raise(rb_eArgError, "Invalid parameter type: %d", paramType->nativeType);
328
329
  }
329
330
  }
331
+ return callbackProc;
330
332
  }
331
333
 
332
334
  static void *
@@ -362,6 +364,7 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
362
364
  FFIStorage* params;
363
365
  VALUE rbReturnValue;
364
366
  rbffi_frame_t frame = { 0 };
367
+ VALUE callbackProc;
365
368
 
366
369
  retval = alloca(MAX(fnInfo->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
367
370
 
@@ -379,9 +382,10 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
379
382
  bc->params = params;
380
383
  bc->frame = &frame;
381
384
 
382
- rbffi_SetupCallParams(argc, argv,
385
+ callbackProc = rbffi_SetupCallParams(argc, argv,
383
386
  fnInfo->parameterCount, fnInfo->parameterTypes, params, ffiValues,
384
- fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
387
+ fnInfo->callbackParameters, fnInfo->callbackCount,
388
+ fnInfo->rbEnums);
385
389
 
386
390
  rbffi_frame_push(&frame);
387
391
  rb_rescue2(rbffi_do_blocking_call, (VALUE) bc, rbffi_save_frame_exception, (VALUE) &frame, rb_eException, (VALUE) 0);
@@ -392,14 +396,16 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
392
396
  ffiValues = ALLOCA_N(void *, fnInfo->parameterCount);
393
397
  params = ALLOCA_N(FFIStorage, fnInfo->parameterCount);
394
398
 
395
- rbffi_SetupCallParams(argc, argv,
399
+ callbackProc = rbffi_SetupCallParams(argc, argv,
396
400
  fnInfo->parameterCount, fnInfo->parameterTypes, params, ffiValues,
397
- fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
401
+ fnInfo->callbackParameters, fnInfo->callbackCount,
402
+ fnInfo->rbEnums);
398
403
 
399
404
  rbffi_frame_push(&frame);
400
405
  ffi_call(&fnInfo->ffi_cif, FFI_FN(function), retval, ffiValues);
401
406
  rbffi_frame_pop(&frame);
402
407
  }
408
+ RB_GC_GUARD(callbackProc);
403
409
 
404
410
  if (unlikely(!fnInfo->ignoreErrno)) {
405
411
  rbffi_save_errno();
data/ext/ffi_c/Call.h CHANGED
@@ -73,9 +73,10 @@ typedef union {
73
73
 
74
74
  extern void rbffi_Call_Init(VALUE moduleFFI);
75
75
 
76
- extern void rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
76
+ extern VALUE rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
77
77
  FFIStorage* paramStorage, void** ffiValues,
78
- VALUE* callbackParameters, int callbackCount, VALUE enums);
78
+ VALUE* callbackParameters, int callbackCount,
79
+ VALUE enums);
79
80
 
80
81
  struct FunctionType_;
81
82
  extern VALUE rbffi_CallFunction(int argc, VALUE* argv, void* function, struct FunctionType_* fnInfo);
@@ -128,7 +128,7 @@ library_open(VALUE klass, VALUE libname, VALUE libflags)
128
128
  /*
129
129
  * call-seq: initialize(libname, libflags)
130
130
  * @param [String] libname name of library to open
131
- * @param [Fixnum] libflags flags for library to open
131
+ * @param [Integer] libflags flags for library to open
132
132
  * @return [FFI::DynamicLibrary]
133
133
  * @raise {LoadError} if +libname+ cannot be opened
134
134
  * A new DynamicLibrary instance.
@@ -232,7 +232,7 @@ dl_error(char* buf, int size)
232
232
 
233
233
  // Get the associated message
234
234
  LPSTR message = NULL;
235
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
235
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
236
236
  NULL, error, 0, (LPSTR)&message, 0, NULL);
237
237
 
238
238
  // Update the passed in buffer
data/ext/ffi_c/Function.c CHANGED
@@ -215,6 +215,52 @@ async_cb_dispatcher_set(struct async_cb_dispatcher *ctx)
215
215
  async_cb_dispatcher = ctx;
216
216
  }
217
217
  #endif
218
+
219
+ static void
220
+ async_cb_dispatcher_initialize(struct async_cb_dispatcher *ctx)
221
+ {
222
+ ctx->async_cb_list = NULL;
223
+
224
+ #if !defined(_WIN32)
225
+ /* n.b. we _used_ to try and destroy the mutex/cond before initializing here,
226
+ * but it's undefined what happens if you try and destory an unitialized cond.
227
+ * glibc in particular seems to wait for any concurrent waiters to finish before
228
+ * destroying a condvar, trying to destroy a condvar after fork that someone was
229
+ * waiting on pre-fork won't work. Just re-init he memory directly. */
230
+ pthread_mutex_init(&ctx->async_cb_mutex, NULL);
231
+ pthread_cond_init(&ctx->async_cb_cond, NULL);
232
+ #else
233
+ InitializeCriticalSection(&ctx->async_cb_lock);
234
+ ctx->async_cb_cond = CreateEvent(NULL, FALSE, FALSE, NULL);
235
+ #endif
236
+ ctx->thread = rb_thread_create(async_cb_event, ctx);
237
+
238
+ /* Name thread, for better debugging */
239
+ rb_funcall(ctx->thread, rb_intern("name="), 1, rb_str_new2("FFI Callback Dispatcher"));
240
+ }
241
+
242
+ static struct async_cb_dispatcher *
243
+ async_cb_dispatcher_ensure_created(void)
244
+ {
245
+ struct async_cb_dispatcher *ctx = async_cb_dispatcher_get();
246
+ if (ctx == NULL) {
247
+ ctx = (struct async_cb_dispatcher*)ALLOC(struct async_cb_dispatcher);
248
+ async_cb_dispatcher_initialize(ctx);
249
+ async_cb_dispatcher_set(ctx);
250
+ }
251
+ return ctx;
252
+ }
253
+
254
+
255
+ static VALUE
256
+ async_cb_dispatcher_atfork_child(VALUE self)
257
+ {
258
+ struct async_cb_dispatcher *ctx = async_cb_dispatcher_get();
259
+ if (ctx) {
260
+ async_cb_dispatcher_initialize(ctx);
261
+ }
262
+ return Qnil;
263
+ }
218
264
  #endif
219
265
 
220
266
  static VALUE
@@ -391,15 +437,6 @@ rbffi_Function_ForProc(VALUE rbFunctionInfo, VALUE proc)
391
437
  return callback;
392
438
  }
393
439
 
394
- #if !defined(_WIN32) && defined(DEFER_ASYNC_CALLBACK)
395
- static void
396
- after_fork_callback(void)
397
- {
398
- /* Ensure that a new dispatcher thread is started in a forked process */
399
- async_cb_dispatcher_set(NULL);
400
- }
401
- #endif
402
-
403
440
  static VALUE
404
441
  function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)
405
442
  {
@@ -426,31 +463,7 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)
426
463
  }
427
464
 
428
465
  #if defined(DEFER_ASYNC_CALLBACK)
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;
434
-
435
- #if !defined(_WIN32)
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);
444
- #endif
445
- ctx->thread = rb_thread_create(async_cb_event, ctx);
446
-
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;
453
- }
466
+ fn->dispatcher = async_cb_dispatcher_ensure_created();
454
467
  #endif
455
468
 
456
469
  fn->closure = rbffi_Closure_Alloc(fn->info->closurePool);
@@ -1060,4 +1073,9 @@ rbffi_Function_Init(VALUE moduleFFI)
1060
1073
  #if defined(DEFER_ASYNC_CALLBACK) && defined(HAVE_RB_EXT_RACTOR_SAFE)
1061
1074
  async_cb_dispatcher_key = rb_ractor_local_storage_ptr_newkey(&async_cb_dispatcher_key_type);
1062
1075
  #endif
1076
+ #ifdef DEFER_ASYNC_CALLBACK
1077
+ /* Ruby code will call this method in a Process._fork patch */
1078
+ rb_define_singleton_method(moduleFFI, "_async_cb_dispatcher_atfork_child",
1079
+ async_cb_dispatcher_atfork_child, 0);
1080
+ #endif
1063
1081
  }