2016-10-18 11 views
0

Я вижу некоторые поведение, я не понимаю, при прохождении строк между 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.

ответ

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

  • Нет связанных вопросов^_^