Skip to content

Instantly share code, notes, and snippets.

@elisbyberi
Forked from HiImJulien/Swift Meets CCxx.md
Created November 12, 2019 11:57
Show Gist options
  • Save elisbyberi/fca91b615034d6baecff3ad2bb2c8b23 to your computer and use it in GitHub Desktop.
Save elisbyberi/fca91b615034d6baecff3ad2bb2c8b23 to your computer and use it in GitHub Desktop.

Swift Meets C/C++

This gist is a simple example on how to call a function written in swift from C/C++, without taking the detour via Objective-C/C++.


Analytics

In this example we're going to invoke a function called say_hello, which, as the name already suggests, prints "Hello, World!" to the terminal.

say_hello is defined as following:

// func.swift

@_cdecl("say_hello")
public func say_hello(){
    print("Hello, World!")
}

This is just the canonical "Hello, World!"-example wrapped in a function called say\_hello. The only thing, that stands out, is the attribute @_cdecl("say\_hello").

@_cdecl is an undocumented attribute, which according to vague informations found on the web, enforces C-name mangling. Note: @_cdecl solely enforces the name mangling; not the calling convention!

In order to link our code with a C/C++ application, will need a library. In order to compile our code as a linked library, specify -emit-library when compiling the .swift-file.

We want to link our swift code with our C/C++ applications, which means, that we'll need this code to be compiled as a library. In order to compiler our code as a linked library, just specify '-emit-library' when compiling the .swift-file.

swiftc func.swift -emit-library

This will result in a linked library called "libfunc.dylib" (or "libfunc.so" on Linux, I suppose), which exports our function say_hello as _say_hello.


Now to our C++:

// main.cpp

// only "extern" when targeting C.
extern "C" void say_hello();

int main(){
    say_hello();    // Prints "Hello, World!"
    return 0;
}

Here we declare say_hello as an external reference, which will be provided by the library, we compiled before.

What's left at this point is just to compile and link our code.

gcc -std=c++11 -c main.cpp -o main.o 
gcc libfunc.dylib main.o -o main

When we run the application, we're getting greeted with following:

./main
> Hello, World!

This was my first "technical article". Feedback is welcome!

None the less, I hope I could help you with this "article".

J. Kirsch

Resources

  • SO Answer by Max Desiatov
  • Trial'n'Error with the command line tool nm
  • Other links, that I cannot remember... :-(
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment