Я вижу некоторые поведение, я не понимаю, при прохождении строк между Swift и C. Рассмотрим следующую функцию: SwiftПередача строки из Swift в C обратно Swift
func demo()
{
print("\n\n\n\n") // Line A
let str = "thisisastring"
let strptr = UnsafePointer<Int8>(str)
let strptr_cstring = String(cString: strptr)
print("from swift: str = '\(str)'")
print("from swift: strptr = \(strptr)")
print("from swift: strptr.pointee = \(strptr.pointee)")
print("from swift: strptr_cstring = '\(strptr_cstring)'")
print("from swift: String(cString: strptr) = '\(String(cString: strptr))'")
let ret_strptr = return_string(str)! // Line B1
//let ret_strptr = return_string(strptr)! // Line B2
//let ret_strptr = strptr // Line B3
print("from swift: ret_strptr = \(ret_strptr) ")
print("from swift: ret_strptr.pointee = \(ret_strptr.pointee)")
let ret_strptr_cstring = String(cString: ret_strptr)
print("from swift: ret_strptr_cstring = '\(ret_strptr_cstring)'")
print("from swift: String(cString: ret_strptr) = '\(String(cString: ret_strptr))'")
}
И функцию C:
const char *return_string(const char *c)
{
printf("from c: got pointer %p = %s\n",c,c);
return c;
}
Если я запустить demo
, как это выше (так только линии B2 и B3 закомментировано), я получаю следующий результат:
from swift: str = 'thisisastring'
from swift: strptr = 0x000000010021b8a0
from swift: strptr.pointee = 116
from swift: strptr_cstring = 'thisisastring'
from swift: String(cString: strptr) = 'thisisastring'
from c: got pointer 0x10021b9b0 = thisisastring
from swift: ret_strptr = 0x000000010021b9b0
from swift: ret_strptr.pointee = 102
from swift: ret_strptr_cstring = '102m swift: ret_'
from swift: String(cString: ret_strptr) = 'P�!'
Две вещи удивляют меня об этом: 1) код C получает указатель 0x10021b9b0, тогда как в Swift строка хранится в 0x000000010021b8a0. Я бы ожидал, что они будут такими же, но я думаю, что Свифт делает копию строки, прежде чем передать ее на C? 2) гораздо более удивительно, хотя, хотя указатель, возвращаемый с C в Swift, является одним и тем же местом, содержимое отличается; Кроме того, последние два оператора печати выдают разные результаты.
Теперь, если я просто закомментируйте линию А в demo
, я получаю следующие результаты:
from swift: str = 'thisisastring'
from swift: strptr = 0x00000001003894b0
from swift: strptr.pointee = 0
from swift: strptr_cstring = 'S\212'
from swift: String(cString: strptr) = ''
from c: got pointer 0x100469640 = thisisastring
from swift: ret_strptr = 0x0000000100469640
from swift: ret_strptr.pointee = 48
from swift: ret_strptr_cstring = '48000010046964'
from swift: String(cString: ret_strptr) = '48000010046964'
Что удивительно, потому что все вещи перед вызовом функции C неверны.
Если я закомментируйте строки B1 и раскомментируйте B3 (только удаление вызова C), я получаю ожидаемый результат:
from swift: str = 'thisisastring'
from swift: strptr = 0x00000001004809b0
from swift: strptr.pointee = 116
from swift: strptr_cstring = 'thisisastring'
from swift: String(cString: strptr) = 'thisisastring'
from swift: ret_strptr = 0x00000001004809b0
from swift: ret_strptr.pointee = 116
from swift: ret_strptr_cstring = 'thisisastring'
from swift: String(cString: ret_strptr) = 'thisisastring'
Если я запускаю его с линией В2 незакомментированной (закомментировать A, B1 и B3), я получаю:
from swift: str = 'thisisastring'
from swift: strptr = 0x0000000100203550
from swift: strptr.pointee = 0
from swift: strptr_cstring = '2'
from swift: String(cString: strptr) = ''
from c: got pointer 0x100203550 =
from swift: ret_strptr = 0x0000000100203550
from swift: ret_strptr.pointee = 0
from swift: ret_strptr_cstring = ''
from swift: String(cString: ret_strptr) = ''
Наконец, если я бегу с линиями а и В2 незакомментированной (B1 и B3 закомментирована), я получаю ожидаемых результатов:
from swift: str = 'thisisastring'
from swift: strptr = 0x00000001005533d0
from swift: strptr.pointee = 116
from swift: strptr_cstring = 'thisisastring'
from swift: String(cString: strptr) = 'thisisastring'
from c: got pointer 0x1005533d0 = thisisastring
from swift: ret_strptr = 0x00000001005533d0
from swift: ret_strptr.pointee = 116
from swift: ret_strptr_cstring = 'thisisastring'
from swift: String(cString: ret_strptr) = 'thisisastring'
Мне кажется, что вызов к C топает по памяти непредсказуемым образом, но я делаю что-то неправильное здесь?
Выполняется на macOS Sierra, Xcode 8.0, Swift 3.0.