iOS Objective-C 应用程序可以使用嵌套静态 ObjC/Swift 库吗?
Can iOS Objective-C app use nested static ObjC/Swift libs?
仅限 OBJ-C...
也就是说,
ObjC 应用程序导入 ObjC 静态库 A。
静态库 A 导入静态库 B。
静态库 A 具有调用库 B 中的函数的函数。
应用程序只调用库A中的函数,不调用库B中的函数。
我可以假设库 A 或 B 可以是 Obj-C 或 Swift 吗?
IE。一个 ObjC 应用程序可以导入一个 ObjC-or-Swift 静态库 A 本身导入第二个 ObjC-or-Swift 静态库 B 吗? (是的,4 个用例排列)
只要库导出 Objective-C 兼容符号,它们是用 Objective-C、Swift、C++ 或任何其他编译的都没有关系语言。
而且我们知道 Swift 编译器为所有标有 @objc
(显式或隐式)的声明导出 Objective-C 兼容符号。
从消费者的角度来看,使用哪种语言生成库并不重要,只要 Objective-C compiler/linker 可以使用这些库导出的符号即可。
我为您创建的 git 存储库 https://github.com/CombineCppSwiftObjcInStaticLib 显示了这个..
您在 BLE_central.swift 中的初始 @objc func run_central()
被公开,这会触发预编译器生成 objc 兼容的 headers(桥),然后再次可以从导入此生成的 header 时 .mm
(objc++) 或 .m
(objc) 中的方法。
事实上 Hub_lib 在 repo 中是一个混合了 Swift 的静态 ObjC++ 库。反之亦然。 header 是这里成功的关键。 如果你可以提供一些 objc 或 c 或 c++ header 到 swift 功能它变得兼容和明智的相反。我的意思是,总的来说,这就是 header 的想法。如果你没有 headers,那并不意味着你不能调用一些外部的东西,这只是意味着你会称之为盲目的。一个合适的 IDE 会在你尝试做这些邪恶的事情之前抱怨,未知的入口点也就是未知的符号等等。所以你选择一个合适的 header - always.
要将 swift 与其他语言正确结合,很高兴知道总是有两种桥接方式。
在 Objective-C 的情况下(以及 Objective-C++)它是
- 桥接 Swift (
projectname-Bridging-Header.h
),
- 和 Swift 的桥接(用
@objc
公开触发自动内部生成 projectname-Swift.h
文件。所以这个 header 在文件浏览器中是“不可见的”在左侧。你也不会在 repo 中找到它作为文件,它由 modulename 命名,即 project-name)。最后提到的header你甚至可以自己手动写,有很多麻烦back-draws。
提示:可执行代码是可执行代码。不管是什么语言,只要它是为正确的设备架构编译的,并且有调用的符号,你就知道如何处理数据 returned.
另一个提示:有一种方法可以处理 swift see docu 中的 C 指针,它变成 swift 数据类型,您可以使用它来另辟蹊径并将函数声明为 return 那些来自 swift.
并且在Swift中直接使用C也是可以的。编译器考虑如果你显式标记一些代码为C。 extern "C" { /* code */ }
会导致C++编译器记住,这仍然是C++代码以这种方式编译函数,它可以从C调用 (和 Swift)
//Example.hpp //no target membership
#ifdef __cplusplus
#include <stdio.h>
class Example {
private:
const char * _name;
public:
Example(const char *name);
~Example(void);
int getLen(void);
};
#endif
应该有一个 Example.cpp 并且不要忘记告诉 Xcode 你处理 c++
#ifdef __cplusplus
+ #endif
//Example.cpp //has target membership
#include "Example.hpp"
#ifdef __cplusplus
#include <stdio.h>
#include <string>
//code implementation according to example.hpp
Example::Example(const char *name) {
_name = name;
}
int Example::getLen() {
return (int)strlen(_name);
}
#endif
//ExampleWrapper.cpp //has target membership
#include "Example.hpp" //c++ header file
extern "C" int myCppFunction(const char *s)
{
// Create an instance of Example, defined in the library
// and call getLen() on it, return result.
return Example(s).getLen();
}
所以这个函数需要在桥接中声明header才能使用它。
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
// for extern "C" functions declare them one by one here
// as implemented in ExampleWrapper.cpp
// becomes "func myCppFunction(_ s: UnsafePointer<Int8>!) -> Int32" in swift
int myCppFunction(const char * s);
然后从swift调用..
os_log("The result from C++ is %u", myCppFunction("12345"))
所以事实上,是的。在 App 中集成调用静态库 B 的静态库 A 是可能的。只要您为每个需要知道其他库头部内容的部分提供一些 header,编译就会很愉快。这对应用程序来说是正确的,因为它对彼此下的库和框架也是正确的。
编辑 这里有一些重要的东西要阅读 Swift Package Manager C 支持 https://github.com/apple/swift-evolution/blob/master/proposals/0038-swiftpm-c-language-targets.md
仅限 OBJ-C...
也就是说, ObjC 应用程序导入 ObjC 静态库 A。 静态库 A 导入静态库 B。 静态库 A 具有调用库 B 中的函数的函数。 应用程序只调用库A中的函数,不调用库B中的函数。
我可以假设库 A 或 B 可以是 Obj-C 或 Swift 吗? IE。一个 ObjC 应用程序可以导入一个 ObjC-or-Swift 静态库 A 本身导入第二个 ObjC-or-Swift 静态库 B 吗? (是的,4 个用例排列)
只要库导出 Objective-C 兼容符号,它们是用 Objective-C、Swift、C++ 或任何其他编译的都没有关系语言。
而且我们知道 Swift 编译器为所有标有 @objc
(显式或隐式)的声明导出 Objective-C 兼容符号。
从消费者的角度来看,使用哪种语言生成库并不重要,只要 Objective-C compiler/linker 可以使用这些库导出的符号即可。
我为您创建的 git 存储库 https://github.com/CombineCppSwiftObjcInStaticLib 显示了这个..
您在 BLE_central.swift 中的初始 @objc func run_central()
被公开,这会触发预编译器生成 objc 兼容的 headers(桥),然后再次可以从导入此生成的 header 时 .mm
(objc++) 或 .m
(objc) 中的方法。
事实上 Hub_lib 在 repo 中是一个混合了 Swift 的静态 ObjC++ 库。反之亦然。 header 是这里成功的关键。 如果你可以提供一些 objc 或 c 或 c++ header 到 swift 功能它变得兼容和明智的相反。我的意思是,总的来说,这就是 header 的想法。如果你没有 headers,那并不意味着你不能调用一些外部的东西,这只是意味着你会称之为盲目的。一个合适的 IDE 会在你尝试做这些邪恶的事情之前抱怨,未知的入口点也就是未知的符号等等。所以你选择一个合适的 header - always.
要将 swift 与其他语言正确结合,很高兴知道总是有两种桥接方式。
在 Objective-C 的情况下(以及 Objective-C++)它是
- 桥接 Swift (
projectname-Bridging-Header.h
), - 和 Swift 的桥接(用
@objc
公开触发自动内部生成projectname-Swift.h
文件。所以这个 header 在文件浏览器中是“不可见的”在左侧。你也不会在 repo 中找到它作为文件,它由 modulename 命名,即 project-name)。最后提到的header你甚至可以自己手动写,有很多麻烦back-draws。
提示:可执行代码是可执行代码。不管是什么语言,只要它是为正确的设备架构编译的,并且有调用的符号,你就知道如何处理数据 returned.
另一个提示:有一种方法可以处理 swift see docu 中的 C 指针,它变成 swift 数据类型,您可以使用它来另辟蹊径并将函数声明为 return 那些来自 swift.
并且在Swift中直接使用C也是可以的。编译器考虑如果你显式标记一些代码为C。 extern "C" { /* code */ }
会导致C++编译器记住,这仍然是C++代码以这种方式编译函数,它可以从C调用 (和 Swift)
//Example.hpp //no target membership
#ifdef __cplusplus
#include <stdio.h>
class Example {
private:
const char * _name;
public:
Example(const char *name);
~Example(void);
int getLen(void);
};
#endif
应该有一个 Example.cpp 并且不要忘记告诉 Xcode 你处理 c++ #ifdef __cplusplus
+ #endif
//Example.cpp //has target membership
#include "Example.hpp"
#ifdef __cplusplus
#include <stdio.h>
#include <string>
//code implementation according to example.hpp
Example::Example(const char *name) {
_name = name;
}
int Example::getLen() {
return (int)strlen(_name);
}
#endif
//ExampleWrapper.cpp //has target membership
#include "Example.hpp" //c++ header file
extern "C" int myCppFunction(const char *s)
{
// Create an instance of Example, defined in the library
// and call getLen() on it, return result.
return Example(s).getLen();
}
所以这个函数需要在桥接中声明header才能使用它。
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
// for extern "C" functions declare them one by one here
// as implemented in ExampleWrapper.cpp
// becomes "func myCppFunction(_ s: UnsafePointer<Int8>!) -> Int32" in swift
int myCppFunction(const char * s);
然后从swift调用..
os_log("The result from C++ is %u", myCppFunction("12345"))
所以事实上,是的。在 App 中集成调用静态库 B 的静态库 A 是可能的。只要您为每个需要知道其他库头部内容的部分提供一些 header,编译就会很愉快。这对应用程序来说是正确的,因为它对彼此下的库和框架也是正确的。
编辑 这里有一些重要的东西要阅读 Swift Package Manager C 支持 https://github.com/apple/swift-evolution/blob/master/proposals/0038-swiftpm-c-language-targets.md