Dynamically loading a Swift `shared object` / `dylib`

Hello,

I have a Swift code, that loads a Swift .dylib (or .so) at runtime and uses a function of of a known name type as an interface. The loading process then uses dlopen and dlsym to execute the function. (I do not )

The source code of .dylib

@_cdecl("mySymbol")
public func mySymbol() -> Any {
    return "Hello world!"
}

The source code of the application

typealias FunctionPrototype = @convention(c) () -> Any

let handle = dlopen(libraryPath, RTLD_NOW)!
let symbol = dlsym(handle, "mySymbol")
let callable = unsafeBitCast(symbol, to: FunctionPrototype.self)
print(callable() as! String)

Everything works fine and I have never had an issue.

However, I was wondering, whether there might be an issue with calling conventions, since I'm using the @convention(c) annotation. I've used it "to make the FunctionPrototype type 1 pointer wide", but are there any other effects caused by the annotation, that I'm not taking into consideration? Is there any standard type, that might just break the program?

Marking the function as @_cdecl forces it to use the c calling convention, so what you're doing looks fine to me.

Types that aren't compatible with the c calling convention should be diagnosed by the compiler on both/either the actual function definition because it's marked @_cdecl or the function type.

1 Like