【问题标题】:Objective C to swift conversion for unions目标 C 到工会的快速转换
【发布时间】:2021-03-10 03:51:08
【问题描述】:

您好,我正在尝试将以下目标 c 代码转换为 swift,但努力将受支持的联合转换为 C 但不直接在 swift 中。

我不确定如何转换以下联合类型并将其传递给 MTLTexture getbytes?


union {
    float f[2];
    unsigned char bytes[8];
} u;

也是我想用 log 语句打印这些浮点值的最后一部分。

如果我能对下面的代码 sn-p 进行快速转换,那就太好了。


id<MTLDevice> device = MTLCreateSystemDefaultDevice();
id<MTLCommandQueue> queue = [device newCommandQueue];
id<MTLCommandBuffer> commandBuffer = [queue commandBuffer];

MTKTextureLoader *textureLoader = [[MTKTextureLoader alloc] initWithDevice:device];
id<MTLTexture> sourceTexture = [textureLoader newTextureWithCGImage:image.CGImage options:nil error:nil];


CGColorSpaceRef srcColorSpace = CGColorSpaceCreateDeviceRGB();
CGColorSpaceRef dstColorSpace = CGColorSpaceCreateDeviceGray();
CGColorConversionInfoRef conversionInfo = CGColorConversionInfoCreate(srcColorSpace, dstColorSpace);
MPSImageConversion *conversion = [[MPSImageConversion alloc] initWithDevice:device
                                                                   srcAlpha:MPSAlphaTypeAlphaIsOne
                                                                  destAlpha:MPSAlphaTypeAlphaIsOne
                                                            backgroundColor:nil
                                                             conversionInfo:conversionInfo];
MTLTextureDescriptor *grayTextureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR16Unorm
                                                                                                 width:sourceTexture.width
                                                                                                height:sourceTexture.height
                                                                                             mipmapped:false];
grayTextureDescriptor.usage = MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead;
id<MTLTexture> grayTexture = [device newTextureWithDescriptor:grayTextureDescriptor];
[conversion encodeToCommandBuffer:commandBuffer sourceTexture:sourceTexture destinationTexture:grayTexture];


MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:grayTexture.pixelFormat
                                                                                             width:sourceTexture.width
                                                                                            height:sourceTexture.height
                                                                                         mipmapped:false];
textureDescriptor.usage = MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead;
id<MTLTexture> texture = [device newTextureWithDescriptor:textureDescriptor];

MPSImageLaplacian *imageKernel = [[MPSImageLaplacian alloc] initWithDevice:device];
[imageKernel encodeToCommandBuffer:commandBuffer sourceTexture:grayTexture destinationTexture:texture];


MPSImageStatisticsMeanAndVariance *meanAndVariance = [[MPSImageStatisticsMeanAndVariance alloc] initWithDevice:device];
MTLTextureDescriptor *varianceTextureDescriptor = [MTLTextureDescriptor
                                                   texture2DDescriptorWithPixelFormat:MTLPixelFormatR32Float
                                                   width:2
                                                   height:1
                                                   mipmapped:NO];
varianceTextureDescriptor.usage = MTLTextureUsageShaderWrite;
id<MTLTexture> varianceTexture = [device newTextureWithDescriptor:varianceTextureDescriptor];
[meanAndVariance encodeToCommandBuffer:commandBuffer sourceTexture:texture destinationTexture:varianceTexture];


[commandBuffer commit];
[commandBuffer waitUntilCompleted];

union {
    float f[2];
    unsigned char bytes[8];
} u;

MTLRegion region = MTLRegionMake2D(0, 0, 2, 1);
[varianceTexture getBytes:u.bytes bytesPerRow:2 * 4 fromRegion:region mipmapLevel: 0];

NSLog(@"mean: %f", u.f[0] * 255);
NSLog(@"variance: %f", u.f[1] * 255 * 255);

如果我能迅速得到这方面的代表,那就太好了?

【问题讨论】:

  • 当我将 union 转换为 struct 并将其传递给 getBytes 函数时,我确实收到错误 - 无法将 struct 的值转换为 UnsafeMutableRawPointer

标签: ios objective-c swift


【解决方案1】:

您可以使用 Struct 代替,就像这样。并添加一个扩展来获取日志记录的描述。


struct u {

    var bytes: [UInt8] = [0,0,0,0, 0,0,0,0]

    var f: [Float32] {
        set {
            var f = newValue
            memcpy(&bytes, &f, 8)
        }
        get {
            var f: [Float32] = [0,0]
            var b = bytes
            memcpy(&f, &b, 8)
            return Array(f)
        }
    }
}

extension u: CustomStringConvertible {
    var description: String {
        let bytesString = (bytes.map{ "\($0)"}).joined(separator: " ")
        return "floats : \(f[0]) \(f[1]) - bytes  : \(bytesString)"
    }
}


var test = u()
print(test)
test.f = [3.14, 1.618]
print(test)
test.bytes = [195, 245, 72, 64, 160, 26, 207, 63]
print(test)

日志:

floats : 0.0 0.0 - bytes  : 0 0 0 0 0 0 0 0
floats : 3.14 1.618 - bytes  : 195 245 72 64 160 26 207 63
floats : 3.14 1.618 - bytes  : 195 245 72 64 160 26 207 63

【讨论】:

    【解决方案2】:

    getBytes 不需要整个 union 才能工作,那里只使用了 u.bytes,可以转换为

    var bytes = [UInt8](repeating: 0, count: 8)
    

    这是长度为 8 的数组(每个元素的初始值为 0),您将它作为 UnsafeMutableRawPointer 传递给 getBytes:

    varianceTexture.getBytes(&bytes, ...)
    

    对于联合,有很多种表示方式。例如:

    var u = ([Float](repeating: 0.0, count: 2), [UInt8](repeating: 0, count: 8))
    

    在这种情况下,您将其传递为

    varianceTexture.getBytes(&u.1, ...)
    

    或者你可以用类似的方式把它变成一个类或结构。

    【讨论】:

    • 不幸的是,您无法使用该 hack,因为无法快速表达相同的意图(在同一内存空间中保存 2 条信息)。所以你必须像这样将bytes 转换为f:stackoverflow.com/questions/41161034/…
    • 对不起,我没有关注您能否提供以下示例。我现在正在使用这样的联合 var u = ([Float](repeating: 0.0, count: 2), [UInt8](repeating: 0, count: 8)) 现在我想要像我在客观示例中显示的那样打印。 NSLog(@"mean: %f", u.f[0] * 255); NSLog(@"variance: %f", u.f[1] * 255 * 255);
    • 你能帮忙吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-11
    • 2011-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多