在Swift语言中,'@_silgen_name'是什么?

15

在阅读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>

第二行的'@_silgen_name'是什么意思?

我从这里找到了以下信息,但我想要更详细的信息,就像在Apple Developer Library中一样。

如果您只想从C语言中调用一组特定的Swift函数,则可以使用'@_silgen_name'属性来覆盖名称重载,并/或使它们成为@convention(c)以使用C调用约定。

2个回答

19

@_silgen_name 最近从 @asmname (请参见以下提交) 更名,附带的提交信息如下:

这反映了该属性仅供编译器内部使用,并不真正等同于C的asm属性,因为它不会改变调用约定以使其与C兼容。

因此,作为一名普通的Swift开发人员,除非与其他平台进行移植工作,否则不会遇到这种属性。

现在,@_silgen_nameSILGenNameAttr 类的一个带有特定选项的属性(宏),后者是 Swift 的 抽象语法树 (AST) 的一部分。可以从 swift/AST/Attr.def 源代码(也可以参考 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接口有关。您很可能会发现在开发者库中找不到有关的详细信息,可以将其视为未记录的功能。

最后,以下与Russ Bishop的交谈可能会对您有所帮助:

The Toolbox: Here there be dragons (34:20)

I would not ship this in a production application under any circumstances. But if you’re feeling adventurous, here they are.

@asmname is an attribute to decorate a function. You definitely need to understand the ABI to use this one. Swift will not help you marshall the parameters very much. The compiler is not going to be very forgiving, so you have to make sure that you’ve manipulated your parameters into a format it’s compatible with. The following code shows how to declare it. Give the function attribute, @asmname, and the string symbol; then function its arguments in return type. The compiler will not complain if you get the arguments wrong or return type incorrectly. It only expects that that symbol exists, and when it jumps to it, it better take those arguments and have that return type.

@asmname("dispatch_get_current_queue") func _get_current_queue() -> dispatch_queue_t

Q&A (37:08)

Q: Obviously not all of these are documented by Apple, so what’s your process of discovering all these behaviors?

Russ: I’ll look at the documentation first, but you’re right that there is a lot of stuff that isn’t in there. If you go to the Swift REPL and use the flag — I think it’s something like -deprecated-integrated-repl — you can ask it to print the Swift module and all the bits that Xcode doesn’t show you. If you dig into the toolchain directory Xcode, you can also find stuff in libswiftCore and libswiftRuntime.

JP: If you’re interested in doing some more unsafe things with Swift, you can do a code search in GitHub for @asmname and language “Swift”, and you’ll see a bunch of really bad but interesting stuff.

Bishops的博客中有一篇稍早的帖子:

...

首先请注意 @asmname 属性。这相当于 DllImportextern。它告诉 Swift 我们将链接某个库,该库定义了一个具有给定名称和匹配给定参数的函数。"请相信我,Swift,我知道我在做什么"。提示:你最好知道你在做什么。


很棒的答案!苹果会拒绝使用这个属性的iOS应用程序吗? - zaitsman

2
简单来说,@_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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接