diff --git a/core/dynlib/doc.odin b/core/dynlib/doc.odin new file mode 100644 index 000000000..812fb02d5 --- /dev/null +++ b/core/dynlib/doc.odin @@ -0,0 +1,7 @@ +/* +Package core:dynlib implements loading of shared libraries/DLLs and their symbols. + +The behaviour of dynamically loaded libraries is specific to the target platform of the program. +For in depth detail on the underlying behaviour please refer to your target platform's documentation. +*/ +package dynlib diff --git a/core/dynlib/lib.odin b/core/dynlib/lib.odin index a6c857ee4..b5cb16e3c 100644 --- a/core/dynlib/lib.odin +++ b/core/dynlib/lib.odin @@ -1,15 +1,94 @@ package dynlib +/* +A handle to a dynamically loaded library. +*/ Library :: distinct rawptr -load_library :: proc(path: string, global_symbols := false) -> (Library, bool) { +/* +Loads a dynamic library from the filesystem. The paramater `global_symbols` makes the symbols in the loaded +library available to resolve references in subsequently loaded libraries. + +The paramater `global_symbols` is only used for the platforms `linux`, `darwin`, `freebsd` and `openbsd`. +On `windows` this paramater is ignored. + +The underlying behaviour is platform specific. +On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlopen`. +On `windows` refer to `LoadLibraryW`. + +**Implicit Allocators** +`context.temp_allocator` + +Example: + import "core:dynlib" + import "core:fmt" + + load_my_library :: proc() { + LIBRARY_PATH :: "my_library.dll" + library, ok := dynlib.load_library(LIBRARY_PATH) + if ! ok { + return + } + fmt.println("The library %q was successfully loaded", LIBRARY_PATH) + } +*/ +load_library :: proc(path: string, global_symbols := false) -> (library: Library, did_load: bool) { return _load_library(path, global_symbols) } -unload_library :: proc(library: Library) -> bool { +/* +Unloads a dynamic library. + +The underlying behaviour is platform specific. +On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlclose`. +On `windows` refer to `FreeLibrary`. + +Example: + import "core:dynlib" + import "core:fmt" + + load_then_unload_my_library :: proc() { + LIBRARY_PATH :: "my_library.dll" + library, ok := dynlib.load_library(LIBRARY_PATH) + if ! ok { + return + } + did_unload := dynlib.unload_library(library) + if ! did_unload { + return + } + fmt.println("The library %q was successfully unloaded", LIBRARY_PATH) + } +*/ +unload_library :: proc(library: Library) -> (did_unload: bool) { return _unload_library(library) } +/* +Loads the address of a procedure/variable from a dynamic library. + +The underlying behaviour is platform specific. +On `linux`, `darwin`, `freebsd` and `openbsd` refer to `dlsym`. +On `windows` refer to `GetProcAddress`. + +**Implicit Allocators** +`context.temp_allocator` + +Example: + import "core:dynlib" + import "core:fmt" + + find_a_in_my_library :: proc() { + LIBRARY_PATH :: "my_library.dll" + library, ok := dynlib.load_library(LIBRARY_PATH) + if ! ok { + return + } + + a, found_a := dynlib.symbol_address(library, "a") + if found_a do fmt.printf("The symbol %q was found at the address %v", "a", a) + } +*/ symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) #optional_ok { return _symbol_address(library, symbol) } diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index f736696e1..5f09dda3c 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -370,6 +370,9 @@ foreign kernel32 { GenerateConsoleCtrlEvent :: proc(dwCtrlEvent: DWORD, dwProcessGroupId: DWORD) -> BOOL --- FreeConsole :: proc() -> BOOL --- GetConsoleWindow :: proc() -> HWND --- + GetConsoleScreenBufferInfo :: proc(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO) -> BOOL --- + SetConsoleScreenBufferSize :: proc(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL --- + SetConsoleWindowInfo :: proc(hConsoleOutput: HANDLE, bAbsolute : BOOL, lpConsoleWindow: ^SMALL_RECT) -> BOOL --- GetDiskFreeSpaceExW :: proc( lpDirectoryName: LPCWSTR, diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index 1b45f61ba..514998a43 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -3767,6 +3767,24 @@ COORD :: struct { Y: SHORT, } +SMALL_RECT :: struct { + Left: SHORT, + Top: SHORT, + Right: SHORT, + Bottom: SHORT, +} + +CONSOLE_SCREEN_BUFFER_INFO :: struct { + dwSize: COORD, + dwCursorPosition: COORD, + wAttributes: WORD, + srWindow: SMALL_RECT, + dwMaximumWindowSize: COORD, +} + + +PCONSOLE_SCREEN_BUFFER_INFO :: ^CONSOLE_SCREEN_BUFFER_INFO + // // Networking // @@ -3909,39 +3927,39 @@ ipv6_mreq :: struct { } SOCKADDR_STORAGE_LH :: struct { - ss_family: ADDRESS_FAMILY, - __ss_pad1: [6]CHAR, + ss_family: ADDRESS_FAMILY, + __ss_pad1: [6]CHAR, __ss_align: i64, - __ss_pad2: [112]CHAR, + __ss_pad2: [112]CHAR, } ADDRINFOA :: struct { - ai_flags: c_int, - ai_family: c_int, - ai_socktype: c_int, - ai_protocol: c_int, - ai_addrlen: size_t, + ai_flags: c_int, + ai_family: c_int, + ai_socktype: c_int, + ai_protocol: c_int, + ai_addrlen: size_t, ai_canonname: ^c_char, - ai_addr: ^SOCKADDR, - ai_next: ^ADDRINFOA, + ai_addr: ^SOCKADDR, + ai_next: ^ADDRINFOA, } sockaddr :: struct { sa_family: USHORT, - sa_data: [14]byte, + sa_data: [14]byte, } sockaddr_in :: struct { sin_family: ADDRESS_FAMILY, - sin_port: u16be, - sin_addr: in_addr, - sin_zero: [8]CHAR, + sin_port: u16be, + sin_addr: in_addr, + sin_zero: [8]CHAR, } sockaddr_in6 :: struct { - sin6_family: ADDRESS_FAMILY, - sin6_port: u16be, + sin6_family: ADDRESS_FAMILY, + sin6_port: u16be, sin6_flowinfo: c_ulong, - sin6_addr: in6_addr, + sin6_addr: in6_addr, sin6_scope_id: c_ulong, } @@ -3968,36 +3986,36 @@ DNS_RECORD :: struct { _: DWORD, Data: struct #raw_union { CNAME: DNS_PTR_DATAA, - A: u32be, // Ipv4 Address - AAAA: u128be, // Ipv6 Address - TXT: DNS_TXT_DATAA, - NS: DNS_PTR_DATAA, - MX: DNS_MX_DATAA, - SRV: DNS_SRV_DATAA, + A: u32be, // Ipv4 Address + AAAA: u128be, // Ipv6 Address + TXT: DNS_TXT_DATAA, + NS: DNS_PTR_DATAA, + MX: DNS_MX_DATAA, + SRV: DNS_SRV_DATAA, }, } DNS_TXT_DATAA :: struct { dwStringCount: DWORD, - pStringArray: cstring, + pStringArray: cstring, } DNS_PTR_DATAA :: cstring DNS_MX_DATAA :: struct { pNameExchange: cstring, // the hostname - wPreference: WORD, // lower values preferred - _: WORD, // padding. + wPreference: WORD, // lower values preferred + _: WORD, // padding. } DNS_SRV_DATAA :: struct { pNameTarget: cstring, - wPriority: u16, - wWeight: u16, - wPort: u16, - _: WORD, // padding + wPriority: u16, + wWeight: u16, + wPort: u16, + _: WORD, // padding } SOCKADDR :: struct { sa_family: ADDRESS_FAMILY, - sa_data: [14]CHAR, -} + sa_data: [14]CHAR, +} \ No newline at end of file