首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AssemblyScript -线性嵌套类布局

AssemblyScript -线性嵌套类布局
EN

Stack Overflow用户
提问于 2022-04-19 16:17:36
回答 1查看 91关注 0票数 0

我正在做一个线性数据布局,其中组件在内存中彼此相邻。直到我意识到在处理嵌套类时,我没有办法进行offsetofchangetype调用,所以一切都进行得很顺利。

例如,它的工作原理如下:

代码语言:javascript
复制
class Vec2{
    x:u8
    y:u8
}
const size = offsetof<Vec2>() // 2 -- ok
const ptr = heap.alloc(size)
changeType<Vec2>(ptr).x = 7 // memory = [7,0] -- ok

当嵌套类时,这种方法自然会失败。

代码语言:javascript
复制
class Player{
    position:Vec2
    health:u8
}
const size = offsetof<Player>() //5 -- want 3, position is a pointer
const ptr = heap.alloc(size)
changeType<Player>(ptr).position.x = 7 //[0,0,0,0,0] -- want [7,0,0], instead accidentally changed pointer 0

目标是内存布局如下所示:

代码语言:javascript
复制
| Player 1 | Player 2 | ...
| x y z h  | x y z h  |

理想情况下,我希望能够创建“价值类型”字段,或者如果不是这样的话,还有其他方法吗?

我希望在编写新组件时避免使用广泛的样板,即手工计算大小,并为每个字段在其偏移量处执行changetype等。

EN

回答 1

Stack Overflow用户

发布于 2022-04-20 23:38:45

如果有人感兴趣,我会在这里张贴我目前的解决方案。实现有点混乱,但使用自定义脚本或编译器转换当然是自动化的。

目标:为以下类创建一个线性代理,以便main函数按预期运行:

代码语言:javascript
复制
class Foo {
    position: Vec2
    health: u8
}
export function main(): Info {
    
    const ptr = heap.alloc(FooProxy.size)
    const foo = changetype<FooProxy>(ptr)

    foo.health = 3
    foo.position.x = 9
    foo.position.y = 10
}

解决方案:计算每个字段的偏移量和对齐度。

代码语言:javascript
复制
class TypeMetadataBase{
    get align():u32{return 0}
    get offset():u32{return 0}
}
class TypeMetadata<T> extends TypeMetadataBase{
    get align():u32{return alignof<T>()}
    get offset():u32{return offsetof<T>()}

    constructor(){
        super()
        if(this.offset == 0)
        throw new Error('offset shouldnt be zero, for primitive types use PrimitiveMetadata')
    }
};
class PrimitiveMetadata<T> extends TypeMetadataBase{
    get align():u32{return sizeof<T>()}
    get offset():u32{return sizeof<T>()}
};

class LinearSchema{

    metadatas:StaticArray<TypeMetadataBase>
    size:u32
    offsets:StaticArray<u32>
    constructor(metadatas:StaticArray<TypeMetadataBase>){
        let align:u32 = 0
        const offsets = new StaticArray<u32>(metadatas.length)
        for (let i = 0; i < metadatas.length; i++){
            if(metadatas[i].align !== 0)
                while(align % metadatas[i].align !== 0)
                    align++
            offsets[i] = align
            align += metadatas[i].offset
        }
        this.offsets = offsets
        this.metadatas = metadatas
        this.size = align
    }
}


class Vec2 {
    x: u8
    y: u8
}

class FooSchema extends LinearSchema{
    constructor(){
        super([
            new PrimitiveMetadata<u8>(),
            new TypeMetadata<Vec2>(),
        ])
    }

}
const schema = new FooSchema()

class FooProxy{
    static get size():u32{return schema.size}
    set health(value:u8){store<u8>(changetype<usize>(this) + schema.offsets[0],value)}
    get health():u8{return load<u8>(changetype<usize>(this) + schema.offsets[0])}
    get position():Vec2{return changetype<Vec2>(changetype<usize>(this) + schema.offsets[1])}
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71928142

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档