From: "cfis (Charlie Savage) via ruby-core" Date: 2025-11-15T05:58:14+00:00 Subject: [ruby-core:123803] [Ruby Bug#21498] Windows - Ruby Overrides C Library APIs thus breaking them Issue #21498 has been updated by cfis (Charlie Savage). I gave a try to @nobu's code above (https://bugs.ruby-lang.org/issues/21498#note-9). That results in a linker error: ``` c linking shared-object -test-/gvl/call_without_gvl.so Creating library call_without_gvl-x64-mswin64_140.lib and object call_without_gvl-x64-mswin64_140.exp call_without_gvl.obj : error LNK2019: unresolved external symbol __imp_select referenced in function do_loop ..\..\..\..\.ext\x64-mswin64_140\-test-\gvl\call_without_gvl.so : fatal error LNK1120: 1 unresolved externals NMAKE : fatal error U1077: '@ cl -nologo -LD -Fe../../../../.ext/x64-mswin64_140/-test-/gvl/call_without_gvl.so call_without_gvl.obj x64-vcruntime140-ruby340.lib user32.lib -link -incremental:no -debug -opt:ref -opt:icf -manifest:embed,ID=2 -incremental:no -debug -opt:ref -opt:icf -manifest:embed,ID=2 -dll -libpath:. -libpath:../../../.. -implib:call_without_gvl-x64-mswin64_140.lib -pdb:call_without_gvl-x64-mswin64_140.pdb -def:call_without_gvl-x64-mswin64_140.def' : return code '0x2' Stop. NMAKE : fatal error U1077: '@cd ext/-test-/gvl/call_without_gvl && "C:\Program Files\Microsoft Visual Studio\18\Insiders\VC\Tools\MSVC\14.50.35717\bin\HostX64\x64\nmake.EXE" -L V=0 all' : return code '0x2' Stop. NMAKE : fatal error U1077: '@nmake -f exts.mk -l libdir="c:\msys64\usr\local\ruby-3.4.7-mswin/lib" LIBRUBY_EXTS=./.libruby-with-ext.time EXTENCS="dmyenc.obj" BASERUBY="C:\msys64\usr\local\ruby\bin\ruby.exe" MINIRUBY=".\miniruby.exe -I./lib -I. " ' : return code '0x2' Stop. ``` Which is due to `select` not being part of the UCRT. What if Ruby did not export only the functions that overlap with UCRT on Windows - the ones listed in this comment - https://bugs.ruby-lang.org/issues/21498#note-8 ---------------------------------------- Bug #21498: Windows - Ruby Overrides C Library APIs thus breaking them https://bugs.ruby-lang.org/issues/21498#change-115207 * Author: cfis (Charlie Savage) * Status: Open * Assignee: windows * ruby -v: *all* on windows (testing with ruby 3.4.3 (2025-04-14 revision d0b7e5b6a0) +PRISM [x64-mswin64_140]) * Backport: 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN ---------------------------------------- I am trying to wrap a simple C++ library, https://github.com/baderouaich/BitmapPlusPlus, as a Ruby extension. However when I use the extension to write a bitmap to disk the bitmap is corrupted. This is because the library uses std::ofstream which eventually uses the C API fclose to write the final bytes to the bitmap file and then closes it. The problem is that Ruby overrides `fclose` and replaces it with `rb_w32_fclose`. It then *exports* its custom version from from x64-vcruntime140-ruby340.dll. And the exported version is broken (at least from the standpoint of the C standard library). Note this has been a long standing issue. The first report I see is from 2013: https://bugs.ruby-lang.org/issues/8569 More recently in 2020 (which explains the issue very well): https://github.com/NREL/OpenStudio/issues/3942#issuecomment-610673401 I understand that Ruby is trying to provide a platform independent API. But the problem is this solution breaks any third party libraries that rely on these C APIs (which of course are very common). And there is no good workaround (see https://github.com/NREL/OpenStudio/issues/3942#issuecomment-611072774). So would it be possible for Ruby to stop exporting custom versions of basic C APIs? The code that does it is here: https://github.com/ruby/ruby/blob/master/win32/mkexports.rb#L41 Ruby of course could still use its custom versions of `fclose`, read, write etc within ruby.exe and x64-vcruntime140-ruby340.dll. But they should not be exported from x64-vcruntime140-ruby340.dll and thus be off limits to extensions. If a case comes up where an extension really needs access to rb_w32_fclose instead of fclose then an extension developer can use an `#ifdef _WIN32` to do so and work across platforms. That at least puts the developer in control versus now where I don't see any way I can wrap the bitmap library as a Ruby extension. >From my experience the biggest problem is the replacing of fclose with rb_w32_fclose. This is the list of generated overrides: FD_CLR=rb_w32_fdclr FD_ISSET=rb_w32_fdisset Sleep=rb_w32_Sleep accept=rb_w32_accept access=rb_w32_uaccess bind=rb_w32_bind close=rb_w32_close connect=rb_w32_connect dup2=rb_w32_dup2 fclose=rb_w32_fclose fstat=rb_w32_fstati128 get_osfhandle=rb_w32_get_osfhandle getcwd=rb_w32_ugetcwd getenv=rb_w32_ugetenv gethostbyaddr=rb_w32_gethostbyaddr gethostbyname=rb_w32_gethostbyname gethostname=rb_w32_gethostname getpeername=rb_w32_getpeername getpid=rb_w32_getpid getppid=rb_w32_getppid getprotobyname=rb_w32_getprotobyname getprotobynumber=rb_w32_getprotobynumber getservbyname=rb_w32_getservbyname getservbyport=rb_w32_getservbyport getsockname=rb_w32_getsockname getsockopt=rb_w32_getsockopt inet_ntop=rb_w32_inet_ntop inet_pton=rb_w32_inet_pton ioctlsocket=rb_w32_ioctlsocket isatty=rb_w32_isatty listen=rb_w32_listen lseek=rb_w32_lseek lstat=rb_w32_ulstati128 mkdir=rb_w32_umkdir mmap=rb_w32_mmap mprotect=rb_w32_mprotect munmap=rb_w32_munmap pipe=rb_w32_pipe pread=rb_w32_pread pwrite=rb_w32_pwrite read=rb_w32_read recv=rb_w32_recv recvfrom=rb_w32_recvfrom rename=rb_w32_urename rmdir=rb_w32_urmdir select=rb_w32_select send=rb_w32_send sendto=rb_w32_sendto setsockopt=rb_w32_setsockopt shutdown=rb_w32_shutdown socket=rb_w32_socket stati128=rb_w32_ustati128 strcasecmp=msvcrt.stricmp strerror=rb_w32_strerror strncasecmp=msvcrt.strnicmp times=rb_w32_times unlink=rb_w32_uunlink utime=rb_w32_uutime utimensat=rb_w32_uutimensat utimes=rb_w32_uutimes write=rb_w32_write ---Files-------------------------------- Screenshot 2025-11-06 233918.png (223 KB) primitives.bmp (360 KB) primitives_bad.bmp (360 KB) -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/