我在Xamarin.iOS中长时间使用我的绑定和静态加速Obj C库。由于统一的API和较新iOS设备中的64位arch,我被迫成功更新和编译我的新版本库并将其与适当的绑定链接。
为了实现良好的性能并且由于处理大块数据(大图像阵列)而导致数据传输obj-C&#C#之间没有时间损失我决定使用不安全的代码将数组从c#绑定到obj-c并且通常使用IntPtr包装数组,即:
private IntPtr WrapIntArray(int[] array) {
IntPtr intPtr;
unsafe
{
fixed (int* pArray = array)
{
intPtr = new IntPtr((void *) pArray);
}
}
return intPtr;
}
然后将此IntPtr传递给导出的绑定方法:
[Export("....")]
void method(IntPtr input, IntPtr output);
如果在32位单音素上运行,我的库在armv7设备上运行良好。
当我今天决定在armv7 + arm64的构建配置中运行时,我的库停止工作并且我发生了崩溃。在调查和调试之后,我发现现在当我在C#中为数组声明我的IntPtr包装器时它的大小为8字节(64位)。
因为我使用obj-c库来设置"输出"通过为数组分配32位值(即输出[43] = 2)的方法导致崩溃。
有人可以帮助我了解我如何处理这个新案例的方式我的绑定方式,而不更改我的obj-c库?
由于
安东尼奥
答案 0 :(得分:1)
上面示例的最大问题是您获取了数组的地址,并且只保证地址在“fixed”语句的持续时间内保持固定。一旦你离开它,GC可能会移动数据。
现在,由于这些是图像,因此可能很大,GC可能不会移动您的数据,但这是GC的启发式问题。最好避免这种做法。
您的方法声明中的IntPtrs应该在C中显示为“void *”或类似的东西。所以这真的取决于你在C方面做了什么。