![](/img/trans.png)
[英]Can I have Swift, Objective-C, C and C++ files in the same Xcode project?
[英]How can I send (and receive) extremely large floating arrays from Swift to Objective c++ to c++, and then back up to Swift?
我是一名Swift程序員,我的Objective-c ++和c ++經驗與我的Swift經驗絕不相稱。 我已經成功地從Swift-> Objc ++-> c ++(在其中進行處理)發送和接收浮點數的小數組,然后備份到Objc ++和Swift。 我們正在C ++中進行大量工作,由於以下幾個原因,我們暫時無法遷移到Swift(其中一個原因是c ++比Swift更有效)。
C ++程序完成的工作是在非常大的浮點數組上。 目前,這些浮點數組由c ++程序通過CSV文件發送和使用。 我們希望刪除這些CSV文件,以便消除在磁盤上讀寫的需要。 我們想直接處理浮點數數組。
以下代碼適用於小型數組。 但是,如果有300,000+的大型數組,則該程序僅會由於內存問題而在iOS設備上崩潰,然后在模擬器上,下面的Objective-c ++代碼占用高達59 GB的內存!
有人可以解釋一下,並告訴我一種更好的方法來發送和接收從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
值傳遞vector
? 您最好使用引用以避免復制。
無論如何,如果您確實在意內存效率,那么最好注意兩件事:
切勿使用NSArray
表示基本類型的數組
NSNumber
NSArray
消耗的內存是[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代碼幾乎不需要做什么。
Objective-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)
謝謝您的回答,它有效。
我也在這里找到了這個“有效”的代碼。 但是,您的代碼效率更高。 我認為我的代碼有問題的一件事是在循環的每次迭代中都復制了NSArray。
NSMutableArray *nsMutableArray = [[NSMutableArray alloc] initWithCapacity: 300000];
for (int i=0; i < 300000; i++) {
[nsMutableArray insertObject:[NSNumber numberWithFloat:cppArray[i]] atIndex:i];
}
NSArray *returnNsArray = [nsMutableArray copy];
return returnNsArray;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.