OBJ-C ONLY…
That is,
An ObjC app imports ObjC static lib A.
Static lib A imports static lib B.
Static lib A has functions that call functions within lib B.
The app only calls functions in lib A and does not call functions in lib B.
Can I assume that lib A or B can be either Obj-C or Swift?
IE. Can an ObjC app import an ObjC-or-Swift static lib A that itself imports a second ObjC-or-Swift static lib B? (yes, 4 use case permutations)
2
Answers
As long as the libraries export Objective-C compatible symbols, it doesn’t matter if they’re written in Objective-C, or Swift, or C++, or any other compiled language.
And we know that the Swift compiler exports Objective-C compatible symbols for all declarations that are marked with
@objc
(either explicitly or implicitly).From a consumer perspective it doesn’t matter which language generated the libraries, as long as the Objective-C compiler/linker can consume the symbols exported by those libraries.
the git repository https://github.com/CombineCppSwiftObjcInStaticLib i created for you is showing this..
your initial
@objc func run_central()
in BLE_central.swift is exposed, which triggers the precompiler to generate objc compatible headers (bridge) which then again makes it possible to call the function from a method inside.mm
(objc++) or.m
(objc) when this generated header is imported.In fact Hub_lib inside the repo is a static ObjC++ lib mixed with Swift. It would work the other way around also. The headers are the key for success here. If you can provide some objc or c or c++ header to swift functions it becomes compatible and wise versa. I mean in general, thats the idea of headers. If you don’t have headers, that does not mean you can not call some external stuff, it just means you would call it blind. A proper IDE will complain before you even try to do this evil stuff, unknown entry points aka unknown symbols etc.. So you go for a proper header – always.
To properly combine swift with other languages its good to know there are always two ways of bridging.
In case of Objective-C (and also Objective-C++) it is
projectname-Bridging-Header.h
),@objc
to trigger automatically internal generation ofprojectname-Swift.h
file. So this header is "invisible" in the file browser on the left side. Nor will you find it in the repo as file, it is named by modulename which is the project-name). The last mentioned header you could even write manually yourself, with lots of troublesome back-draws.Hint: Executable code is executable code. No matter what language, as far it is compiled for the right device architecture and has symbols to call and you know what to do with the data returned.
Another Hint: there is a way to handle C pointers in swift see docu which become swift datatypes which you can use to go the other way and declare functions to return those from swift.
And direct use of C in Swift is also possible. The compiler considers if you explicit mark some code as C.
extern "C" { /* code */ }
will cause the C++ compiler to remember, this is still C++ code to compile the function in such a way, it can be called from C (and Swift)There should be an Example.cpp and don’t forget to tell Xcode you deal with c++
#ifdef __cplusplus
+#endif
So this function needs to be declared in the bridging header to make use of it.
and then call from swift..
So in fact, yes. Integrating a static lib A that calls static lib B in App is possible. Happy compiling as long you offer some header for each part that needs to know what is inside the head of the other lib. That is true for Apps as it is true for libs and frameworks under each other.
Edit here some important stuff to read about Swift Package Manager C support https://github.com/apple/swift-evolution/blob/master/proposals/0038-swiftpm-c-language-targets.md