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++.
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
- SO Answer by Max Desiatov
- Trial'n'Error with the command line tool
nm
- Other links, that I cannot remember... :-(
In the second example, i found the last command to fail with the following warning:
However, the following did work:
swiftc -emit-library lib.swift -o bin/lib gcc -std=c++17 -c main.cpp -o bin/main.o gcc bin/main.o bin/lib -lstdc++ -o bin/linked ./bin/linked # The number is 2
Alternately, a
g++
approach also works.swiftc -emit-library lib.swift -o bin/lib g++ -std=c++17 -c main.cpp -o bin/main.o g++ bin/main.o bin/lib -o bin/linked ./bin/linked # The number is 2
As FYI, StackOverflow has some discussion of "What is the difference between g++ and gcc?", and "Which one should be used for general c++ development?".