Ok, Fixed by doing the following steps
- Create a systemLibrary module, Should look like this
Sources/
Cwindows_bind/
module.modulemap
win_bridge.h
In module.modulemap:
module windows [extern_c][system] {
umbrella header "win_bridge.h"
export *
}
win_bridge.h
#include <windows.h>
// We're defining this only because for some reason, LoadLibrary doesn't get imported into swift automaticly but GetProcAddress, And FreeLibrary does when using this header, I'm guessing do to macro related stuff.
extern HINSTANCE load_library(const char *path) {
return LoadLibrary(path);
}
- Add to Package.swift, Should look something like this
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "swift_tolk",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "swift_tolk",
targets: ["swift_tolk"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
.systemLibrary (
name: "Cwindows_bind"),
.target(
name: "swift_tolk",
dependencies: ["Cwindows_bind"]),
]
)
3. Finally, Use in the code, After modification and extra google searching since swift doesn't automaticly convert the String I pass to load_library to const char*, So I needed to find the way to do it, And here:
In Sources/swift_tolk/swift_tolk.swift:
import windows
typealias FuncLibLoad = @convention(c) () -> Void
typealias FuncLibSpeak = @convention(c) (CWideChar, CBool) -> CBool
public func lib_load() {
if let handle = "Tolk.dll".withCString ({ (cstr) -> HINSTANCE? in
load_library(cstr)
}) {
if let sym = GetProcAddress(handle, "Tolk_Load") {
let res = unsafeBitCast(sym, to: FuncLibLoad.self)
res()
}
if let sym = GetProcAddress(handle, "Tolk_Speak") {
let res = unsafeBitCast(sym, to: FuncLibSpeak.self)
res(Unicode.Scalar("Hello, World.")!, true)
}
FreeLibrary(handle)
}
}
This compiles, But throws some LLD warnings I honestly don't understand and the functions doesn't scene to work, Here's the compilation output, And nevermind the warning about unused bool, It's just a test to get if the thing is working
[1/2] Compiling swift_tolk swift_tolk.swift
C:\Users\mohamed\projects\ls\swift_tolk\Sources\swift_tolk\swift_tolk.swift:15:13: warning: result of call to function returning 'CBool' (aka 'Bool') is unused
res(Unicode.Scalar("Hello, World.")!, true)
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[2/3] Compiling ls main.swift
lld-link: warning: C:\Users\mohamed\projects\ls.build\x86_64-unknown-windows-msvc\release\ls.build\main.swift.o: locally defined symbol imported: $s10swift_tolk8lib_loadyyF (defined in C:\Users\mohamed\projects\ls.build\x86_64-unknown-windows-msvc\release\swift_tolk.build\swift_tolk.swift.o) [LNK4217]
lld-link: warning: section name .debug_abbrev is longer than 8 characters and will use a non-standard string table
lld-link: warning: section name .debug_info is longer than 8 characters and will use a non-standard string table
lld-link: warning: section name .debug_line is longer than 8 characters and will use a non-standard string table
lld-link: warning: section name .debug_loc is longer than 8 characters and will use a non-standard string table
lld-link: warning: section name .debug_names is longer than 8 characters and will use a non-standard string table
lld-link: warning: section name .debug_ranges is longer than 8 characters and will use a non-standard string table
lld-link: warning: section name .debug_str is longer than 8 characters and will use a non-standard string table
[3/3] Linking C:\Users\mohamed\projects\ls.build\x86_64-unknown-windows-msvc\release\ls.exe
[3/3] Build complete!
I guess I'm doing something obviously wrong, But not sure what that is.