如何从Swift不安全指针中获取原始整数位模式?

fcipmucu  于 2023-04-10  发布在  Swift
关注(0)|答案(2)|浏览(105)

你可以从一个整数构造一个UnsafePointer,比如:

let ptr = UnsafePointer<Void>(bitPattern: 123)

但是如何从指针中获取整数位模式(在本例中为123)呢?

你为什么要这么做

(添加以回应一些评论,这些评论建议我没有正确使用指针。
这不是你通常做的事情,上面的指针并不是一个指向任何东西的指针。如果程序取消引用它,它会崩溃。
一些低级的C API使用void *来引用一些任意的数据。这是C的泛型类型版本。例如,想象一下C中的堆栈数据结构,具有如下API

Stack *create_stack();
void stack_push(Stack *stack, void *element);
void *stack_pop(Stack *stack);

通常你会传递指针到堆分配的数据,但是假设你只想要一个64位整数的堆栈,你知道你的系统上的指针是64位的。你可以直接在堆栈中存储整数,避免堆分配。

Stack *myStack = create_stack();
long elt = 123;
stack_push(myStack, (void*)elt);
...
elt = (long)stack_pop(myStack);

我正在处理这样的API,但更复杂(用于多边形镶嵌)。

oiopk7p5

oiopk7p51#

虽然unsafeBitCast可以工作,但更自然的Swift解决方案是

let ptr = UnsafePointer<Void>(bitPattern: 123)
let x = Int(bitPattern: ptr)

(Note Int与32位和64位平台上的指针大小相同。)
IntUInt都有几种指针类型的bitPattern:初始化器:

  • UnsafePointer<_>?
  • UnsafeRawPointer?
  • UnsafeMutablePointer<_>?
  • UnsafeMutableRawPointer?
  • OpaquePointer?
  • ObjectIdentifier

除了ObjectIdentifier之外,所有这些指针类型都有自己的bitPattern:初始化器,用于IntUInt
一个可能需要这种转换的例子是dlsym函数,它具有以下C声明:

extern void * dlsym(void * __handle, const char * __symbol);

Swift是这样导入的:

public func dlsym(
  _ __handle: UnsafeMutableRawPointer!,
  _ __symbol: UnsafePointer<CChar>!
) -> UnsafeMutableRawPointer!

对于handle参数,可以传递dlopen返回的句柄,也可以传递几个魔术常数中的一个。魔术常数在C中的定义如下:

#define RTLD_NEXT   ((void *) -1)   /* Search subsequent objects. */
#define RTLD_DEFAULT    ((void *) -2)   /* Use default search algorithm. */
#define RTLD_SELF   ((void *) -3)   /* Search this and subsequent objects (Mac OS X 10.5 and later) */
#define RTLD_MAIN_ONLY  ((void *) -5)   /* Search main executable only (Mac OS X 10.5 and later) */

但是Swift不会导入这些常量,如果你想在Swift中使用其中一个,可以使用UnsafeMutableRawPointer(bitPattern:)来创建必要的常量:

fileprivate let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
let mySym = dlsym(RTLD_DEFAULT, "mySym")
a8jjtwal

a8jjtwal2#

我在另一个论坛上找到了答案。使用unsafeBitCast

let ptr = UnsafePointer<Void>(bitPattern: 123)
let x: Int64 = unsafeBitCast(ptr, Int64.self)
// x == 123

相关问题