Win: define Win32 API functions#4832
Conversation
src/lib_windows.cr
Outdated
|
|
||
| require "winerror.cr" | ||
|
|
||
| data = uninitialized LibWindows::WSAData |
There was a problem hiding this comment.
Does this need to be a top-level variable?
There was a problem hiding this comment.
I will remove these lines because as I see nothing from Winsock dll is used.
src/lib_windows.cr
Outdated
| @@ -0,0 +1,253 @@ | |||
| @[CallConvention("X86_StdCall")] | |||
There was a problem hiding this comment.
Just a quick question, have we tried without this? If we're using --target x86_64-pc-windows-msvc the default calling convention for everything should be X86_StdCall so it should work without.
src/lib_windows.cr
Outdated
| end | ||
|
|
||
| struct WIN32_FIND_DATA_A | ||
| dwFileAttributes : DWord |
There was a problem hiding this comment.
Renaming these struct members to be more crystally such as file_attributes here would be great.
There was a problem hiding this comment.
No, we should stick to same namings. Reasons:
- It's easier to lookup for documention;
- Avoids juggling with different names;
- Bindings should eventually be generated automatically; we shouldn't have to rewrite anything if/when that happens.
There was a problem hiding this comment.
just my 2 cents. I partly agree. Struct names have to be the same due to Microsoft documentation. But struct member naming can be changed because:
- otherwise they look alien
- it's still easy to find them in documentation due to struct naming
- I don't think this binding will be regenerated eventually (because API aren't changed for decades and other reasons). But even so, it would be easy to keep previous changed names during regeneration (it's just simple engineering problem)
And more importantly, what to do with the current function naming, for example:
fun duplicate_handle = DuplicateHandle(...)
Shoud I rename duplicate_handle as DuplicateHandle?
Sorry for long reading.
src/winerror.cr
Outdated
| @@ -0,0 +1,2104 @@ | |||
| class WinError < Exception | |||
There was a problem hiding this comment.
I deeply disagree with creating a WinError class. Errno is platform-specific, and it needs to go. Exception hierarchy should never depend on the platform you're running on.
There was a problem hiding this comment.
I thought about this. The problem is that errno also exists on Windows and it's used for C functions like _open link and Errno class is already working for Windows. So mostly Win32 API functions use GetLastError, "posix" subsystem (some functionality will be used in crystal) uses errno. So how to use one class for these different things simultaneously?
There was a problem hiding this comment.
You somewhat abstract system errors or map one to the other.
There was a problem hiding this comment.
Ok, I'll try to figure out then
There was a problem hiding this comment.
For now mapping to errno will work but we must remove errno before the first release. We should abstract the exception hierarchy to be platform specific. There's a good document on how python did this that we can take inspiration from. Doing that is beyond the scope of this pr though.
ysbaddaden
left a comment
There was a problem hiding this comment.
A few rules I would like this to have, following the the existing platform specific rules for POSIX systems:
- Bindings should live under
src/lib_c/arch-sys-abi, for examplesrc/lib_c/x86_64-pc-win32/c(I'm not sure of the exact target) andsrc/i686-pc-win32. - File and directory structure should follow the C headers counterpart (allowing to eventually generate these automatically).
- Keep exact naming of structs and fields (just like you did); it simplifies looking for documention.
This is all so such bindings can be generated automatically, make sure each architecture has a specific set of bindings (they usually have tiny differences) and documentation for and definitions in the original C headers can be found quickly and easily.
|
The correct target is |
|
Vendor in target triples is decorative and can be skipped safely, which we're doing in Crystal. We only keep Looking into the rust code, the windows targets seem to be the following, with a translation to GNU targets (for GCC?):
Since the vendor should be omitted, it would seem the target should be |
|
@ysbaddaden The problem is we don't just keep |
|
FYI, in win branch this way is used to find windows target path. |
|
I'm no sure. Did I fulfill the requests or I need to do something else? |
|
You can't assume
In fact, you don't need to change anything in Now, you can't assume |
|
If I run |
|
@txe "x86_64-windows-msvc" is the correct triple, but you can't define all triples containing windows to be that. |
|
I installed MSYS2 and installed LLVM (mingw-w64-x86_64-llvm) there. This version reports |
src/winerror.cr
Outdated
|
|
||
| def winerror_to_errno(winerror) | ||
| case winerror | ||
| when 2; return 2 |
There was a problem hiding this comment.
This is a bunch of magical numbers. I have no idea what they mean. Where do the value come from?
There was a problem hiding this comment.
There is an undocumented function _dosmaperr. Python uses this functions to generate a mapper. Because the mapper has not be changed for 6 years, I supposed it's quite correct and just copied those numbers.
There was a problem hiding this comment.
It would be great if you could replace these numbers with their respective constants.
| set.add "freebsd" if set.any?(&.starts_with?("freebsd")) | ||
| set.add "openbsd" if set.any?(&.starts_with?("openbsd")) | ||
| set.add "unix" if set.any? { |flag| %w(cygnus darwin freebsd linux openbsd).includes?(flag) } | ||
| set.add "win32" if set.any?(&.starts_with?("windows")) && set.any? { |flag| %w(gnu msvc).includes?(flag) } |
There was a problem hiding this comment.
Why not just use the "windows" flag?
ysbaddaden
left a comment
There was a problem hiding this comment.
This is starting to look very good.
I just personally wish functions, structs and fields naming would keep their original form: SYSTEMTIME, TIME_ZONE_INFORMATION, wDayOfWeek, ...
The problem are functions, since Windows decided they should be CamelCase... maybe prefix them with an _ or keep them as underscored...
src/winerror.cr
Outdated
| when 267; return 20 | ||
| when 1816; return 12 | ||
| else return Errno::EINVAL | ||
| when ERROR_FILE_NOT_FOUND ; return Errno::ENOENT |
There was a problem hiding this comment.
You don't need semicolons. In fact you don't even need return:
when ERROR_FILE_NOT_FOUND then Errno::ENOENT| daylight_bias : Long | ||
| end | ||
|
|
||
| struct FileTime |
There was a problem hiding this comment.
Duplication: there is already FILETIME above.
I didn't get it. Could you give an example of what to do? |
ysbaddaden
left a comment
There was a problem hiding this comment.
Looks perfect to me!
I believe keeping the original case is important, but I understand that keeping the function names with a leading underscore may not be the best choice. If someone doesn't like that, maybe we can agree on something better. Otherwise, perfect!
|
Thanks! |
src/winerror.cr
Outdated
| buffer = uninitialized UInt8[256] | ||
| size = LibC._FormatMessageA(LibC::FORMAT_MESSAGE_FROM_SYSTEM, nil, code, 0, buffer, buffer.size, nil) | ||
| details = String.new(buffer.to_unsafe, size).strip | ||
| super "#{message}: [WinError #{code}, #{details}]", winerror_to_errno(code) |
There was a problem hiding this comment.
Just a tiny subjective nitpick, can we have brackets here (super("#{message}: [WinError #{code}, #{details}]", winerror_to_errno(code))), it looks weird without (I actually missed the winerror_to_errno call).
|
IO::FileDescriptor is implemented |
|
Where? It's not in this PR. |
|
It's in my branch, I'm going to make a number of small PRs, so that will help to keep things simple. |
|
Can't wait for other PRs 😍 |
|
So why did Windows stuff end up in |
|
Because everything in |
|
|
|
I thought a bit about flag |
|
Any progress on approving the PR? |
|
I maintain that we should find a less ugly way of naming these functions than starting with |
|
@txe Even though function names can start with uppercase, that will only happen in the next release. So until then you'll probably have to use the underscore... |
This reverts commit f416f6c. revert the previous commit
|
So, I suppose, it doesn't make sense to merge this PR until the next release? |
|
@txe I think it does make sense. Later we can rename the function names. |
|
🎉 |
I'd like to begin merging source from txe/crystal-win:win with master doing it bit by bit.
This PR adds some basic stuff which will be used by code related to Windows:
I suppose the file and function naming is controversial so I'm prepared to change the naming if you give appropriate one.