Skip to content

Instantly share code, notes, and snippets.

@Khrob
Created May 6, 2021 12:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Khrob/ef7cfcf2b6f60e80993489d2ab4b1691 to your computer and use it in GitHub Desktop.
Save Khrob/ef7cfcf2b6f60e80993489d2ab4b1691 to your computer and use it in GitHub Desktop.
/**
This is the simplest way I've found to create a dynamic library in swift, then call a function from it in another swift program.
It doesn't use any package manager nonsense, just a compiled library and executable.
**/
///// Step 1: Create your dylib/dll
// libby.swift
// This is the code for the library you want to compile.
// Need to declare with @_cdecl so that this function gets an objective-c/c legible signature.
// That way dlsym() can find it when you load the
@_cdecl("external_func")
public func external_func ()
{
print ("a func, a very palpable func!")
}
///// Step 2: Compile it
/**
In the terminal, run:
swiftc -emit-library libby.swift -o libby.dylib
(tested with Swift v5.3.2)
**/
///// Step 3: Create an executable that calls it:
// main.swift
import Darwin
// Open the dynamic library
let handle = dlopen("./libby.dylib", RTLD_NOW)
if let s = dlerror() { print(String(cString: s)) }
if handle == nil { exit(0) }
// Get the function's symbol
let symbol = dlsym(handle, "external_func")
if let t = dlerror() { print(String(cString: t)); exit(0) }
if symbol == nil { exit(0) }
// Cast the unsafe pointer symbol to a swift callable func
typealias func_alias = @convention(c) ()->()
let function = unsafeBitCast(symbol, to:func_alias.self)
// Call it!
function()
// Clean up
dlclose(handle)
///// Step 4: Compile your executable
/**
In the terminal, run:
swiftc main.swift
**/
///// Step 5: Run your program
/**
In the terminal, run:
./main
Output:
a func, a very palpable func!
And you're done!
**/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment