Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何从Renderscript内核检索结构_Java_Android_Renderscript_Android Renderscript - Fatal编程技术网

Java 如何从Renderscript内核检索结构

Java 如何从Renderscript内核检索结构,java,android,renderscript,android-renderscript,Java,Android,Renderscript,Android Renderscript,我有个问题。我想从renderscript内核中检索结构。我想要的是得到一个输入,一个struct元素。。。我会修改它,然后返回修改过的。但是在反射层中没有这样的方法。我试图从缓冲区手动反序列化数据,但我甚至无法将缓冲区复制到ByteBuffer,因为分配在copyTo中对某个类型进行了验证,所以我不知道该怎么做…RenderScript支持自定义元素。要创建一个,请在RS脚本中声明一个自定义的typedef struct,如下所示: typedef struct MyElement {

我有个问题。我想从renderscript内核中检索结构。我想要的是得到一个输入,一个struct元素。。。我会修改它,然后返回修改过的。但是在反射层中没有这样的方法。我试图从缓冲区手动反序列化数据,但我甚至无法将缓冲区复制到ByteBuffer,因为分配在copyTo中对某个类型进行了验证,所以我不知道该怎么做…

RenderScript支持自定义元素。要创建一个,请在RS脚本中声明一个自定义的
typedef struct
,如下所示:

typedef struct MyElement {

    int x;
    int y;
    bool simpleBool;

} MyElement_t;
在构建过程之后,将出现一个
ScriptField\u MyElement
Java类,镜像RS结构。您将能够使用此类创建使用您自己的元素的自定义分配:

// Declares a new Allocation, based upon the custom struct Element
Element myElement = ScriptField_MyElement.createElement(mRS);
Allocation myElementsAllocation = Allocation.createSized(mRS, myElement, 5);

// Or

Allocation myElementsAllocation = ScriptField_MyElement.create1D(mRS, sizeX).getAllocation();
您可以在中找到此过程的示例。 此外,在中,您可以看到如何使用自定义元素来建模数学结构(在本例中是粒子,以一定的加速度下落)

在RenderScript脚本内部:

  • 要从分配中获取自定义元素,请执行以下操作:

    MyElement_t el = * (MyElement_t *) rsGetElementAt(aIn, index);
    
    rsSetElementAt(myAlloc, (void *)&el);
    
  • 要更改自定义图元成员,请执行以下操作:

    el.x = 10;
    
  • 要在分配中设置自定义元素,请执行以下操作:

    MyElement_t el = * (MyElement_t *) rsGetElementAt(aIn, index);
    
    rsSetElementAt(myAlloc, (void *)&el);
    
参考:

编辑:

目前,没有直接的方法将自定义struct元素复制到Java端

提供了该过程的示例

对示例的简短解释 注意:以下过程是实验性的,根本不起作用!如果您计划大量使用此过程,请使用Android NDK访问分配。 此外,在Android SDK的未来版本中,此代码可能会中断,因为它依赖于Java反射;在Android SDK中,一些通常隐藏的方法可以在没有任何通知的情况下更改

让我们假设使用以下自定义结构元素:

typedef struct Point {
    int x;
    int y;
} Point_t;
当查看生成的结构代码时(在Android Studio中,通过按住CTRL+B键,同时关注Java端的
ScriptField\u点
),可以看到以下元素:

public static Element createElement(RenderScript rs) {
        Element.Builder eb = new Element.Builder(rs);
        eb.add(Element.I32(rs), "x");
        eb.add(Element.I32(rs), "y");
        return eb.create();
    }
您可以用一种简陋的方式映射自定义结构的内容:

1) 定义目标字节数组:

    byte destinationArray[] = new byte[allocationGrayPointOrdered.getBytesSize()];
2) 使用Java反射访问隐藏的
分配.copyTo
方法:

private static Method getCopyToWithoutValidationMethod(){
    // private void copyTo(Object array, Element.DataType dt, int arrayLen)
    Method allocationHiddenCopyToMethod = null;
    try {
        allocationHiddenCopyToMethod = Allocation.class.getDeclaredMethod("copyTo", Object.class, Element.DataType.class, int.class);
        allocationHiddenCopyToMethod.setAccessible(true);
    } catch (NoSuchMethodException e) {
        throw new RuntimeException("Could not find allocationHiddenCopyToMethod");
    }

    return allocationHiddenCopyToMethod;
}
3) 执行复制:

// Gets reflected method
Method copyToWithoutValidationMethod = getCopyToWithoutValidationMethod();

// Tries to copy contents
try {
    copyToWithoutValidationMethod.invoke(allocationGrayPointOrdered, destinationArray, 
                                                Element.DataType.UNSIGNED_8, destinationArray.length);
} catch (IllegalAccessException e) {
    throw new RuntimeException(e);
} catch (InvocationTargetException e) {
    throw new RuntimeException(e);
}
4) 一旦数组中填充了源数据,就可以将其内容映射到人类可读的结构

// Defines the destination array
ScriptField_Point.Item mappedItems[][] = new ScriptField_Point.Item[sizeX][sizeY];

// Wraps array contents
ByteBuffer byteBuffer = ByteBuffer.wrap(destinationArray);
// Sets byte order to be Android-like
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);

// Iterates on every column and row
for (int x = 0; x < sizeX; x++) {
    for (int y = 0; y < sizeY; y++) {

        // Allocates a new item
        ScriptField_Point.Item currentItem = new ScriptField_Point.Item();

        // Calculate the offset in the source array
        int currentOffset = (x + y * sizeX) * ScriptField_Point.Item.sizeof;

        // Gets data from the byte array
        currentItem.x = byteBuffer.getInt(currentOffset);
        currentItem.y = byteBuffer.getInt(currentOffset + 4);

        mappedItems[x][y] = currentItem;
    }
}
//定义目标数组
ScriptField_Point.Item MappeItems[][]=新ScriptField_Point.Item[sizeX][sizeY];
//包装数组内容
ByteBuffer ByteBuffer=ByteBuffer.wrap(destinationArray);
//将字节顺序设置为类似于Android
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
//迭代每一列和每一行
对于(int x=0;x

有关完整的解释,请参阅

Hmm,但您指定了如何使用反射层创建分配。我的问题是如何在内核运行(和修改)后读取java中的结构,我添加了进程:)嗯。。。“副本”中的答案不正确。答案是,您可以使用分配的copy1DRangeToUnchecked方法将其复制到ByteBuffer中,并自己反序列化。后来我意识到了这一点