在Apple Swift中传递C风格的未初始化指针?

时间:2014-06-06 20:29:51

标签: swift

我正试图在Apple Swift中实现一些AES256加密例程,以便在ObjC,C和Swift代码与数据类型之间实现互操作性,并且遇到了一些问题我希望有人提出一些建议在我忽略的事情上。

大多数人都很熟悉,常见的C风格模式是声明一个未初始化的指针然后将其传递给一个函数,其中函数调用malloc()是一个对象并指向它的指针;函数调用完成后,指针指向新创建的对象。 Common Crypto库在某些地方使用它;最值得注意的是,在创建一个新的CCCryptor对象时(实际上是一个幕后的结构,看起来像是对CCCryptorRef的typedef&ed为一个不透明的引用) - 调用CCCryptorCreate()的最后一个参数就是这样一个指针,应该,在函数调用结束时,包含一个指向CCCryptorRef的指针。

斯威夫特给这个带来了皱纹 - 变量不能是未初始化的,它们总是有一个值或者是零(/可选),因此我在这里碰到了一点点。以下不起作用,因为CCCryptorCreate(正确地)就好像我只是传递nil作为最后一个参数,我是:

var myCryptorRef: CMutablePointer<Unmanaged<CCCryptorRef>?> = nil
CCCryptorCreate(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES128),
  CCOptions(kCCOptionECBMode), seedData.bytes(), UInt(kCCKeySizeAES256), 
  nil, myCryptorRef)

但你也不能将它声明为可选项,如下所示:

var myCryptorRef: CMutablePointer<Unmanaged<CCCryptorRef>?>?

或者作为非指针类型:

var myCryptoRef: Unmanaged<CCCryptorRef>?
CCCryptorCreate(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES128),
  CCOptions(kCCOptionECBMode), seedData.bytes(), UInt(kCCKeySizeAES256), 
  nil, &myCryptorRef)

因为CCCryptorCreate所期望的是指向CCCryptorRef的未初始化指针或者已经是malloc()的CCCryptorRef,试图传递它尚未初始化的对象的地址并不是非常正如你所期望的那样。

所以,它归结为:在调用CCCryptorCreate之前,任何人都可以想出一种初始化CCCryptor结构的方法(通过命名struct中的所有变量似乎不起作用的结构init的Swift标准方法) ,或一些替代结构,允许我保留未初始化指针的C概念,以这种方式使用?感谢您提出的任何建议。

为了清楚起见,注释:Swift将对CCCryptorCreate()的调用解释如下:

CCCryptorCreate(op: CCOperation, alg: CCAlgorithm, options: CCOptions, 
  key: CConstVoidPointer, keyLength: UInt, iv: CConstVoidPointer, 
  cryptorRef: CMutablePointer<Unmanaged<CCCryptor>?>)

对我尝试过的其他一些事情进行了额外的编辑:为了真正荒谬,我尝试了以下内容,但它也无效(EXC_BAD_ACCESS调用fromOpaque):

var someMem = malloc(UInt(sizeof(CCCryptor)))
var crashTime = Unmanaged<CCCryptor>.fromOpaque(someMem)

此外,每个地方都提到了CCCryptor或CCCryptorRef,我尝试了其中任何一个 - 在CommonCrypto / CommonCryptor.h中,CCCryptorRef是这样定义的:

typedef struct _CCCryptor *CCCryptorRef

因此,虽然现有的Objective-C代码示例使用CCCryptorRef,但我一直在尝试。

2 个答案:

答案 0 :(得分:3)

试试这个:

var myCryptor: Unmanaged<CCCryptor>?

CCCryptorCreate( .... , &myCryptor )

来自Using Swift with Cocoa and Objective-C

  

如果你声明了这样一个函数:

func takesAMutablePointer(x: CMutablePointer<Float>) { /*...*/ }
     

您可以通过以下任何方式调用它:

var x: Float = 0.0 
var p: CMutablePointer<Float> = nil 
var a: Float[] = [1.0, 2.0, 3.0] 
takesAMutablePointer(nil) 
takesAMutablePointer(p) 
takesAMutablePointer(&x) 
takesAMutablePointer(&a)

您还应该查看this并将Unmanaged引用转换为管理的内容。

答案 1 :(得分:0)

这是一个适用于测试版3的示例,使用librabbitmq中的类型:

let envelopePtr = UnsafePointer<amqp_envelope_t>.alloc(1)
reply = amqp_consume_message(connection, envelopePtr, nil, 0)
let envelope = envelopePtr.memory