2015-11-20 2 views
1

Я кодирую Int64 (на графической карте) с unsafeAddressOf некоторых экземпляров (которые правильно хранятся и сохраняются некоторым массивом).Получение экземпляра из «unsafeAddressOf»

Я хотел бы вернуться к моим экземплярам с моего Int64. Мне удалось получить UnsafePointer<MyClass>, правильно инициализированный с моего Int64.

Тогда я:

let x = UnsafePointer<MyClass>.memory. 

Но использование x аварий.

Я понимаю, что это небезопасно и сложно, учитывая ARC. Но все-таки, есть ли способ достичь этого в Свифт, или он беспомощен?

Спасибо.

+0

«Мне удалось получить UnsafePointer , правильно инициализированный из моего Int64». показать нам эту часть кода, пожалуйста, – user3441734

ответ

0

То, что вы пытаетесь сделать, это крайне небезопасно, так как вы сами сказали, и есть, вероятно, более безопасные подходы к решению любой проблемы вы работаете, но вот полный пример, который делает это:

func getPointer<T:AnyObject>(obj : T) -> Int64 
{ 
    return unsafeBitCast(unsafeAddressOf(obj), Int64.self) 
} 

func recoverObject<T:AnyObject>(ptr : Int64) -> T 
{ 
    return Unmanaged<T>.fromOpaque(COpaquePointer(bitPattern: Int(ptr))).takeUnretainedValue() 
} 

class C { 
    var cID = 0 
    func foo() { 
     print("Instance of C, id = \(cID)") 
    } 
} 

class D { 
    var dID = 0 
    func foo() { 
     print("Instance of D, id = \(dID)") 
    } 
} 


let c : C = C() 
let d : D = D() 

c.cID = 123; 
d.dID = 321; 

let cPtr : Int64 = getPointer(c) 
let dPtr : Int64 = getPointer(d) 

c.cID *= 10 

let c1 : C = recoverObject(cPtr) 
let d1 : D = recoverObject(dPtr) 

c1.foo() 
d1.foo() 

выход:

Instance of C, id = 1230 
Instance of D, id = 321 

Благодаря user3441734 для некоторых полезных советов! Обратите внимание на использование дженериков. Функции для получения «указателя» и де-ссылки на него должны работать с любым классом (однако не будут работать с структурами).

Что касается более безопасных способов сделать это, ответ будет зависеть от контекста того, что вы делаете. Почему невозможно получить доступ к массиву экземпляров везде, где вам нужны экземпляры, а не получать их через Int64? Если массив фактически поддерживается кодом (Objective-) C в сторонней библиотеке, тогда есть дополнительные проблемы, которые могут возникнуть из-за выравнивания памяти и т. Д. Возможно, будет возможно написать код C, который возвращает экземпляры в код Swift в более безопасным способом.

Пожалуйста, дайте мне знать о более подробной информации, если ответ по какой-то причине не работает.

0
class C { 
    func foo() { 
     print("C") 
    } 
} 
var c = C() 

let addr = unsafeAddressOf(c) 
dump(addr) 
/* 
▿ UnsafePointer(0x7F86E942B230) 
    - pointerValue: 140217415807536 
*/ 

let pC = withUnsafePointer(&c) { (p) -> UnsafePointer<C> in 
    return p 
} 

dump(pC) 
/* 
▿ UnsafePointer(0x10DE5B390) 
    - pointerValue: 4528124816 
*/ 

dump(pC.memory) 
/* 
- C#0 
*/ 
let opaquePointer = COpaquePointer(addr) 
let unmanagedC = Unmanaged<C>.fromOpaque(opaquePointer) 
dump(unmanagedC) 
/* 
▿ Swift.Unmanaged<C> 
- _value: C#0 
*/ 

// I still dont have an idea how to use it ... 

ha, я понял!

unmanagedC.takeUnretainedValue().foo() // prints C ! 
+0

Это работает! Вы можете увидеть некоторые дополнительные подробности в этом ответе на форуме apple dev: [link] (https://forums.developer.apple.com/thread/26655) –

Смежные вопросы