Skip to content

Instantly share code, notes, and snippets.

@neonichu
Created October 7, 2014 21:50
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save neonichu/dcf49b26a2742404d8f1 to your computer and use it in GitHub Desktop.
Save neonichu/dcf49b26a2742404d8f1 to your computer and use it in GitHub Desktop.
Using dlopen / dlsym to call C functions from Swift
import Darwin
let handle = dlopen("/usr/lib/libc.dylib", RTLD_NOW)
let sym = dlsym(handle, "random")
let functionPointer = UnsafeMutablePointer<() -> CLong>(sym)
let result = functionPointer.memory()
println(result)
@neonichu
Copy link
Author

neonichu commented Oct 7, 2014

xcrun swift DynamicFunctions.swift

0  swift                    0x0000000103be3eb8 llvm::sys::PrintStackTrace(__sFILE*) + 40
1  swift                    0x0000000103be43a4 SignalHandler(int) + 452
2  libsystem_platform.dylib 0x00007fff8bfdaf1a _sigtramp + 26
3  libsystem_platform.dylib 0x00007fd443f71128 _sigtramp + 3086574120
4  libsystem_platform.dylib 0x00000001067f0b89 _sigtramp + 2055298185
5  swift                    0x0000000103259019 llvm::JIT::runFunction(llvm::Function*, std::__1::vector<llvm::GenericValue, std::__1::allocator<llvm::GenericValue> > const&) + 329
6  swift                    0x0000000103505403 llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, char const* const*) + 1523
7  swift                    0x00000001031423ba swift::RunImmediately(swift::CompilerInstance&, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&, swift::IRGenOptions&, swift::SILOptions const&) + 1066
8  swift                    0x0000000102f38183 frontend_main(llvm::ArrayRef<char const*>, char const*, void*) + 5107
9  swift                    0x0000000102f3564d main + 1677
10 libdyld.dylib            0x00007fff80beb5c9 start + 1
Stack dump:
0.  Program arguments: /Applications/Xcode-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret FunctionPointer.swift -target x86_64-apple-darwin14.0.0 -target-cpu core2 -sdk /Applications/Xcode-Beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk -module-name FunctionPointer 

😭

@neonichu
Copy link
Author

neonichu commented Oct 8, 2014

This is the actual crash when running the compiled program:

* thread #1: tid = 0x643d, 0x000000010019cde9 libswiftCore.dylib`_swift_retain_(swift::HeapObject*) + 9, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    frame #0: 0x000000010019cde9 libswiftCore.dylib`_swift_retain_(swift::HeapObject*) + 9
libswiftCore.dylib`_swift_retain_(swift::HeapObject*) + 9:
-> 0x10019cde9:  lock   
   0x10019cdea:  addl   $0x4, 0x8(%rdi)
   0x10019cdee:  movq   %rdi, %rax
   0x10019cdf1:  popq   %rbp
(lldb) bt
* thread #1: tid = 0x643d, 0x000000010019cde9 libswiftCore.dylib`_swift_retain_(swift::HeapObject*) + 9, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
  * frame #0: 0x000000010019cde9 libswiftCore.dylib`_swift_retain_(swift::HeapObject*) + 9
    frame #1: 0x000000010000199b FunctionPointer`top_level_code + 2459
    frame #2: 0x0000000100001a5a FunctionPointer`main + 42
    frame #3: 0x00007fff8af265c9 libdyld.dylib`start + 1

@kjunichi
Copy link

Hello! Thanks your code.I made it work.

import Darwin

let handle = dlopen("/usr/lib/libc.dylib", RTLD_NOW)
let sym = dlsym(handle, "random")

typealias randomFunc = @convention(c) () -> CInt
let f = unsafeBitCast(sym, randomFunc.self)
let result = f()
dlclose(handle)
print(result)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment