![](/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.