Open casper opened 6 years ago
I get the strange suspicion something if not right with FFI here. This is on a 32-bit installation btw. That might also be relevant.
Full setup for clarification: Clean installation of Cygwin 32-bit + build of Ruby 2.5.1 under Cygwin + gem install of win32-sound.
Okay I figured out the problem, and it is two-fold. Both ffi and win32-sound make incorrect assumptions about cygwin.
The first problem is that types.conf in ffi doesn't have a mapping for uintptr_t
. This can be fixed by adding
rbx.platform.typedef.uintptr_t = uint64
as seen here
An alternative fix is to simply use :uint64
in place of :uintptr_t
in these sorts of places.
Fortunately, this means this can be fixed within this project.
Even if we fix the first problem, we get a new one. We start getting errors like this:
LoadError (Could not open library 'kernel32': No such file or directory.)
Could not open library 'cygkernel32.dll': No such file or directory
The problem here is that when we tell ffi to load a library like here, ffi decides to generate library file names here. Unfortunately, it has no special case for cygwin, and prepends the string 'cyg' to the library name, along with adding '.dll' to the end. Of course, there is no file named 'cygkernel32.dll', as this is nonsense.
What it needs to do is generate the string 'kernel32.dll'.
Of course, this would have to be a fix to ffi.
So even if you fix the uintptr_t
problem, and you get ffi to correctly load kernel32 and winmm, you may run into the problem where the structs are the wrong size. This is caused by the use of ushort
and ulong
in this code. Cygwin isn't aware that we're trying to use a 32-bit library, and happily creates a modern struct with bigger members than we were expecting.
This is fixed by replacing ushort
with uint16
and ulong
with uint32
. (And it would be a good idea to comb through any other repos that use ffi which may be used within a cygwin64 environment which hit old windows libraries).
So both ffi and win32-sound were making incorrect assumptions about cygwin, which resulted in incorrect file lookups and memory layouts, and fixes to code would be needed in both projects.
@casper Ah, I didn't notice you were on a 32-bit Cygwin by the time I did my analysis, and I only checked on a 64-bit version. Luckily, these fixes should cover both.
Thanks domgetter. That's an excellent summary (sorry for the late reply). But I gather that there really isn't any immediate solution for this then, as it would require upstream fixes on FFI first?
There are a couple workarounds for you. You could modify your installation of the FFI gem so that it loads the library correctly, and modify your installation of win32-sound so that the types are picked up correctly.
You could also install ruby natively to Windows, and then call that installation within Cygwin. FFI can load native libraries just fine. This is what confused me at first with your bug. When I loaded up Cygwin, everything worked just fine because I had Ruby and the gems installed on Windows. But I noticed from the filepaths in your error that you installed everything from within Cygwin.
I think those are your only two options for now. If you want to do the first option (modify inplace), let me know and I can help you dig through and change the code. Personally, I think the second option is much easier :P, but I don't know your exact use case here.
Ok. Thanks. I will think about these. I tried option 2 earlier, but the machine I'm using is too old to run the latest DevKit bundle for Ruby (MSYS2 support has been dropped for older Windows versions). That was actually the original reason for installing Ruby with Cygwin. Even the Ruby 2.5 Cygwin installation had problems on 32-bit Windows , because I think it's using the same broken FFI for its build process. I might give option 1 a shot at some point. Will comment here if I make some progress on it.
Any way to get this to work? I get the following error when requiring the library: