Краткая версия:
как я могу преобразовать std::string
(объект, возвращаемый функцией .cpp, вызванной из файла .Swift с использованием моста) в Swift String
?
Длинная версия:
У меня есть библиотека, написанная на C++, и мне нужно вызвать некоторый код с помощью Swift. Я создал мост, добавив два файла в свои проекты Xcode:
связующий заголовок, который позволяет Swift вызывать функции C (на самом деле Swift не может напрямую вызывать функции C++, поэтому ему необходимо проходить через функции C)
//file bridgingHeader.h
const char * getLastOpenedFile();
и файлы .cpp, которые могут вызывать (конечно) функции C++ внутри и могут определять функции C с помощью extern "C"
//file wrapper.cpp
#include <string>
#include "my_library.hpp"
extern "C" const char * getStringFromLibrary()
{
const char * s = get_string_from_library().c_str();
return s;
}
Я могу получить доступ к возвращаемому значению из файла .swift, используя
let myString = String(cString: getStringFromLibrary())
Swift.print(myString)
Поставив точку останова для проверки значения s
внутри функции getStringFromLibrary()
я вижу содержимое строки, значит функция из библиотеки вызывается корректно.
В любом случае файл .swift печатает какие-то странные символы, а не исходную строку. Изменение getStringFromLibrary()
следующим образом
extern "C" const char * getStringFromLibrary()
{
return get_string_from_library().c_str();
}
Как следствие, код .swift печатает префикс реальной строки. Это заставляет меня задуматься о проблеме с памятью: вероятно, когда getStringFromLibrary()
выходит, объект std::string
, возвращенный get_string_from_library()
, уничтожается, и поэтому память, на которую указывает указатель, возвращенный с помощью .c_str()
, больше не является надежной, поэтому я получаю неверные результаты от Swift.print()
.
Как правильно получить доступ к std::string
из файла .swift, а затем освободить его память?
getStringFromLibrary
будет висеть на оборванном указателе, посколькуs
ссылается наconst char*
, который был выделен и уничтожен функциейget_string_from_library
. Я не знаком с быстрым, но вам, по сути, придется выделить этотconst char*
и передать право собственности вызывающему. - person Cory Kramer   schedule 13.04.2018char *
, копирования содержимого переменной в строку Swift и последующего явного вызоваfree()
- person Nisba   schedule 13.04.2018freeStringFromLibrary
вместо вызоваfree
непосредственно из Swift, чтобы скрыть основной метод выделения памяти. Это позволит вам использоватьnew[]
илиmalloc
внутри. - person Miles Budnek   schedule 13.04.2018