如何使用UnsafeMutableRawPointer来填充数组?

时间:2017-01-10 17:14:02

标签: swift metal

我有一个Metal纹理,我想通过使它成为一个float4数组从Swift访问它的数据(这样我就可以访问每个像素的4个颜色组件)。

我发现了[ "attribute": "image", "format": "raw", "value": function($model){ return ($model->image) ? Html::img("/path-to-img-location" . $model->image) : false; } ] 的这种方法:

MTLTexture

我根本不知道如何使用UnsafeMutableRawPointer,它是如何工作的,以及如何将数据恢复到一个简单的Swift数组中。

我的第一次尝试是创建一个指针并分配足够的空间,但我甚至不知道这是不是我应该做的:

getBytes(UnsafeMutableRawPointer, bytesPerRow: Int, bytesPerImage: Int, from: MTLRegion, mipmapLevel: Int, slice: Int)

然后我根本不知道如何将这些数据恢复到标准的Swift数组......

谢谢。

4 个答案:

答案 0 :(得分:11)

首先,我们假设你有一个UnsafeRawPointer和一个长度:

let ptr: UnsafeRawPointer = ...
let length: Int = ...

现在您要将其转换为[float4]。首先,您可以通过将UnsafeRawPointer绑定到类型:

来将let float4Ptr = ptr.bindMemory(to: float4.self, capacity: length) 转换为类型指针
let float4Buffer = UnsafeBufferPointer(start: float4Ptr, count: length)

现在您可以将其转换为类型化缓冲区指针:

let output = Array(float4Buffer)

由于缓冲区是一个集合,你可以用它初始化一个数组:

UnsafeRawPointer

有关使用a = [{'1':'value1'},{'2':'value2'}] b = [{'x':'value1'},{'y':'hello'},{'z':'value1'}] 的更多信息,请参阅SE-0138SE-0107UnsafeRawPointer Migration Guide

答案 1 :(得分:3)

另一种选择是创建适当大小的数组 并将地址传递给函数的底层存储:

For Each cel

在结束内,For Each cel In Intersect(.Rows(irow), .Range(iCol)) Private Sub cmdAdd_Click() Dim irow As Long Dim lastRow As Long Dim iCol As String Dim c As Range Dim ws As Worksheet Dim value As Long Dim NewPart As Boolean Dim ws_warehouse(7) As Worksheet '7 is total warehouse tab you have Dim cel As Range Set ws = Worksheets("Main") Set ws_warehouse(1) = Worksheets("Elkhart East") Set ws_warehouse(2) = Worksheets("Tennessee") Set ws_warehouse(3) = Worksheets("Alabama") Set ws_warehouse(4) = Worksheets("North Carolina") Set ws_warehouse(5) = Worksheets("Pennsylvania") Set ws_warehouse(6) = Worksheets("Texas") Set ws_warehouse(7) = Worksheets("West Coast") Set c = ws.Range("A7:A1048576").Find(What:=Me.PartTextBox.value, SearchOrder:=xlRows, _ SearchDirection:=xlPrevious, LookIn:=xlValues, LookAt:=xlWhole) If c Is Nothing Then 'find first empty row in database lastRow = ActiveSheet.UsedRange.Row - 1 + ActiveSheet.UsedRange.Rows.Count irow = lastRow + 1 NewPart = True Else 'find row where the part is irow = ws.Cells.Find(What:=Me.PartTextBox.value, SearchOrder:=xlRows, _ SearchDirection:=xlPrevious, LookIn:=xlValues).Row NewPart = False End If 'check for a part number If Trim(Me.PartTextBox.value) = "" Then Me.PartTextBox.SetFocus MsgBox "Please Enter A Part Number" Exit Sub End If If Trim(Me.MonthComboBox.value) = "" Then Me.MonthComboBox.SetFocus MsgBox "Please Enter A Month" Exit Sub End If If Trim(Me.AddTextbox.value) = "" Then Me.AddTextbox.SetFocus MsgBox "Please Enter A Value To Add Or Substract" Exit Sub End If Select Case MonthComboBox.value Case "Current Month" iCol = "C:C,S:S" Case "Current Month +1" iCol = "N:R" Case "Current Month +2" iCol = "O:R" Case "Current Month +3" iCol = "P:R" Case "Current Month +4" iCol = "Q:R" End Select actWarehouse = Me.warehousecombobox.ListIndex + 1 With ws .Cells(irow, "A").value = Me.PartTextBox.value For Each cel In Intersect(.Rows(irow), .Range(iCol)) cel.value = cel.value + CLng(Me.AddTextbox.value) cel.Interior.ColorIndex = 6 Next cel End With With ws_warehouse(actWarehouse) 'find part number l_row = .Range("A" & .Rows.Count).End(xlUp).Row NewPart = True For r = 7 To l_row If Trim(.Range("A" & r)) = "" Then Exit For If LCase(.Range("A" & r)) = LCase(Me.PartTextBox.Text) Then irow = r Exit For NewPart = False End If Next r If NewPart Then irow = r .Cells(irow, "A").value = Me.PartTextBox.value For Each cel In Intersect(.Rows(irow), .Range(iCol)) cel.value = cel.value + CLng(Me.AddTextbox.value) cel.Interior.ColorIndex = 6 Next cel End With 'clear the data Me.PartTextBox.value = "" Me.MonthComboBox.value = "" Me.AddTextbox.value = "" Me.PartTextBox.SetFocus Me.warehousecombobox.value = "" End Sub Private Sub cmdClose_Click() Unload Me End Sub 将数组存储表示为字节的集合,和 var pixelData = Array(repeating: float4(), count: myTextureSizeInFloat4) pixelData.withUnsafeMutableBytes { texture.getBytes($0.baseAddress!, ...) } 是指向第一个字节的指针。

答案 2 :(得分:1)

补充@VasilyBodnarchuk的答案:

extension UnsafeMutableRawPointer {
    func toArray<T>(to type: T.Type, capacity count: Int) -> [T] {
        return Array(UnsafeBufferPointer(start: bindMemory(to: type, capacity: count), count: count))
    }
}

答案 3 :(得分:0)

详细信息

  • Xcode 11.2.1(11B500),Swift 5.1

解决方案

error: invalid operands of types ‘double(double) throw ()’ and ‘double’ to binary ‘operator+’
     y = y0 + R;
         ~~~^~~

用法

#include <iostream>
#include <cmath>

double y0, y, R;
int main() {
    std::cin >> y0 >> R; 
    y = y0 + R;
}