From 099224a8c67f308e66d64c48568bc50a8951393b Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 16 Oct 2024 16:10:14 -0500 Subject: [PATCH] Update gems to latest releases in MRI 3.4 master --- lib/pom.rb | 44 +- lib/pom.xml | 182 ++++---- lib/ruby/stdlib/fiddle.rb | 15 +- lib/ruby/stdlib/fiddle/ffi_backend.rb | 613 ++++++++++++++++++++++++++ lib/ruby/stdlib/fiddle/jruby.rb | 462 ------------------- lib/ruby/stdlib/fiddle/pack.rb | 6 + lib/ruby/stdlib/fiddle/struct.rb | 33 +- lib/ruby/stdlib/fiddle/version.rb | 2 +- pom.rb | 2 +- pom.xml | 2 +- 10 files changed, 779 insertions(+), 582 deletions(-) create mode 100644 lib/ruby/stdlib/fiddle/ffi_backend.rb delete mode 100644 lib/ruby/stdlib/fiddle/jruby.rb diff --git a/lib/pom.rb b/lib/pom.rb index f1767e7c3a8..07e164e4239 100644 --- a/lib/pom.rb +++ b/lib/pom.rb @@ -17,9 +17,9 @@ def log(message=nil) default_gems = [ # treat RGs update special: # - we do not want bin/update_rubygems or bin/gem overrides - ['rubygems-update', '3.5.6', { bin: false, require_paths: ['lib'] }], + ['rubygems-update', '3.5.21', { bin: false, require_paths: ['lib'] }], ['benchmark', '0.3.0'], - ['bundler', '2.5.6'], + ['bundler', '2.5.21'], ['cgi', '0.4.1'], # Currently using a stub gem for JRuby until we can incorporate our code. # https://github.com/ruby/date/issues/48 @@ -36,8 +36,10 @@ def log(message=nil) # https://github.com/ruby/fcntl/issues/9 # ['fcntl', '1.0.1'], ['ffi', '1.16.3'], - # ['fiddle', '1.1.0'], ['fileutils', '1.7.2'], + # This version is accurate, but fiddle install needs mkmf which needs fileutils. We can't install it independently + # at build time, so instead we continue to version the files and will work out the build sequence separately. + #['fiddle', '1.1.3'], ['find', '0.2.0'], ['forwardable', '1.3.3'], ['io-console', '0.7.2'], @@ -45,28 +47,28 @@ def log(message=nil) # ['io-nonblock', '0.1.0'], ['io-wait', '0.3.1'], ['ipaddr', '1.2.6'], - ['irb', '1.13.0'], + ['irb', '1.14.1'], ['jar-dependencies', '0.4.1'], ['jruby-readline', '1.3.7'], ['jruby-openssl', '0.15.0'], ['json', '2.7.2'], - ['logger', '1.6.0'], + ['logger', '1.6.1'], ['net-http', '0.4.1'], ['net-protocol', '0.2.2'], ['open3', '0.2.1'], # https://github.com/ruby/openssl/issues/20#issuecomment-1022872855 # ['openssl', '3.0.0'], ['open-uri', '0.4.1'], - ['optparse', '0.4.0'], + ['optparse', '0.5.0'], ['ostruct', '0.6.0'], # https://github.com/ruby/pathname/issues/17 # ['pathname', '0.2.0'], ['pp', '0.5.0'], ['prettyprint', '0.2.0'], ['pstore', '0.1.3'], - ['psych', '5.1.2'], + ['psych', '5.2.0.beta1'], ['rake-ant', '1.0.6'], - ['rdoc', '6.6.2'], + ['rdoc', '6.7.0'], # Ext removed from CRuby in 3.3, equivalent for us would be to remove jruby-readline but unknown implications. # The gem below just attempts to load the extension, and failing that loads reline. Our current readline.rb in # jruby-readline does largely the same, but it finds the extension and does not load reline. @@ -74,7 +76,7 @@ def log(message=nil) # ['readline', '0.0.4'], # Will be solved with readline # ['readline-ext', '0.1.4'], - ['reline', '0.4.3'], + ['reline', '0.5.10'], # https://github.com/ruby/resolv/issues/19 # ['resolv', '0.2.1'], ['ruby2_keywords', '0.0.5'], @@ -91,13 +93,13 @@ def log(message=nil) ['ffi-bindings-libfixposix', '0.5.1.0'], ['syntax_suggest', '2.0.0'], ['tempfile', '0.2.1'], - ['time', '0.3.0'], + ['time', '0.4.0'], ['timeout', '0.4.1'], # https://github.com/ruby/tmpdir/issues/13 # ['tmpdir', '0.1.2'], ['tsort', '0.2.0'], ['un', '0.3.0'], - ['uri', '0.13.0'], + ['uri', '0.13.1'], ['weakref', '0.1.3'], # https://github.com/ruby/win32ole/issues/12 # ['win32ole', '1.8.8'], @@ -110,32 +112,32 @@ def log(message=nil) ['abbrev', '0.1.2'], ['base64', '0.2.0'], # Extension still lives in JRuby. See https://github.com/ruby/bigdecimal/issues/268 - ['bigdecimal', '3.1.6'], - ['csv', '3.2.8'], + ['bigdecimal', '3.1.8'], + ['csv', '3.3.0'], # Newer versions require deep control over CRuby internals, needs work to support JRuby. # ['debug', '1.9.1'], ['debug', '0.2.1'], ['drb', '2.2.1'], ['getoptlong', '0.2.1'], ['matrix', '0.4.2'], - ['minitest', '5.22.2'], + ['minitest', '5.25.1'], ['mutex_m', '0.2.0'], - ['net-ftp', '0.3.7'], - ['net-imap', '0.4.10'], + ['net-ftp', '0.3.8'], + ['net-imap', '0.4.17'], ['net-pop', '0.1.2'], - ['net-smtp', '0.4.0.1'], + ['net-smtp', '0.5.0'], ['nkf', '0.2.0'], ['observer', '0.1.2'], + ['power_assert', '2.0.4'], ['prime', '0.1.2'], - ['power_assert', '2.0.3'], - ['racc', '1.7.3'], + ['racc', '1.8.1'], ['rake', '${rake.version}'], # Depends on many CRuby internals # ['rbs', '2.0.0'], ['resolv-replace', '0.1.1'], - ['rexml', '3.3.4'], + ['rexml', '3.3.8'], ['rinda', '0.2.0'], - ['rss', '0.3.0'], + ['rss', '0.3.1'], # https://github.com/ruby/syslog/issues/1 # ['syslog', '0.1.0'], ['test-unit', '3.6.2'], diff --git a/lib/pom.xml b/lib/pom.xml index 4e6209e9875..dd9da96420e 100644 --- a/lib/pom.xml +++ b/lib/pom.xml @@ -34,7 +34,7 @@ DO NOT MODIFY - GENERATED CODE rubygems rubygems-update - 3.5.6 + 3.5.21 gem provided @@ -60,7 +60,7 @@ DO NOT MODIFY - GENERATED CODE rubygems bundler - 2.5.6 + 2.5.21 gem provided @@ -200,6 +200,19 @@ DO NOT MODIFY - GENERATED CODE + + rubygems + fiddle + 1.1.3 + gem + provided + + + rubygems + jar-dependencies + + + rubygems find @@ -268,7 +281,7 @@ DO NOT MODIFY - GENERATED CODE rubygems irb - 1.13.0 + 1.14.1 gem provided @@ -333,7 +346,7 @@ DO NOT MODIFY - GENERATED CODE rubygems logger - 1.6.0 + 1.6.1 gem provided @@ -398,7 +411,7 @@ DO NOT MODIFY - GENERATED CODE rubygems optparse - 0.4.0 + 0.5.0 gem provided @@ -463,7 +476,7 @@ DO NOT MODIFY - GENERATED CODE rubygems psych - 5.1.2 + 5.2.0.beta1 gem provided @@ -489,7 +502,7 @@ DO NOT MODIFY - GENERATED CODE rubygems rdoc - 6.6.2 + 6.7.0 gem provided @@ -502,7 +515,7 @@ DO NOT MODIFY - GENERATED CODE rubygems reline - 0.4.3 + 0.5.10 gem provided @@ -671,7 +684,7 @@ DO NOT MODIFY - GENERATED CODE rubygems time - 0.3.0 + 0.4.0 gem provided @@ -723,7 +736,7 @@ DO NOT MODIFY - GENERATED CODE rubygems uri - 0.13.0 + 0.13.1 gem provided @@ -788,7 +801,7 @@ DO NOT MODIFY - GENERATED CODE rubygems bigdecimal - 3.1.6 + 3.1.8 gem provided @@ -801,7 +814,7 @@ DO NOT MODIFY - GENERATED CODE rubygems csv - 3.2.8 + 3.3.0 gem provided @@ -866,7 +879,7 @@ DO NOT MODIFY - GENERATED CODE rubygems minitest - 5.22.2 + 5.25.1 gem provided @@ -892,7 +905,7 @@ DO NOT MODIFY - GENERATED CODE rubygems net-ftp - 0.3.7 + 0.3.8 gem provided @@ -905,7 +918,7 @@ DO NOT MODIFY - GENERATED CODE rubygems net-imap - 0.4.10 + 0.4.17 gem provided @@ -931,7 +944,7 @@ DO NOT MODIFY - GENERATED CODE rubygems net-smtp - 0.4.0.1 + 0.5.0 gem provided @@ -969,8 +982,8 @@ DO NOT MODIFY - GENERATED CODE rubygems - prime - 0.1.2 + power_assert + 2.0.4 gem provided @@ -982,8 +995,8 @@ DO NOT MODIFY - GENERATED CODE rubygems - power_assert - 2.0.3 + prime + 0.1.2 gem provided @@ -996,7 +1009,7 @@ DO NOT MODIFY - GENERATED CODE rubygems racc - 1.7.3 + 1.8.1 gem provided @@ -1035,7 +1048,7 @@ DO NOT MODIFY - GENERATED CODE rubygems rexml - 3.3.4 + 3.3.8 gem provided @@ -1061,7 +1074,7 @@ DO NOT MODIFY - GENERATED CODE rubygems rss - 0.3.0 + 0.3.1 gem provided @@ -1105,9 +1118,9 @@ DO NOT MODIFY - GENERATED CODE ${gem.home} specifications/default/* - specifications/rubygems-update-3.5.6* + specifications/rubygems-update-3.5.21* specifications/benchmark-0.3.0* - specifications/bundler-2.5.6* + specifications/bundler-2.5.21* specifications/cgi-0.4.1* specifications/date-3.3.4* specifications/delegate-0.3.1* @@ -1118,30 +1131,31 @@ DO NOT MODIFY - GENERATED CODE specifications/error_highlight-0.6.0* specifications/ffi-1.16.3* specifications/fileutils-1.7.2* + specifications/fiddle-1.1.3* specifications/find-0.2.0* specifications/forwardable-1.3.3* specifications/io-console-0.7.2* specifications/io-wait-0.3.1* specifications/ipaddr-1.2.6* - specifications/irb-1.13.0* + specifications/irb-1.14.1* specifications/jar-dependencies-0.4.1* specifications/jruby-readline-1.3.7* specifications/jruby-openssl-0.15.0* specifications/json-2.7.2* - specifications/logger-1.6.0* + specifications/logger-1.6.1* specifications/net-http-0.4.1* specifications/net-protocol-0.2.2* specifications/open3-0.2.1* specifications/open-uri-0.4.1* - specifications/optparse-0.4.0* + specifications/optparse-0.5.0* specifications/ostruct-0.6.0* specifications/pp-0.5.0* specifications/prettyprint-0.2.0* specifications/pstore-0.1.3* - specifications/psych-5.1.2* + specifications/psych-5.2.0.beta1* specifications/rake-ant-1.0.6* - specifications/rdoc-6.6.2* - specifications/reline-0.4.3* + specifications/rdoc-6.7.0* + specifications/reline-0.5.10* specifications/ruby2_keywords-0.0.5* specifications/securerandom-0.3.1* specifications/shellwords-0.2.0* @@ -1154,41 +1168,41 @@ DO NOT MODIFY - GENERATED CODE specifications/ffi-bindings-libfixposix-0.5.1.0* specifications/syntax_suggest-2.0.0* specifications/tempfile-0.2.1* - specifications/time-0.3.0* + specifications/time-0.4.0* specifications/timeout-0.4.1* specifications/tsort-0.2.0* specifications/un-0.3.0* - specifications/uri-0.13.0* + specifications/uri-0.13.1* specifications/weakref-0.1.3* specifications/yaml-0.3.0* specifications/abbrev-0.1.2* specifications/base64-0.2.0* - specifications/bigdecimal-3.1.6* - specifications/csv-3.2.8* + specifications/bigdecimal-3.1.8* + specifications/csv-3.3.0* specifications/debug-0.2.1* specifications/drb-2.2.1* specifications/getoptlong-0.2.1* specifications/matrix-0.4.2* - specifications/minitest-5.22.2* + specifications/minitest-5.25.1* specifications/mutex_m-0.2.0* - specifications/net-ftp-0.3.7* - specifications/net-imap-0.4.10* + specifications/net-ftp-0.3.8* + specifications/net-imap-0.4.17* specifications/net-pop-0.1.2* - specifications/net-smtp-0.4.0.1* + specifications/net-smtp-0.5.0* specifications/nkf-0.2.0* specifications/observer-0.1.2* + specifications/power_assert-2.0.4* specifications/prime-0.1.2* - specifications/power_assert-2.0.3* - specifications/racc-1.7.3* + specifications/racc-1.8.1* specifications/rake-${rake.version}* specifications/resolv-replace-0.1.1* - specifications/rexml-3.3.4* + specifications/rexml-3.3.8* specifications/rinda-0.2.0* - specifications/rss-0.3.0* + specifications/rss-0.3.1* specifications/test-unit-3.6.2* - gems/rubygems-update-3.5.6*/**/* + gems/rubygems-update-3.5.21*/**/* gems/benchmark-0.3.0*/**/* - gems/bundler-2.5.6*/**/* + gems/bundler-2.5.21*/**/* gems/cgi-0.4.1*/**/* gems/date-3.3.4*/**/* gems/delegate-0.3.1*/**/* @@ -1199,30 +1213,31 @@ DO NOT MODIFY - GENERATED CODE gems/error_highlight-0.6.0*/**/* gems/ffi-1.16.3*/**/* gems/fileutils-1.7.2*/**/* + gems/fiddle-1.1.3*/**/* gems/find-0.2.0*/**/* gems/forwardable-1.3.3*/**/* gems/io-console-0.7.2*/**/* gems/io-wait-0.3.1*/**/* gems/ipaddr-1.2.6*/**/* - gems/irb-1.13.0*/**/* + gems/irb-1.14.1*/**/* gems/jar-dependencies-0.4.1*/**/* gems/jruby-readline-1.3.7*/**/* gems/jruby-openssl-0.15.0*/**/* gems/json-2.7.2*/**/* - gems/logger-1.6.0*/**/* + gems/logger-1.6.1*/**/* gems/net-http-0.4.1*/**/* gems/net-protocol-0.2.2*/**/* gems/open3-0.2.1*/**/* gems/open-uri-0.4.1*/**/* - gems/optparse-0.4.0*/**/* + gems/optparse-0.5.0*/**/* gems/ostruct-0.6.0*/**/* gems/pp-0.5.0*/**/* gems/prettyprint-0.2.0*/**/* gems/pstore-0.1.3*/**/* - gems/psych-5.1.2*/**/* + gems/psych-5.2.0.beta1*/**/* gems/rake-ant-1.0.6*/**/* - gems/rdoc-6.6.2*/**/* - gems/reline-0.4.3*/**/* + gems/rdoc-6.7.0*/**/* + gems/reline-0.5.10*/**/* gems/ruby2_keywords-0.0.5*/**/* gems/securerandom-0.3.1*/**/* gems/shellwords-0.2.0*/**/* @@ -1235,41 +1250,41 @@ DO NOT MODIFY - GENERATED CODE gems/ffi-bindings-libfixposix-0.5.1.0*/**/* gems/syntax_suggest-2.0.0*/**/* gems/tempfile-0.2.1*/**/* - gems/time-0.3.0*/**/* + gems/time-0.4.0*/**/* gems/timeout-0.4.1*/**/* gems/tsort-0.2.0*/**/* gems/un-0.3.0*/**/* - gems/uri-0.13.0*/**/* + gems/uri-0.13.1*/**/* gems/weakref-0.1.3*/**/* gems/yaml-0.3.0*/**/* gems/abbrev-0.1.2*/**/* gems/base64-0.2.0*/**/* - gems/bigdecimal-3.1.6*/**/* - gems/csv-3.2.8*/**/* + gems/bigdecimal-3.1.8*/**/* + gems/csv-3.3.0*/**/* gems/debug-0.2.1*/**/* gems/drb-2.2.1*/**/* gems/getoptlong-0.2.1*/**/* gems/matrix-0.4.2*/**/* - gems/minitest-5.22.2*/**/* + gems/minitest-5.25.1*/**/* gems/mutex_m-0.2.0*/**/* - gems/net-ftp-0.3.7*/**/* - gems/net-imap-0.4.10*/**/* + gems/net-ftp-0.3.8*/**/* + gems/net-imap-0.4.17*/**/* gems/net-pop-0.1.2*/**/* - gems/net-smtp-0.4.0.1*/**/* + gems/net-smtp-0.5.0*/**/* gems/nkf-0.2.0*/**/* gems/observer-0.1.2*/**/* + gems/power_assert-2.0.4*/**/* gems/prime-0.1.2*/**/* - gems/power_assert-2.0.3*/**/* - gems/racc-1.7.3*/**/* + gems/racc-1.8.1*/**/* gems/rake-${rake.version}*/**/* gems/resolv-replace-0.1.1*/**/* - gems/rexml-3.3.4*/**/* + gems/rexml-3.3.8*/**/* gems/rinda-0.2.0*/**/* - gems/rss-0.3.0*/**/* + gems/rss-0.3.1*/**/* gems/test-unit-3.6.2*/**/* - cache/rubygems-update-3.5.6* + cache/rubygems-update-3.5.21* cache/benchmark-0.3.0* - cache/bundler-2.5.6* + cache/bundler-2.5.21* cache/cgi-0.4.1* cache/date-3.3.4* cache/delegate-0.3.1* @@ -1280,30 +1295,31 @@ DO NOT MODIFY - GENERATED CODE cache/error_highlight-0.6.0* cache/ffi-1.16.3* cache/fileutils-1.7.2* + cache/fiddle-1.1.3* cache/find-0.2.0* cache/forwardable-1.3.3* cache/io-console-0.7.2* cache/io-wait-0.3.1* cache/ipaddr-1.2.6* - cache/irb-1.13.0* + cache/irb-1.14.1* cache/jar-dependencies-0.4.1* cache/jruby-readline-1.3.7* cache/jruby-openssl-0.15.0* cache/json-2.7.2* - cache/logger-1.6.0* + cache/logger-1.6.1* cache/net-http-0.4.1* cache/net-protocol-0.2.2* cache/open3-0.2.1* cache/open-uri-0.4.1* - cache/optparse-0.4.0* + cache/optparse-0.5.0* cache/ostruct-0.6.0* cache/pp-0.5.0* cache/prettyprint-0.2.0* cache/pstore-0.1.3* - cache/psych-5.1.2* + cache/psych-5.2.0.beta1* cache/rake-ant-1.0.6* - cache/rdoc-6.6.2* - cache/reline-0.4.3* + cache/rdoc-6.7.0* + cache/reline-0.5.10* cache/ruby2_keywords-0.0.5* cache/securerandom-0.3.1* cache/shellwords-0.2.0* @@ -1316,37 +1332,37 @@ DO NOT MODIFY - GENERATED CODE cache/ffi-bindings-libfixposix-0.5.1.0* cache/syntax_suggest-2.0.0* cache/tempfile-0.2.1* - cache/time-0.3.0* + cache/time-0.4.0* cache/timeout-0.4.1* cache/tsort-0.2.0* cache/un-0.3.0* - cache/uri-0.13.0* + cache/uri-0.13.1* cache/weakref-0.1.3* cache/yaml-0.3.0* cache/abbrev-0.1.2* cache/base64-0.2.0* - cache/bigdecimal-3.1.6* - cache/csv-3.2.8* + cache/bigdecimal-3.1.8* + cache/csv-3.3.0* cache/debug-0.2.1* cache/drb-2.2.1* cache/getoptlong-0.2.1* cache/matrix-0.4.2* - cache/minitest-5.22.2* + cache/minitest-5.25.1* cache/mutex_m-0.2.0* - cache/net-ftp-0.3.7* - cache/net-imap-0.4.10* + cache/net-ftp-0.3.8* + cache/net-imap-0.4.17* cache/net-pop-0.1.2* - cache/net-smtp-0.4.0.1* + cache/net-smtp-0.5.0* cache/nkf-0.2.0* cache/observer-0.1.2* + cache/power_assert-2.0.4* cache/prime-0.1.2* - cache/power_assert-2.0.3* - cache/racc-1.7.3* + cache/racc-1.8.1* cache/rake-${rake.version}* cache/resolv-replace-0.1.1* - cache/rexml-3.3.4* + cache/rexml-3.3.8* cache/rinda-0.2.0* - cache/rss-0.3.0* + cache/rss-0.3.1* cache/test-unit-3.6.2* diff --git a/lib/ruby/stdlib/fiddle.rb b/lib/ruby/stdlib/fiddle.rb index 28c2a38d8aa..6718b012efe 100644 --- a/lib/ruby/stdlib/fiddle.rb +++ b/lib/ruby/stdlib/fiddle.rb @@ -1,6 +1,10 @@ # frozen_string_literal: true -require 'fiddle.so' unless RUBY_ENGINE == 'jruby' -require 'fiddle/jruby' if RUBY_ENGINE == 'jruby' + +if RUBY_ENGINE == 'ruby' + require 'fiddle.so' +else + require 'fiddle/ffi_backend' +end require 'fiddle/closure' require 'fiddle/function' require 'fiddle/version' @@ -21,8 +25,7 @@ def self.win32_last_error # Sets the last win32 +Error+ of the current executing +Thread+ to +error+ def self.win32_last_error= error if RUBY_ENGINE == 'jruby' - errno = FFI.errno - errno == 0 ? nil : errno + FFI.errno = error || 0 else Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error end @@ -43,8 +46,7 @@ def self.win32_last_socket_error # +Thread+ to +error+ def self.win32_last_socket_error= error if RUBY_ENGINE == 'jruby' - errno = FFI.errno - errno == 0 ? nil : errno + FFI.errno = error || 0 else Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error end @@ -56,7 +58,6 @@ def self.last_error if RUBY_ENGINE == 'jruby' errno = FFI.errno errno == 0 ? nil : errno - errno else Thread.current[:__FIDDLE_LAST_ERROR__] end diff --git a/lib/ruby/stdlib/fiddle/ffi_backend.rb b/lib/ruby/stdlib/fiddle/ffi_backend.rb new file mode 100644 index 00000000000..0c7c379777f --- /dev/null +++ b/lib/ruby/stdlib/fiddle/ffi_backend.rb @@ -0,0 +1,613 @@ +# This is based on JRuby's FFI-based fiddle implementation. + +require 'ffi' + +module Fiddle + def self.malloc(size) + Fiddle::Pointer.malloc(size) + end + + def self.free(ptr) + Fiddle::Pointer::LibC::FREE.call(ptr) + nil + end + + def self.dlwrap(val) + Pointer.to_ptr(val) + end + + module Types + VOID = 0 + VOIDP = 1 + CHAR = 2 + UCHAR = -CHAR + SHORT = 3 + USHORT = -SHORT + INT = 4 + UINT = -INT + LONG = 5 + ULONG = -LONG + LONG_LONG = 6 + ULONG_LONG = -LONG_LONG + FLOAT = 7 + DOUBLE = 8 + VARIADIC = 9 + CONST_STRING = 10 + BOOL = 11 + INT8_T = CHAR + UINT8_T = UCHAR + if FFI::Type::Builtin::SHORT.size == 2 + INT16_T = SHORT + UINT16_T = USHORT + elsif FFI::Type::Builtin::INT.size == 2 + INT16_T = INT + UINT16_T = UINT + end + if FFI::Type::Builtin::SHORT.size == 4 + INT32_T = SHORT + UINT32_T = USHORT + elsif FFI::Type::Builtin::INT.size == 4 + INT32_T = INT + UINT32_T = UINT + elsif FFI::Type::Builtin::LONG.size == 4 + INT32_T = LONG + UINT32_T = ULONG + end + if FFI::Type::Builtin::INT.size == 8 + INT64_T = INT + UINT64_T = UINT + elsif FFI::Type::Builtin::LONG.size == 8 + INT64_T = LONG + UINT64_T = ULONG + else + INT64_T = LONG_LONG + UINT64_T = ULONG_LONG + end + + # FIXME: platform specific values + SSIZE_T = INT64_T + SIZE_T = -SSIZE_T + PTRDIFF_T = SSIZE_T + INTPTR_T = INT64_T + UINTPTR_T = -INTPTR_T + end + + WINDOWS = FFI::Platform.windows? + + module FFIBackend + FFITypes = { + 'c' => FFI::Type::INT8, + 'h' => FFI::Type::INT16, + 'i' => FFI::Type::INT32, + 'l' => FFI::Type::LONG, + 'f' => FFI::Type::FLOAT32, + 'd' => FFI::Type::FLOAT64, + 'p' => FFI::Type::POINTER, + 's' => FFI::Type::STRING, + + Types::VOID => FFI::Type::Builtin::VOID, + Types::VOIDP => FFI::Type::Builtin::POINTER, + Types::CHAR => FFI::Type::Builtin::CHAR, + Types::UCHAR => FFI::Type::Builtin::UCHAR, + Types::SHORT => FFI::Type::Builtin::SHORT, + Types::USHORT => FFI::Type::Builtin::USHORT, + Types::INT => FFI::Type::Builtin::INT, + Types::UINT => FFI::Type::Builtin::UINT, + Types::LONG => FFI::Type::Builtin::LONG, + Types::ULONG => FFI::Type::Builtin::ULONG, + Types::LONG_LONG => FFI::Type::Builtin::LONG_LONG, + Types::ULONG_LONG => FFI::Type::Builtin::ULONG_LONG, + Types::FLOAT => FFI::Type::Builtin::FLOAT, + Types::DOUBLE => FFI::Type::Builtin::DOUBLE, + Types::BOOL => FFI::Type::Builtin::BOOL, + Types::CONST_STRING => FFI::Type::Builtin::POINTER, + Types::VARIADIC => FFI::Type::Builtin::VARARGS, + } + + def self.to_ffi_type(fiddle_type) + if fiddle_type.is_a?(Symbol) + fiddle_type = Types.const_get(fiddle_type.to_s.upcase) + end + if !fiddle_type.is_a?(Integer) && fiddle_type.respond_to?(:to_int) + fiddle_type = fiddle_type.to_int + end + ffi_type = FFITypes[fiddle_type] + ffi_type = FFITypes[-fiddle_type] if ffi_type.nil? && fiddle_type.is_a?(Integer) && fiddle_type < 0 + raise TypeError.new("cannot convert #{fiddle_type} to ffi") unless ffi_type + ffi_type + end + end + + class Function + DEFAULT = "default" + STDCALL = "stdcall" + + def initialize(ptr, args, return_type, abi = DEFAULT, kwargs = nil) + if kwargs.nil? + if abi.kind_of? Hash + kwargs = abi + abi = DEFAULT + end + end + @name = kwargs[:name] if kwargs.kind_of? Hash + @ptr, @args, @return_type, @abi = ptr, args, return_type, abi + raise TypeError.new "invalid argument types" unless args.is_a?(Array) + + ffi_return_type = Fiddle::FFIBackend.to_ffi_type(@return_type) + ffi_args = @args.map { |t| Fiddle::FFIBackend.to_ffi_type(t) } + pointer = FFI::Pointer.new(ptr.to_i) + options = {convention: @abi} + if ffi_args.last == FFI::Type::Builtin::VARARGS + @function = FFI::VariadicInvoker.new( + pointer, + ffi_args, + ffi_return_type, + options + ) + else + @function = FFI::Function.new(ffi_return_type, ffi_args, pointer, options) + end + end + + def call(*args, &block) + if @function.is_a?(FFI::VariadicInvoker) + n_fixed_args = @args.size - 1 + n_fixed_args.step(args.size - 1, 2) do |i| + if args[i] == :const_string || args[i] == Types::CONST_STRING + args[i + 1] = String.try_convert(args[i + 1]) || args[i + 1] + end + args[i] = Fiddle::FFIBackend.to_ffi_type(args[i]) + end + else + args.map! do |arg| + if arg.respond_to?(:to_ptr) + begin + arg = arg.to_ptr + end until arg.is_a?(FFI::Pointer) || !arg.respond_to?(:to_ptr) + arg + else + arg + end + end + end + result = @function.call(*args, &block) + result = Pointer.new(result) if result.is_a?(FFI::Pointer) + result + end + end + + class Closure + def initialize(ret, args, abi = Function::DEFAULT) + raise TypeError.new "invalid argument types" unless args.is_a?(Array) + + @ctype, @args = ret, args + ffi_args = @args.map { |t| Fiddle::FFIBackend.to_ffi_type(t) } + if ffi_args.size == 1 && ffi_args[0] == FFI::Type::Builtin::VOID + ffi_args = [] + end + return_type = Fiddle::FFIBackend.to_ffi_type(@ctype) + raise "#{self.class} must implement #call" unless respond_to?(:call) + callable = method(:call) + @function = FFI::Function.new(return_type, ffi_args, callable, convention: abi) + @freed = false + end + + def to_ptr + @function + end + + def to_i + @function.to_i + end + + def free + return if @freed + @function.free + @freed = true + end + + def freed? + @freed + end + end + + class Error < StandardError; end + class DLError < Error; end + class ClearedReferenceError < Error; end + + class Pointer + attr_reader :ffi_ptr + extend FFI::DataConverter + native_type FFI::Type::Builtin::POINTER + + def self.to_native(value, ctx) + if value.is_a?(Pointer) + value.ffi_ptr + + elsif value.is_a?(Integer) + FFI::Pointer.new(value) + + elsif value.is_a?(String) + value + end + end + + def self.from_native(value, ctx) + self.new(value) + end + + def self.to_ptr(value) + if value.is_a?(String) + cptr = Pointer.malloc(value.bytesize) + cptr.ffi_ptr.put_string(0, value) + cptr + + elsif value.is_a?(Array) + raise NotImplementedError, "array ptr" + + elsif value.respond_to?(:to_ptr) + ptr = value.to_ptr + case ptr + when Pointer + ptr + when FFI::Pointer + Pointer.new(ptr) + else + raise DLError.new("to_ptr should return a Fiddle::Pointer object, was #{ptr.class}") + end + + else + Pointer.new(value) + end + end + + class << self + alias [] to_ptr + end + + def []=(*args, value) + if args.size == 2 + if value.is_a?(Integer) + value = self.class.new(value) + end + if value.is_a?(Fiddle::Pointer) + value = value.to_str(args[1]) + end + + @ffi_ptr.put_bytes(args[0], value, 0, args[1]) + elsif args.size == 1 + if value.is_a?(Fiddle::Pointer) + value = value.to_str(args[0] + 1) + else + value = value.chr + end + + @ffi_ptr.put_bytes(args[0], value, 0, 1) + end + rescue FFI::NullPointerError + raise DLError.new("NULL pointer access") + end + + def initialize(addr, size = nil, free = nil) + ptr = if addr.is_a?(FFI::Pointer) + addr + + elsif addr.is_a?(Integer) + FFI::Pointer.new(addr) + + elsif addr.respond_to?(:to_ptr) + fiddle_ptr = addr.to_ptr + if fiddle_ptr.is_a?(Pointer) + fiddle_ptr.ffi_ptr + elsif fiddle_ptr.is_a?(FFI::AutoPointer) + addr.ffi_ptr + elsif fiddle_ptr.is_a?(FFI::Pointer) + fiddle_ptr + else + raise DLError.new("to_ptr should return a Fiddle::Pointer object, was #{fiddle_ptr.class}") + end + elsif addr.is_a?(IO) + raise NotImplementedError, "IO ptr isn't supported" + end + + @size = size ? size : ptr.size + @free = free + @ffi_ptr = ptr + @freed = false + end + + module LibC + extend FFI::Library + ffi_lib FFI::Library::LIBC + MALLOC = attach_function :malloc, [ :size_t ], :pointer + REALLOC = attach_function :realloc, [ :pointer, :size_t ], :pointer + FREE = attach_function :free, [ :pointer ], :void + end + + def self.malloc(size, free = nil) + if block_given? and free.nil? + message = "a free function must be supplied to #{self}.malloc " + + "when it is called with a block" + raise ArgumentError, message + end + + pointer = new(LibC.malloc(size), size, free) + if block_given? + begin + yield(pointer) + ensure + pointer.call_free + end + else + pointer + end + end + + def null? + @ffi_ptr.null? + end + + def to_ptr + @ffi_ptr + end + + def size + defined?(@layout) ? @layout.size : @size + end + + def free + @free + end + + def free=(free) + @free = free + end + + def call_free + return if @free.nil? + return if @freed + if @free == RUBY_FREE + LibC::FREE.call(@ffi_ptr) + else + @free.call(@ffi_ptr) + end + @freed = true + end + + def freed? + @freed + end + + def size=(size) + @size = size + end + + def [](index, length = nil) + if length + ffi_ptr.get_bytes(index, length) + else + ffi_ptr.get_char(index) + end + rescue FFI::NullPointerError + raise DLError.new("NULL pointer dereference") + end + + def to_i + ffi_ptr.to_i + end + alias to_int to_i + + # without \0 + def to_s(len = nil) + if len + ffi_ptr.get_string(0, len) + else + ffi_ptr.get_string(0) + end + rescue FFI::NullPointerError + raise DLError.new("NULL pointer access") + end + + def to_str(len = nil) + if len + ffi_ptr.read_string(len) + else + ffi_ptr.read_string(@size) + end + rescue FFI::NullPointerError + raise DLError.new("NULL pointer access") + end + + def to_value + raise NotImplementedError, "to_value isn't supported" + end + + def inspect + "#<#{self.class.name} ptr=#{to_i.to_s(16)} size=#{@size} free=#{@free.inspect}>" + end + + def +(delta) + self.class.new(to_i + delta, @size - delta) + end + + def -(delta) + self.class.new(to_i - delta, @size + delta) + end + + def <=>(other) + return unless other.is_a?(Pointer) + diff = self.to_i - other.to_i + return 0 if diff == 0 + diff > 0 ? 1 : -1 + end + + def eql?(other) + return unless other.is_a?(Pointer) + self.to_i == other.to_i + end + + def ==(other) + eql?(other) + end + + def ptr + Pointer.new(ffi_ptr.get_pointer(0)) + end + + def +@ + ptr + end + + def -@ + ref + end + + def ref + cptr = Pointer.malloc(FFI::Type::POINTER.size, RUBY_FREE) + cptr.ffi_ptr.put_pointer(0, ffi_ptr) + cptr + end + end + + class Handle + RTLD_GLOBAL = FFI::DynamicLibrary::RTLD_GLOBAL + RTLD_LAZY = FFI::DynamicLibrary::RTLD_LAZY + RTLD_NOW = FFI::DynamicLibrary::RTLD_NOW + + def initialize(libname = nil, flags = RTLD_LAZY | RTLD_GLOBAL) + @lib = FFI::DynamicLibrary.open(libname, flags) rescue LoadError + raise DLError.new("Could not open #{libname}") unless @lib + + @open = true + + begin + yield(self) + ensure + self.close + end if block_given? + end + + def close + raise DLError.new("closed handle") unless @open + @open = false + 0 + end + + def self.sym(func) + DEFAULT.sym(func) + end + + def sym(func) + raise TypeError.new("invalid function name") unless func.is_a?(String) + raise DLError.new("closed handle") unless @open + address = @lib.find_function(func) + raise DLError.new("unknown symbol #{func}") if address.nil? || address.null? + address.to_i + end + + def self.sym_defined?(func) + DEFAULT.sym_defined?(func) + end + + def sym_defined?(func) + raise TypeError.new("invalid function name") unless func.is_a?(String) + raise DLError.new("closed handle") unless @open + address = @lib.find_function(func) + !address.nil? && !address.null? + end + + def self.[](func) + self.sym(func) + end + + def [](func) + sym(func) + end + + def enable_close + @enable_close = true + end + + def close_enabled? + @enable_close + end + + def disable_close + @enable_close = false + end + + DEFAULT = new + end + + class Pinned + def initialize(object) + @object = object + end + + def ref + if @object.nil? + raise ClearedReferenceError, "`ref` called on a cleared object" + end + @object + end + + def clear + @object = nil + end + + def cleared? + @object.nil? + end + end + + RUBY_FREE = Fiddle::Pointer::LibC::FREE.address + NULL = Fiddle::Pointer.new(0) + + ALIGN_VOIDP = Fiddle::FFIBackend::FFITypes[Types::VOIDP].alignment + ALIGN_CHAR = Fiddle::FFIBackend::FFITypes[Types::CHAR].alignment + ALIGN_SHORT = Fiddle::FFIBackend::FFITypes[Types::SHORT].alignment + ALIGN_INT = Fiddle::FFIBackend::FFITypes[Types::INT].alignment + ALIGN_LONG = Fiddle::FFIBackend::FFITypes[Types::LONG].alignment + ALIGN_LONG_LONG = Fiddle::FFIBackend::FFITypes[Types::LONG_LONG].alignment + ALIGN_INT8_T = Fiddle::FFIBackend::FFITypes[Types::INT8_T].alignment + ALIGN_INT16_T = Fiddle::FFIBackend::FFITypes[Types::INT16_T].alignment + ALIGN_INT32_T = Fiddle::FFIBackend::FFITypes[Types::INT32_T].alignment + ALIGN_INT64_T = Fiddle::FFIBackend::FFITypes[Types::INT64_T].alignment + ALIGN_FLOAT = Fiddle::FFIBackend::FFITypes[Types::FLOAT].alignment + ALIGN_DOUBLE = Fiddle::FFIBackend::FFITypes[Types::DOUBLE].alignment + ALIGN_BOOL = Fiddle::FFIBackend::FFITypes[Types::BOOL].alignment + ALIGN_SIZE_T = Fiddle::FFIBackend::FFITypes[Types::SIZE_T].alignment + ALIGN_SSIZE_T = ALIGN_SIZE_T + ALIGN_PTRDIFF_T = Fiddle::FFIBackend::FFITypes[Types::PTRDIFF_T].alignment + ALIGN_INTPTR_T = Fiddle::FFIBackend::FFITypes[Types::INTPTR_T].alignment + ALIGN_UINTPTR_T = Fiddle::FFIBackend::FFITypes[Types::UINTPTR_T].alignment + + SIZEOF_VOIDP = Fiddle::FFIBackend::FFITypes[Types::VOIDP].size + SIZEOF_CHAR = Fiddle::FFIBackend::FFITypes[Types::CHAR].size + SIZEOF_UCHAR = Fiddle::FFIBackend::FFITypes[Types::UCHAR].size + SIZEOF_SHORT = Fiddle::FFIBackend::FFITypes[Types::SHORT].size + SIZEOF_USHORT = Fiddle::FFIBackend::FFITypes[Types::USHORT].size + SIZEOF_INT = Fiddle::FFIBackend::FFITypes[Types::INT].size + SIZEOF_UINT = Fiddle::FFIBackend::FFITypes[Types::UINT].size + SIZEOF_LONG = Fiddle::FFIBackend::FFITypes[Types::LONG].size + SIZEOF_ULONG = Fiddle::FFIBackend::FFITypes[Types::ULONG].size + SIZEOF_LONG_LONG = Fiddle::FFIBackend::FFITypes[Types::LONG_LONG].size + SIZEOF_ULONG_LONG = Fiddle::FFIBackend::FFITypes[Types::ULONG_LONG].size + SIZEOF_INT8_T = Fiddle::FFIBackend::FFITypes[Types::INT8_T].size + SIZEOF_UINT8_T = Fiddle::FFIBackend::FFITypes[Types::UINT8_T].size + SIZEOF_INT16_T = Fiddle::FFIBackend::FFITypes[Types::INT16_T].size + SIZEOF_UINT16_T = Fiddle::FFIBackend::FFITypes[Types::UINT16_T].size + SIZEOF_INT32_T = Fiddle::FFIBackend::FFITypes[Types::INT32_T].size + SIZEOF_UINT32_T = Fiddle::FFIBackend::FFITypes[Types::UINT32_T].size + SIZEOF_INT64_T = Fiddle::FFIBackend::FFITypes[Types::INT64_T].size + SIZEOF_UINT64_T = Fiddle::FFIBackend::FFITypes[Types::UINT64_T].size + SIZEOF_FLOAT = Fiddle::FFIBackend::FFITypes[Types::FLOAT].size + SIZEOF_DOUBLE = Fiddle::FFIBackend::FFITypes[Types::DOUBLE].size + SIZEOF_BOOL = Fiddle::FFIBackend::FFITypes[Types::BOOL].size + SIZEOF_SIZE_T = Fiddle::FFIBackend::FFITypes[Types::SIZE_T].size + SIZEOF_SSIZE_T = SIZEOF_SIZE_T + SIZEOF_PTRDIFF_T = Fiddle::FFIBackend::FFITypes[Types::PTRDIFF_T].size + SIZEOF_INTPTR_T = Fiddle::FFIBackend::FFITypes[Types::INTPTR_T].size + SIZEOF_UINTPTR_T = Fiddle::FFIBackend::FFITypes[Types::UINTPTR_T].size + SIZEOF_CONST_STRING = Fiddle::FFIBackend::FFITypes[Types::VOIDP].size +end diff --git a/lib/ruby/stdlib/fiddle/jruby.rb b/lib/ruby/stdlib/fiddle/jruby.rb deleted file mode 100644 index d76f9094271..00000000000 --- a/lib/ruby/stdlib/fiddle/jruby.rb +++ /dev/null @@ -1,462 +0,0 @@ -# This is part of JRuby's FFI-based fiddle implementation. -# It should be maintained as part of the JRuby repository, as it has no -# equivalent file in CRuby. - -require 'ffi' - -module Fiddle - def self.malloc(size) - Fiddle::Pointer.malloc(size) - end - - def self.free(ptr) - Fiddle::Pointer.__freefunc__(ptr) - nil - end - - def self.dlwrap(val) - Pointer.to_ptr(val) - end - - module Types - VOID = 0 - VOIDP = 1 - CHAR = 2 - UCHAR = -2 - SHORT = 3 - USHORT = -3 - INT = 4 - UINT = -4 - LONG = 5 - ULONG = -5 - LONG_LONG = 6 - ULONG_LONG = -6 - FLOAT = 7 - DOUBLE = 8 - SSIZE_T = 9 - SIZE_T = 10 - PTRDIFF_T = 11 - INTPTR_T = 12 - UINTPTR_T = 13 - BOOL = 14 - end - - WINDOWS = FFI::Platform.windows? - - module JRuby - FFITypes = { - 'c' => FFI::Type::INT8, - 'h' => FFI::Type::INT16, - 'i' => FFI::Type::INT32, - 'l' => FFI::Type::LONG, - 'f' => FFI::Type::FLOAT32, - 'd' => FFI::Type::FLOAT64, - 'p' => FFI::Type::POINTER, - 's' => FFI::Type::STRING, - 'b' => FFI::Type::BOOL, - - Types::VOID => FFI::Type::Builtin::VOID, - Types::VOIDP => FFI::Type::Builtin::POINTER, - Types::CHAR => FFI::Type::Builtin::CHAR, - Types::UCHAR => FFI::Type::Builtin::UCHAR, - Types::SHORT => FFI::Type::Builtin::SHORT, - Types::USHORT => FFI::Type::Builtin::USHORT, - Types::INT => FFI::Type::Builtin::INT, - Types::UINT => FFI::Type::Builtin::UINT, - Types::LONG => FFI::Type::Builtin::LONG, - Types::ULONG => FFI::Type::Builtin::ULONG, - Types::LONG_LONG => FFI::Type::Builtin::LONG_LONG, - Types::ULONG_LONG => FFI::Type::Builtin::ULONG_LONG, - Types::FLOAT => FFI::Type::Builtin::FLOAT, - Types::DOUBLE => FFI::Type::Builtin::DOUBLE, - Types::BOOL => FFI::Type::Builtin::BOOL, - - # FIXME: platform specific values? - Types::SIZE_T => FFI::Type::Builtin::LONG_LONG, - Types::PTRDIFF_T => FFI::Type::Builtin::LONG_LONG, - Types::INTPTR_T => FFI::Type::Builtin::LONG_LONG, - Types::UINTPTR_T => FFI::Type::Builtin::LONG_LONG, - } - - def self.__ffi_type__(dl_type) - ffi_type = FFITypes[dl_type] - ffi_type = FFITypes[-dl_type] if ffi_type.nil? && dl_type.is_a?(Integer) && dl_type < 0 - raise TypeError.new("cannot convert #{dl_type} to ffi") unless ffi_type - ffi_type - end - end - - class Function - DEFAULT = "default" - STDCALL = "stdcall" - - def initialize(ptr, args, return_type, abi = DEFAULT, kwargs = nil) - if kwargs.nil? - if abi.kind_of? Hash - kwargs = abi - abi = DEFAULT - end - end - @name = kwargs[:name] if kwargs.kind_of? Hash - @ptr, @args, @return_type, @abi = ptr, args, return_type, abi - raise TypeError.new "invalid return type" unless return_type.is_a?(Integer) - raise TypeError.new "invalid return type" unless args.is_a?(Array) - - @function = FFI::Function.new( - Fiddle::JRuby::__ffi_type__(@return_type), - @args.map { |t| Fiddle::JRuby.__ffi_type__(t) }, - FFI::Pointer.new(ptr.to_i), - :convention => @abi - ) - @function.attach(self, "call") - end - - # stubbed; should be overwritten by initialize's #attach call above - def call(*args); end - end - - class Closure - def initialize(ret, args, abi = Function::DEFAULT) - @ctype, @args = ret, args - raise TypeError.new "invalid return type" unless ret.is_a?(Integer) - raise TypeError.new "invalid return type" unless args.is_a?(Array) - - @function = FFI::Function.new( - Fiddle::JRuby.__ffi_type__(@ctype), - @args.map { |t| Fiddle::JRuby.__ffi_type__(t) }, - self, - :convention => abi - ) - end - - def to_i - @function.to_i - end - end - - class DLError < StandardError; end - - class Pointer - attr_reader :ffi_ptr - extend FFI::DataConverter - native_type FFI::Type::Builtin::POINTER - - def self.to_native(value, ctx) - if value.is_a?(Pointer) - value.ffi_ptr - - elsif value.is_a?(Integer) - FFI::Pointer.new(value) - - elsif value.is_a?(String) - value - end - end - - def self.from_native(value, ctx) - self.new(value) - end - - def self.to_ptr(value) - if value.is_a?(String) - cptr = Pointer.malloc(value.bytesize) - cptr.ffi_ptr.put_string(0, value) - cptr - - elsif value.is_a?(Array) - raise NotImplementedError, "array ptr" - - elsif value.respond_to?(:to_ptr) - ptr = value.to_ptr - ptr.is_a?(Pointer) ? ptr : Pointer.new(ptr) - - else - Pointer.new(value) - end - end - - class << self - alias [] to_ptr - end - - def []=(*args, value) - if args.size == 2 - if value.is_a?(Integer) - value = self.class.new(value) - end - if value.is_a?(Fiddle::Pointer) - value = value.to_str(args[1]) - end - - @ffi_ptr.put_bytes(args[0], value, 0, args[1]) - elsif args.size == 1 - if value.is_a?(Fiddle::Pointer) - value = value.to_str(args[0] + 1) - else - value = value.chr - end - - @ffi_ptr.put_bytes(args[0], value, 0, 1) - end - rescue FFI::NullPointerError - raise DLError.new("NULL pointer access") - end - - def initialize(addr, size = nil, free = nil) - ptr = if addr.is_a?(FFI::Pointer) - addr - - elsif addr.is_a?(Integer) - FFI::Pointer.new(addr) - - elsif addr.respond_to?(:to_ptr) - fiddle_ptr = addr.to_ptr - if fiddle_ptr.is_a?(Pointer) - fiddle_ptr.ffi_ptr - elsif fiddle_ptr.is_a?(FFI::AutoPointer) - addr.ffi_ptr - elsif fiddle_ptr.is_a?(FFI::Pointer) - fiddle_ptr - else - raise DLError.new("to_ptr should return a Fiddle::Pointer object, was #{fiddle_ptr.class}") - end - elsif addr.is_a?(IO) - raise NotImplementedError, "IO ptr isn't supported" - end - - @size = size ? size : ptr.size - @free = free || 0 - @ffi_ptr = free.nil? ? ptr : FFI::AutoPointer.new(ptr, self.class.__freefunc__(free)) - end - - def self.__freefunc__(free) - if free.is_a?(FFI::Function) - free - - elsif free.is_a?(FFI::Pointer) - free.null? ? Proc.new { |ptr| } : FFI::Function.new(:void, [ :pointer ], free) - - elsif free.is_a?(Integer) - free == 0 ? Proc.new { |ptr| } : FFI::Function.new(:void, [ :pointer ], FFI::Pointer.new(free)) - - elsif free.respond_to?(:call) - free - - else - raise ArgumentError.new("invalid free func") - end - end - - module LibC - extend FFI::Library - ffi_lib FFI::Library::LIBC - MALLOC = attach_function :malloc, [ :size_t ], :pointer - REALLOC = attach_function :realloc, [ :pointer, :size_t ], :pointer - FREE = attach_function :free, [ :pointer ], :void - end - - def self.malloc(size, free = nil) - self.new(LibC.malloc(size), size, free ? free : LibC::FREE) - end - - def null? - @ffi_ptr.null? - end - - def to_ptr - @ffi_ptr - end - - def size - defined?(@layout) ? @layout.size : @size - end - - def free - @free == LibC::FREE ? nil : @free - end - - def free=(free) - raise NotImplementedError, "free= isn't supported" - end - - def size=(size) - @size = size - end - - def [](index, length = nil) - if length - ffi_ptr.get_string(index, length) - else - ffi_ptr.get_string(index, index + 1).ord - end - rescue FFI::NullPointerError - raise DLError.new("NULL pointer dereference") - end - - def to_i - ffi_ptr.to_i - end - alias to_int to_i - - # without \0 - def to_s(len = nil) - if len - ffi_ptr.get_string(0, len) - else - ffi_ptr.get_string(0) - end - rescue FFI::NullPointerError - raise DLError.new("NULL pointer access") - end - - def to_str(len = nil) - if len - ffi_ptr.read_string(len) - else - ffi_ptr.read_string(@size) - end - rescue FFI::NullPointerError - raise DLError.new("NULL pointer access") - end - - def to_value - raise NotImplementedError, "to_value isn't supported" - end - - def inspect - "#<#{self.class.name} ptr=#{to_i.to_s(16)} size=#{@size} free=#{@free.inspect}>" - end - - def +(delta) - self.class.new(to_i + delta, @size - delta) - end - - def -(delta) - self.class.new(to_i - delta, @size + delta) - end - - def <=>(other) - return unless other.is_a?(Pointer) - diff = self.to_i - other.to_i - return 0 if diff == 0 - diff > 0 ? 1 : -1 - end - - def eql?(other) - return unless other.is_a?(Pointer) - self.to_i == other.to_i - end - - def ==(other) - eql?(other) - end - - def ptr - Pointer.new(ffi_ptr.get_pointer(0)) - end - - def +@ - ptr - end - - def -@ - ref - end - - def ref - cptr = Pointer.malloc(FFI::Type::POINTER.size) - cptr.ffi_ptr.put_pointer(0, ffi_ptr) - cptr - end - end - - class Handle - RTLD_GLOBAL = FFI::DynamicLibrary::RTLD_GLOBAL - RTLD_LAZY = FFI::DynamicLibrary::RTLD_LAZY - RTLD_NOW = FFI::DynamicLibrary::RTLD_NOW - - def initialize(libname = nil, flags = RTLD_LAZY | RTLD_GLOBAL) - @lib = FFI::DynamicLibrary.open(libname, flags) rescue LoadError - raise DLError.new("Could not open #{libname}") unless @lib - - @open = true - - begin - yield(self) - ensure - self.close - end if block_given? - end - - def close - raise DLError.new("closed handle") unless @open - @open = false - 0 - end - - def self.sym(func) - DEFAULT.sym(func) - end - - def sym(func) - raise TypeError.new("invalid function name") unless func.is_a?(String) - raise DLError.new("closed handle") unless @open - address = @lib.find_function(func) - raise DLError.new("unknown symbol #{func}") if address.nil? || address.null? - address.to_i - end - - def self.[](func) - self.sym(func) - end - - def [](func) - sym(func) - end - - def enable_close - @enable_close = true - end - - def close_enabled? - @enable_close - end - - def disable_close - @enable_close = false - end - end - - RUBY_FREE = Fiddle::Pointer::LibC::FREE.address - NULL = Fiddle::Pointer.new(0) - - ALIGN_VOIDP = Fiddle::JRuby::FFITypes[Types::VOIDP].alignment - ALIGN_CHAR = Fiddle::JRuby::FFITypes[Types::CHAR].alignment - ALIGN_SHORT = Fiddle::JRuby::FFITypes[Types::SHORT].alignment - ALIGN_INT = Fiddle::JRuby::FFITypes[Types::INT].alignment - ALIGN_LONG = Fiddle::JRuby::FFITypes[Types::LONG].alignment - ALIGN_LONG_LONG = Fiddle::JRuby::FFITypes[Types::LONG_LONG].alignment - ALIGN_FLOAT = Fiddle::JRuby::FFITypes[Types::FLOAT].alignment - ALIGN_DOUBLE = Fiddle::JRuby::FFITypes[Types::DOUBLE].alignment - ALIGN_SIZE_T = Fiddle::JRuby::FFITypes[Types::SIZE_T].alignment - ALIGN_SSIZE_T = ALIGN_SIZE_T - ALIGN_PTRDIFF_T = Fiddle::JRuby::FFITypes[Types::PTRDIFF_T].alignment - ALIGN_INTPTR_T = Fiddle::JRuby::FFITypes[Types::INTPTR_T].alignment - ALIGN_UINTPTR_T = Fiddle::JRuby::FFITypes[Types::UINTPTR_T].alignment - ALIGN_BOOL = Fiddle::JRuby::FFITypes[Types::BOOL].alignment - - SIZEOF_VOIDP = Fiddle::JRuby::FFITypes[Types::VOIDP].size - SIZEOF_CHAR = Fiddle::JRuby::FFITypes[Types::CHAR].size - SIZEOF_SHORT = Fiddle::JRuby::FFITypes[Types::SHORT].size - SIZEOF_INT = Fiddle::JRuby::FFITypes[Types::INT].size - SIZEOF_LONG = Fiddle::JRuby::FFITypes[Types::LONG].size - SIZEOF_LONG_LONG = Fiddle::JRuby::FFITypes[Types::LONG_LONG].size - SIZEOF_FLOAT = Fiddle::JRuby::FFITypes[Types::FLOAT].size - SIZEOF_DOUBLE = Fiddle::JRuby::FFITypes[Types::DOUBLE].size - SIZEOF_SIZE_T = Fiddle::JRuby::FFITypes[Types::SIZE_T].size - SIZEOF_SSIZE_T = SIZEOF_SIZE_T - SIZEOF_PTRDIFF_T = Fiddle::JRuby::FFITypes[Types::PTRDIFF_T].size - SIZEOF_INTPTR_T = Fiddle::JRuby::FFITypes[Types::INTPTR_T].size - SIZEOF_UINTPTR_T = Fiddle::JRuby::FFITypes[Types::UINTPTR_T].size - SIZEOF_BOOL = Fiddle::JRuby::FFITypes[Types::BOOL].size -end diff --git a/lib/ruby/stdlib/fiddle/pack.rb b/lib/ruby/stdlib/fiddle/pack.rb index 81088f402b1..b41e36e8e26 100644 --- a/lib/ruby/stdlib/fiddle/pack.rb +++ b/lib/ruby/stdlib/fiddle/pack.rb @@ -41,6 +41,12 @@ module PackInfo # :nodoc: all when SIZEOF_LONG PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_ULONG] end + if RUBY_ENGINE == "jruby" and WINDOWS and [0].pack("l!").size == 8 + # JRuby's 'l!' pack string doesn't use 32-bit on Windows. + # See https://github.com/jruby/jruby/issues/8357 for details + PACK_MAP[TYPE_LONG] = PACK_MAP[TYPE_INT] + PACK_MAP[TYPE_ULONG] = PACK_MAP[TYPE_UINT] + end SIZE_MAP = { TYPE_VOIDP => SIZEOF_VOIDP, diff --git a/lib/ruby/stdlib/fiddle/struct.rb b/lib/ruby/stdlib/fiddle/struct.rb index 6d05bbd7421..e4c2c79ac59 100644 --- a/lib/ruby/stdlib/fiddle/struct.rb +++ b/lib/ruby/stdlib/fiddle/struct.rb @@ -290,15 +290,28 @@ def CStructEntity.alignment(types) # Allocates a C struct with the +types+ provided. # # See Fiddle::Pointer.malloc for memory management issues. - def CStructEntity.malloc(types, func = nil, size = size(types), &block) + def CStructEntity.malloc(types, func = nil, size = size(types)) + if block_given? and func.nil? + message = "a free function must be supplied to #{self}.malloc " + + "when it is called with a block" + raise ArgumentError, message + end + + pointer = Pointer.malloc(size) + begin + struct = new(pointer, types, func) + rescue + pointer.free = func + pointer.call_free + raise + end if block_given? - super(size, func) do |struct| - struct.set_ctypes types - yield struct + begin + yield(struct) + ensure + struct.call_free end else - struct = super(size, func) - struct.set_ctypes types struct end end @@ -505,6 +518,14 @@ def []=(*args) def to_s() # :nodoc: super(@size) end + + def +(delta) + Pointer.new(to_i + delta, @size - delta) + end + + def -(delta) + Pointer.new(to_i - delta, @size + delta) + end end # A pointer to a C union diff --git a/lib/ruby/stdlib/fiddle/version.rb b/lib/ruby/stdlib/fiddle/version.rb index 706d98a7b5a..6c5109dca8d 100644 --- a/lib/ruby/stdlib/fiddle/version.rb +++ b/lib/ruby/stdlib/fiddle/version.rb @@ -1,3 +1,3 @@ module Fiddle - VERSION = "1.1.2" + VERSION = "1.1.3" end diff --git a/pom.rb b/pom.rb index e0506d28533..da1cdae409b 100644 --- a/pom.rb +++ b/pom.rb @@ -67,7 +67,7 @@ # versions for default gems with bin executables # used in ./lib/pom.rb and ./maven/jruby-stdlib/pom.rb - 'rake.version' => '13.1.0', + 'rake.version' => '13.2.1', 'jruby-launcher.version' => '1.1.6', 'ant.version' => '1.9.8', 'asm.version' => '9.7.1', diff --git a/pom.xml b/pom.xml index cd7efc7cc64..ca5c26fe3f2 100644 --- a/pom.xml +++ b/pom.xml @@ -122,7 +122,7 @@ DO NOT MODIFY - GENERATED CODE pom.xml true utf-8 - 13.1.0 + 13.2.1 ${project.version}