-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Win: define Win32 API functions #4832
Changes from all commits
54c41eb
6467ece
b380d2d
9ab0fe2
47669e3
27b96fa
51ef5c6
8501cdc
6fa4c19
7392588
9dc4c97
9610937
f416f6c
00a6232
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
lib LibC | ||
# source https://docs.microsoft.com/en-us/cpp/c-runtime-library/errno-doserrno-sys-errlist-and-sys-nerr | ||
EPERM = 1 | ||
ENOENT = 2 | ||
ESRCH = 3 | ||
EINTR = 4 | ||
EIO = 5 | ||
ENXIO = 6 | ||
E2BIG = 7 | ||
ENOEXEC = 8 | ||
EBADF = 9 | ||
ECHILD = 10 | ||
EAGAIN = 11 | ||
ENOMEM = 12 | ||
EACCES = 13 | ||
EFAULT = 14 | ||
EBUSY = 16 | ||
EEXIST = 17 | ||
EXDEV = 18 | ||
ENODEV = 19 | ||
ENOTDIR = 20 | ||
EISDIR = 21 | ||
EINVAL = 22 | ||
ENFILE = 23 | ||
EMFILE = 24 | ||
ENOTTY = 25 | ||
EFBIG = 27 | ||
ENOSPC = 28 | ||
ESPIPE = 29 | ||
EROFS = 30 | ||
EMLINK = 31 | ||
EPIPE = 32 | ||
EDOM = 33 | ||
ERANGE = 34 | ||
EDEADLK = 36 | ||
ENAMETOOLONG = 38 | ||
ENOLCK = 39 | ||
ENOSYS = 40 | ||
ENOTEMPTY = 41 | ||
EILSEQ = 42 | ||
STRUNCATE = 80 | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
lib LibC | ||
STD_INPUT_HANDLE = 0xFFFFFFF6_u32 | ||
STD_OUTPUT_HANDLE = 0xFFFFFFF5_u32 | ||
STD_ERROR_HANDLE = 0xFFFFFFF4_u32 | ||
|
||
FILE_TYPE_UNKNOWN = 0x0000 | ||
FILE_TYPE_DISK = 0x0001 | ||
FILE_TYPE_CHAR = 0x0002 | ||
FILE_TYPE_PIPE = 0x0003 | ||
FILE_TYPE_REMOTE = 0x8000 | ||
|
||
GENERIC_EXECUTE = 0x20000000 | ||
GENERIC_WRITE = 0x40000000 | ||
GENERIC_READ = 0x80000000 | ||
|
||
CREATE_NEW = 1 | ||
CREATE_ALWAYS = 2 | ||
OPEN_EXISTING = 3 | ||
OPEN_ALWAYS = 4 | ||
TRUNCATE_EXISTING = 5 | ||
|
||
FILE_FLAG_OVERLAPPED = 0x40000000 | ||
|
||
# source https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx | ||
alias Long = Int32 | ||
alias Word = UInt16 | ||
alias WChar = UInt16 | ||
alias DWord = UInt32 | ||
alias Handle = Void* | ||
alias SizeT = UInt64 | ||
alias BOOL = Int32 # FIXME maybe it need to be removed because it can be confused with Bool | ||
|
||
INVALID_HANDLE_VALUE = Pointer(Void).new((-1).to_u64) | ||
INFINITY = 0xFFFFFFFF_u32 | ||
|
||
fun _DuplicateHandle = DuplicateHandle(source_process : Handle, source : Handle, target_process : Handle, target : Handle*, desired_access : DWord, inherit_handle : Bool, options : DWord) : Bool | ||
|
||
# member names are not original otherwise they would be really confusing | ||
struct OVERLAPPED | ||
status : SizeT | ||
bytes_transfered : SizeT | ||
offset : UInt64 | ||
event : Handle | ||
end | ||
|
||
struct SECURITY_ATTRIBUTES | ||
nLength : DWord | ||
lpSecurityDescriptor : Void* | ||
bInheritHandle : BOOL | ||
end | ||
|
||
fun _GetStdHandle = GetStdHandle(std_handle : DWord) : Handle | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused as to why we're adding underscores to symbol names which appear not to be underscored in the first place. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find an underscore a really ugly way of solving this, so I think we should be able to define If we can't relax that requirement easily only for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we could relax this rule, I have no problem with that, specially for lib functions. For class methods there's also no problem. The only problem is top level methods: # This is valid in Ruby
def Foo(x)
end
# But this is always a generic instantiation in Crystal
Foo(String) We still have time to relax this rule everywhere and change generics to use For now, we can relax the rule for lib funs and relax the rule for method calls... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer if if we only relaxed the rule for lib funs myself, I don't think there's a usecase for this outside external symbols, and I don't want to encourage confusing method casing for typical class maethods. Really though I think we should just rename these methods and not change the compiler. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally I'd prefer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we allow any case for I thought there could be a problem with that if in the future we allow bindings to C++, since there will be a need for generic class inside the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bcardiff I was thinking exactly the same thing yesterday. This should be applicable to structs, and maybe even aliases like Since all these types have to be prefixed with a lib, like This also removes the confusion between Crystal's Yesterday I also remembered we have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still think that this is a lot of unnecessary complexity just to allow us to use names from C unchanged. Is it really worth it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's almost trivial to implement and will simplify writing bindings. So why not? |
||
fun _GetFileType = GetFileType(file : Handle) : DWord | ||
fun _CreateFileA = CreateFileA(filename : UInt8*, access : DWord, sharemode : DWord, security_attributes : SECURITY_ATTRIBUTES*, creation : DWord, flags : DWord, template : Handle) : Handle | ||
fun _ReadFile = ReadFile(file : Handle, buffer : UInt8*, size : DWord, read : DWord*, overlapped : OVERLAPPED*) : Bool | ||
fun _WriteFile = WriteFile(file : Handle, buffer : UInt8*, size : DWord, written : DWord*, overlapped : OVERLAPPED*) : Bool | ||
fun _CloseHandle = CloseHandle(file : Handle) : Bool | ||
|
||
fun _GetCurrentDirectoryA = GetCurrentDirectoryA(size : DWord, buffer : UInt8*) : DWord | ||
fun _SetCurrentDirectoryA = SetCurrentDirectoryA(path : UInt8*) : BOOL | ||
fun _CreateDirectoryA = CreateDirectoryA(path : UInt8*, security_attribute : Void*) : BOOL | ||
fun _RemoveDirectoryA = RemoveDirectoryA(path : UInt8*) : BOOL | ||
fun _GetTempPathA = GetTempPathA(len : DWord, buffer : UInt8*) : DWord | ||
|
||
MAX_PATH = 260 | ||
|
||
struct FILETIME | ||
dwLowDateTime : DWord | ||
dwHighDateTime : DWord | ||
end | ||
|
||
struct WIN32_FIND_DATA_A | ||
dwFileAttributes : DWord | ||
ftCreationTime : FILETIME | ||
ftLastAccessTime : FILETIME | ||
ftLastWriteTime : FILETIME | ||
nFileSizeHigh : DWord | ||
nFileSizeLow : DWord | ||
dwReserved0 : DWord | ||
dwReserved1 : DWord | ||
cFileName : StaticArray(UInt8, MAX_PATH) | ||
cAlternateFileName : StaticArray(UInt8, 14) | ||
end | ||
|
||
FILE_ATTRIBUTE_ARCHIVE = 32_i32 | ||
FILE_ATTRIBUTE_COMPRESSED = 2048_i32 | ||
FILE_ATTRIBUTE_NORMAL = 128_i32 | ||
FILE_ATTRIBUTE_DIRECTORY = 16_i32 | ||
FILE_ATTRIBUTE_HIDDEN = 2_i32 | ||
FILE_ATTRIBUTE_READONLY = 1_i32 | ||
FILE_ATTRIBUTE_REPARSE_POINT = 1024_i32 | ||
FILE_ATTRIBUTE_SYSTEM = 4_i32 | ||
FILE_ATTRIBUTE_TEMPORARY = 256_i32 | ||
INVALID_FILE_ATTRIBUTES = -1_i32 | ||
|
||
FILE_BEGIN = 0_i32 | ||
FILE_CURRENT = 1_i32 | ||
FILE_END = 2_i32 | ||
INVALID_SET_FILE_POINTER = (-1).to_u32 | ||
|
||
fun _FindFirstFileA = FindFirstFileA(fileName : UInt8*, filedata : WIN32_FIND_DATA_A*) : Handle | ||
fun _FindNextFileA = FindNextFileA(file : Handle, filedata : WIN32_FIND_DATA_A*) : BOOL | ||
fun _FindClose = FindClose(file : Handle) : BOOL | ||
fun _GetFileAttributesA = GetFileAttributesA(filename : UInt8*) : DWord | ||
fun _GetFileSize = GetFileSize(file : Handle, fileSizeHigh : DWord*) : DWord | ||
fun _GetFileSizeEx = GetFileSizeEx(file : Handle, size : UInt64*) : BOOL | ||
fun _GetFileTime = GetFileTime(file : Handle, lpCreationTime : FILETIME*, lpLastAccessTime : FILETIME*, lpLastWriteTime : FILETIME*) : BOOL | ||
fun _SetFilePointer = SetFilePointer(file : Handle, lDistanceToMove : Long, lpDistanceToMoveHigh : Long*, dwMoveMethod : DWord) : DWord | ||
fun _SetEndOfFile = SetEndOfFile(file : Handle) : BOOL | ||
fun _DeleteFileA = DeleteFileA(filename : UInt8*) : BOOL | ||
fun _GetFullPathNameA = GetFullPathNameA(filename : UInt8*, buf_len : DWord, lpBuffer : UInt8*, lpFilePart : UInt8**) : DWord | ||
# from Shlwapi.lib | ||
# fun _PathFileExistsA = PathFileExistsA(path : UInt8*) : BOOL | ||
fun _MoveFileA = MoveFileA(lpExistingFileName : UInt8*, lpNewFileName : UInt8*) : BOOL | ||
fun _GetTempFileNameA = GetTempFileNameA(path_name : UInt8*, prefix : UInt8*, unique_num : UInt32, temp_file_name : UInt8*) : UInt32 | ||
|
||
fun _CreateIoCompletionPort = CreateIoCompletionPort(file : Handle, port : Handle, data : Void*, threads : DWord) : Handle | ||
fun _GetQueuedCompletionStatus = GetQueuedCompletionStatus(port : Handle, bytes_transfered : DWord*, data : Void**, entry : OVERLAPPED**, timeout_millis : DWord) : Bool | ||
fun _PostQueuedCompletionStatus = PostQueuedCompletionStatus(port : Handle, bytes_transfered : DWord, data : Void*, entry : OVERLAPPED*) : Bool | ||
fun _GetCurrentProcess = GetCurrentProcess : Handle | ||
fun _GetCurrentThread = GetCurrentThread : Handle | ||
fun _CreatePipe = CreatePipe(hReadPipe : UInt64*, hWritePipe : UInt64*, lpPipeAttributes : SECURITY_ATTRIBUTES*, nSize : DWord) : BOOL | ||
fun _PeekNamedPipe = PeekNamedPipe(hNamedPipe : Handle, lpBuffer : UInt8*, nBufferSize : DWord, lpBytesRead : DWord*, lpTotalBytesAvail : DWord*, lpBytesLeftThisMessage : DWord*) : BOOL | ||
|
||
WAIT_ABANDONED = 0x00000080_u32 | ||
WAIT_OBJECT_0 = 0x00000000_u32 | ||
WAIT_TIMEOUT = 0x00000102_u32 | ||
WAIT_FAILED = 0xFFFFFFFF_u32 | ||
|
||
fun _WaitForSingleObject = WaitForSingleObject(handle : Handle, timeout_millis : DWord) : DWord | ||
fun _CreateTimerQueueTimer = CreateTimerQueueTimer(timer_handle : Handle*, queue_handle : Handle, callback : (Void*, Bool) ->, data : Void*, due : DWord, period : DWord, flags : SizeT) : Bool | ||
fun _DeleteTimerQueueTimer = DeleteTimerQueueTimer(queue_handle : Handle, timer_handle : Handle, completion_event : Handle) : Bool | ||
fun _GetLastError = GetLastError : DWord | ||
fun _SetLastError = SetLastError(code : DWord) : Void | ||
|
||
# STARTUPINFOA.deFlags | ||
STARTF_USESTDHANDLES = 0x00000100_u32 | ||
|
||
# CreateProcessA.dwCreationFlags | ||
NORMAL_PRIORITY_CLASS = 0x00000020_u32 | ||
CREATE_NO_WINDOW = 0x08000000_u32 | ||
|
||
struct STARTUPINFOA | ||
cb : DWord | ||
lpReserved : UInt8* | ||
lpDesktop : UInt8* | ||
lpTitle : UInt8* | ||
dwX : DWord | ||
dwY : DWord | ||
dwXSize : DWord | ||
dwYSize : DWord | ||
dwXCountChars : DWord | ||
dwYCountChars : DWord | ||
dwFillAttribute : DWord | ||
dwFlags : DWord | ||
wShowWindow : Word | ||
cbReserved2 : Word | ||
lpReserved2 : UInt8* | ||
hStdInput : Handle | ||
hStdOutput : Handle | ||
hStdError : Handle | ||
end | ||
|
||
struct PROCESS_INFORMATION | ||
hProcess : Handle | ||
hThread : Handle | ||
dwProcessId : DWord | ||
dwThreadId : DWord | ||
end | ||
|
||
fun _CreateProcessA = CreateProcessA(lpApplicationName : UInt8*, lpCommandLine : UInt8*, | ||
lpProcessAttributes : SECURITY_ATTRIBUTES*, lpThreadAttributes : SECURITY_ATTRIBUTES*, bInheritHandles : BOOL, | ||
dwCreationFlags : DWord, lpEnvironment : Void*, lpCurrentDirectory : UInt8*, | ||
lpStartupInfo : STARTUPINFOA*, lpProcessInformation : PROCESS_INFORMATION*) : BOOL | ||
fun _KillProcess = KillProcess(hProcess : Handle, uExitCode : UInt32) : BOOL | ||
fun _GetExitCodeProcess = GetExitCodeProcess(hProcess : Handle, lpExitCode : DWord*) : BOOL | ||
|
||
FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100_u32 | ||
FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200_u32 | ||
FORMAT_MESSAGE_FROM_STRING = 0x00000400_u32 | ||
FORMAT_MESSAGE_FROM_HMODULE = 0x00000800_u32 | ||
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000_u32 | ||
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000_u32 | ||
|
||
fun _FormatMessageA = FormatMessageA(flags : DWord, source : Void*, msg : DWord, lang : DWord, buffer : UInt8*, size : DWord, args : Void*) : DWord | ||
|
||
WSASYSNOTREADY = 10091 | ||
WSAVERNOTSUPPORTED = 10092 | ||
WSAEINPROGRESS = 10036 | ||
WSAEPROCLIM = 10067 | ||
WSAEFAULT = 10014 | ||
WSAEINVAL = 10022 | ||
|
||
struct WSAData | ||
wVersion : UInt16 | ||
wHighVersion : UInt16 | ||
szDescription : UInt8[257] | ||
szSystemStatus : UInt8[129] | ||
iMaxSockets : UInt16 | ||
iMaxUdpDg : UInt16 | ||
lpVendorInfo : UInt8* | ||
end | ||
|
||
fun _WSAStartup = WSAStartup(version : Int16, data : WSAData*) : Int32 | ||
|
||
# source https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx | ||
struct SystemTime | ||
wYear : Word | ||
wMonth : Word | ||
wDayOfWeek : Word | ||
wDay : Word | ||
wHour : Word | ||
wMinute : Word | ||
wSecond : Word | ||
wMilliseconds : Word | ||
end | ||
|
||
# source https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx | ||
struct TIME_ZONE_INFORMATION | ||
_Bias : Long | ||
_StandardName : StaticArray(WChar, 32) | ||
_StandardDate : SYSTEMTIME | ||
_StandardBias : Long | ||
_DaylightName : StaticArray(WChar, 32) | ||
_DaylightDate : SYSTEMTIME | ||
_DaylightBias : Long | ||
end | ||
|
||
fun _GetTimeZoneInformation = GetTimeZoneInformation(tz_info : TIME_ZONE_INFORMATION*) : DWord | ||
fun _GetSystemTimeAsFileTime = GetSystemTimeAsFileTime(time : FILETIME*) | ||
|
||
fun _GetComputerNameA = GetComputerNameA(buffer : UInt8*, size : DWord*) : BOOL | ||
|
||
fun _CxxThrowException = _CxxThrowException(exception_object : Void*, throw_info : Void*) : NoReturn | ||
end | ||
|
||
module WindowsExt | ||
@[Primitive(:throw_info)] | ||
def self.throw_info : Void* | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just use the "windows" flag?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason is given in #4832 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I didn't see that.