我已经使用codegen工具从MATLAB生成了C代码。该功能可以描述如下:
function [result] = calculate_data(my_matrix)
for idx = 1:length(my_matrix)
result = result + sum(my_matrix(idx,1:3));
end
end
Run Code Online (Sandbox Code Playgroud)
使用codegen工具时,我明确声明my_matrix是double(:inf,3)的类型。换句话说,行数是无限制的,但是它将有3列。生成代码时,这是我要执行的生成的函数:
calculate_data(my_matrix : UnsafePointer<emxArray_real_T>!, result : UnsafeMutablePointer<emxArray_real_T>!)
Run Code Online (Sandbox Code Playgroud)
在不同的c文件中,emxArray_real_T的定义如下:
struct emxArray_real_T
{
double *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
Run Code Online (Sandbox Code Playgroud)
当我看到上述类的初始化选项时,这一点特别有意义:
emxArray_real_T.init(data: UnsafeMutablePointer<Double>!, size: UnsafeMutablePointer<Int32>!, allocatedSize: Int32, numDimensions: Int32, canFreeData: boolean_T)
Run Code Online (Sandbox Code Playgroud)
我试图遵循本文档作为将我的头缠在如何调用生成的C代码上的一种方法,但是我认为我可能缺少一个基本步骤。这是我在做什么:
// create an 2d array with some fake data
var mySampleData = [[Double]]();
for i in 0 ..< 3 {
mySampleData.append([1.1, 2.2, 3.3]);
}
// begin fulfilling requirements for emxArray_real_T
var data_pointer = UnsafeMutablePointer<Double>.allocate(capacity: 3);
data_pointer.initialize(from: mySampleData)
Run Code Online (Sandbox Code Playgroud)
但是,上面的代码引发了一个错误,指出:
Generic parameter 'C' could not be inferred
Run Code Online (Sandbox Code Playgroud)
我认为自己正在做完全错误的事情,并且可能走在错误的道路上。有一个类似的帖子与我的问题有关,如何将float [] []类型数组转换为“ emxArray_real_T * x”,但是提供的解决方案似乎是针对C的,而不是针对Swift 4的。我该如何有效地调用一个使用Swift 4的C函数,并且满足emxArray_real_T.init方法的要求?可以使用伪造的数据来演示基本原理。
在一个简单的 Xcode 项目中,我可以成功运行以下代码emxArray_real_T
,其中包含用于 struct和函数的模拟 C 构造calculate_data
。创建一个emxArray_real_T
我做的类型的对象
var data: [Double] = (0 ..< 12).map(Double.init)
var size: [Int32] = [4, 3]
var array = emxArray_real_T(
data: &data,
size: &size,
allocatedSize: 12,
numDimensions: 2,
canFreeData: false
)
Run Code Online (Sandbox Code Playgroud)
这个对象可以calculate_data
像calculate_data(&array, nil)
. 在实际应用程序nil
中将是另一个数组对象。为简单起见,此处仅用作占位符。
您的第二个问题可以通过使用正确的类型([Double]
而不是Double
第 6 行)来解决:
var mySampleData = [[Double]]();
for i in 0 ..< 3 {
mySampleData.append([i*1, i*2, i*3].map(Double.init));
}
let pointer = UnsafeMutablePointer<[Double]>.allocate(capacity: 3)
pointer.initialize(from: mySampleData, count: 3)
print((pointer + 0).pointee)
print((pointer + 1).pointee)
print((pointer + 2).pointee)
pointer.deallocate()
Run Code Online (Sandbox Code Playgroud)
输出将是
[0.0, 0.0, 0.0]
[1.0, 2.0, 3.0]
[2.0, 4.0, 6.0]
Run Code Online (Sandbox Code Playgroud)
正如预期的那样。
我不得不承认我使用了 Swift 5.0.1。不过,这应该不会产生重大差异。