Я программист на Swift, мой опыт в области Objective-C ++ и C ++ НИКОГДА не соответствует моему опыту в Swift. Мне удалось отправить и получить небольшие массивы чисел с плавающей запятой из Swift -> Objc ++ -> c ++ (где происходит обработка), а затем обратно в Objc ++ и Swift. У нас есть большой объем работы, выполняемой на C ++, которую мы на данный момент не можем перейти на Swift по нескольким причинам (одна из которых C ++ намного эффективнее выполняет эту работу, чем Swift).
Программа на C ++ выполняет работу с чрезвычайно большими массивами чисел с плавающей запятой. В настоящий момент эти массивы чисел с плавающей запятой отправляются и используются программой C ++ в виде файлов CSV. Мы хотим покончить с этими CSV-файлами, чтобы исключить необходимость чтения и записи на диск. Мы хотели бы иметь дело непосредственно с массивами чисел с плавающей запятой.
Следующий код хорошо работает с небольшими массивами. Но с очень большими массивами из 300000+ программа просто вылетает на устройстве iOS из-за проблем с памятью, а затем на симуляторе приведенный ниже код Objective-c ++ использует до 59 ГБ!
Может ли кто-нибудь объяснить и подсказать мне лучший подход к отправке и получению больших массивов чисел с плавающей запятой из Swift в Objc ++ в C ++, а затем обратно в Swift?
На данный момент я не буду использовать код .h и .hpp и покажу только коды Swift, .mm и .cpp.
SWIFT CODE:
let objcCppWrapper = ObjcCppWrapper()
let pointer: UnsafeMutablePointer<Float> = UnsafeMutablePointer(mutating: floatArray)
if let cppArraySameSize = objcCppWrapper.cppProcessSwiftArray(pointer, number_elements: Int32(floatArray.count)) {
let newArraySameSizePointer: UnsafeMutablePointer<Any> = UnsafeMutablePointer(mutating: cppArraySameSize)
let size = Int32(floatArray.count)
let floatsSameSizeAny : [Any] = Array(UnsafeBufferPointer(start: newArraySameSizePointer, count: Int(size)))
print("Swift: 'floatsSameSizeAny' size is \(floatsSameSizeAny.count)")
}
OBJECTIVE-C++ CODE:
-(NSArray *) cppProcessSwiftArray:(float [])array number_elements:(int )number_elements{
//Transform the float array into a vector array
std::vector<float> arrayVector(number_elements);
for(int j=0; j < number_elements; j++){
arrayVector[j] = array[j];
}
CppProcess cppProcess;
std::vector<float> cppArray = cppProcess.cppProcessSwiftArray(arrayVector);
//USES WAYYYYYY TOO MUCH MEMORY! UP TO 59 GB ON SIMULATOR, CRASHES TERMINATES IN IOS DEVICE DU TO MEMORY ISSUE.
NSArray *returnNsArray = [NSArray array];
for(int j=0; j < cppArray.size(); j++){
returnNsArray = [returnNsArray arrayByAddingObject:[NSNumber numberWithFloat:cppArray[j]]];
}
return returnNsArray;
}
C++ CODE:
vector<float> CppProcess::cppProcessSwiftArray(vector<float> arrayOfFloats) {
cout << "CPP: Received an array is of size " << arrayOfFloats.size() << '\n';
std::vector<float> returnedSameSizeArray(arrayOfFloats.size());
//For the moment, only create an arbitrary array of same size and return it...
for(int j=0; j < arrayOfFloats.size(); j++){
returnedSameSizeArray[j] = j ;
}
return returnedSameSizeArray;
}
Ваш код Swift - это демонстрация неправильного использования указателей и массивов Swift. Использование вами UnsafeMutablePointer.init(mutating:)
может привести к катастрофическим результатам, включая сбой или неожиданное изменение переменных.
Также в коде C ++, почему вы передаете vector
по значению? Лучше использовать ссылку, чтобы избежать копирования.
В любом случае, если вы думаете об эффективности памяти, лучше позаботьтесь о двух вещах:
Никогда не используйте NSArray
для представления массива примитивного типа
NSArray
из NSNumber
потребляет в десять раз или больше памяти , чем[Float]
Избегайте копирования, насколько это возможно
Как видите, копирование увеличивает потребление памяти вдвое.
Сначала перепишите свой код на C ++. Используйте указатели вместо vector
и избегайте ненужного копирования.
Код C ++:
void CppProcess::cppProcessSwiftArray(const float *arrayOfFloats, int count, float *outputArray) {
cout << "CPP: Received an array is of size " << count << '\n';
//For the moment, only create an arbitrary array of same size and return it...
for(int j=0; j < count; j++){
outputArray[j] = j ;
}
}
Указатели могут быть легко связаны с Swift, поэтому вашему коду Objective-C мало что нужно делать.
Код цели-C:
-(void)cppProcessSwiftArray:(const float * _Nonnull)array count:(NSInteger)count output:(float * _Nonnull)outputArray {
CppProcess cppProcess;
cppProcess.cppProcessSwiftArray(array, (int)count, outputArray);
}
Затем вы можете использовать функцию соединения массивов Swift и указателя.
Код Swift:
let floatArray: [Float] = ...
var resultArray: [Float] = Array(repeating: 0, count: floatArray.count)
let objcCppWrapper = ObjcCppWrapper()
objcCppWrapper.cppProcessSwiftArray(floatArray, count: floatArray.count, output: &resultArray)
Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.
En caso de infracción, por favor [email protected] Eliminar
Déjame decir algunas palabras