在Swift 2.2中阅读Darwin库时,我发现了以下代码。
@warn_unused_result
@_silgen_name("_swift_Darwin_sem_open2")
internal func _swift_Darwin_sem_open2(
name: UnsafePointer<CChar>,
_ oflag: CInt
) -> UnsafeMutablePointer<sem_t>
什么是&#39; @_ silgen_name&#39;在第二行?
我在here找到了以下信息,但我想了解更多详细信息,例如Apple Developer Library。
如果它只是您要从C调用的一组特定Swift函数,则可以使用@_silgen_name属性覆盖损坏的名称,和/或使它们@convention(c)使用C调用约定。< / p>
答案 0 :(得分:16)
@_silgen_name
最近刚刚从@asmname
(see the following commit)重命名,其中包含以下提交消息:
这反映了属性的仅适用于 编译器内部使用,并不等同于C的asm 属性,因为它不会更改调用约定 C兼容。
因此,作为一般的Swift开发人员,除非使用Swift移植到其他平台,否则不会遇到此属性。
现在,@_silgen_name
是具有特定选项的类SILGenNameAttr
的属性(宏),后者是Swifts abstract syntax tree (AST)的一部分。来自swift/AST/Attr.def
source code(另请参阅swift/lib/AST/Attr.cpp)
// Schema for DECL_ATTR:
//
// - Attribute name.
// - Class name without the 'Attr' suffix (ignored for
// - Options for the attribute, including:
// * the declarations the attribute can appear on
// * whether duplicates are allowed
// * whether the attribute is considered a decl modifier or not (no '@')
// - Unique attribute identifier used for serialization. This
// can never be changed.
//
// SIMPLE_DECL_ATTR is the same, but the class becomes
// SimpleDeclAttr<DAK_##NAME>.
//
DECL_ATTR(_silgen_name, SILGenName,
OnFunc | OnConstructor | OnDestructor | LongAttribute |
UserInaccessible, 0)
我们在swift/AST/Attr.h中找到了SILGeneNameAttr
的声明:
/// Defines the @_silgen_name attribute.
class SILGenNameAttr : public DeclAttribute {
public:
SILGenNameAttr(StringRef Name, SourceLoc AtLoc, SourceRange Range, bool Implicit)
: DeclAttribute(DAK_SILGenName, AtLoc, Range, Implicit),
Name(Name) {}
SILGenNameAttr(StringRef Name, bool Implicit)
: SILGenNameAttr(Name, SourceLoc(), SourceRange(), /*Implicit=*/true) {}
/// The symbol name.
const StringRef Name;
static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_SILGenName;
}
};
总结;它与为C函数提供Swift接口有关。您很可能很难在开发人员库中找到有关SILGenNameAttr
的任何详细信息,并且可以将其视为未记录的功能。
最后,您可能会对以下与Russ Bishop的谈话感兴趣:
工具箱:这里有龙(34:20)
我不会在任何生产应用程序中发送它 情况。但是如果你有冒险精神的话,他们就是这样。
@asmname
是装饰函数的属性。你绝对需要 了解ABI使用这个。斯威夫特不会帮助你 非常重要的参数。编译器不会 非常宽容,所以你必须确保你已经操纵了你的 将参数转换为与其兼容的格式。以下代码 显示如何声明它。给出函数属性@asmname
和 字符串符号;然后在返回类型中运行其参数。该 如果你的参数错误或返回,编译器不会抱怨 输入不正确。它只期望该符号存在,何时存在 跳转到它,最好采用这些参数并具有返回类型。@asmname("dispatch_get_current_queue") func _get_current_queue() -> dispatch_queue_t
Q&amp; A(37:08)
问:显然,Apple并未记录所有这些内容,那么您发现所有这些行为的过程是什么?
Russ :我会先看一下文档,但你说的很多东西都没有。如果你去斯威夫特 REPL并使用旗帜 - 我认为它就像
-deprecated-integrated-repl
- 您可以要求它打印Swift模块以及Xcode没有显示的所有位。如果你深入了解 工具链目录Xcode,你也可以在libswiftCore和 libswiftRuntime。JP :如果您对使用Swift做一些不安全的事情感兴趣,可以在GitHub中为
@asmname
和语言进行代码搜索 “斯威夫特”,你会看到一堆非常糟糕但有趣的东西。
来自Bishops博客的稍微过时的帖子:
...
首先注意
@asmname
属性。这相当于DllImport
或extern
。它告诉Swift我们将要链接 一些库,用于定义具有给定名称和匹配的函数 给定的论点。 “只要相信我斯威夫特,我知道我在做什么”。 提示:你最好知道自己在做什么。
答案 1 :(得分:1)
简而言之,
@_silgen_name
定义共享库上显示的函数名称。
Glibc.swift告诉_swift_Glibc_open已定义。
你可以通过nm /usr/lib/swift/linux/libswiftGlibc.so
这样看到这一点。
00000000000016f0 t _swift_Glibc_fcntl
0000000000001700 t _swift_Glibc_fcntlPtr
00000000000016b0 t _swift_Glibc_open
00000000000016c0 t _swift_Glibc_openat
00000000000016d0 t _swift_Glibc_sem_open2
00000000000016e0 t _swift_Glibc_sem_open4