2011-02-25 42 views
3

我希望能够在我的Android应用程序中添加一点本机C代码。我有一个IntBuffer,我用它作为OpenGL的glColorPointer方法的参数。这是填充/使用这样的事情:在Android游戏中将java.nio.IntBuffer传递给C函数

private IntBuffer mColourBuffer; 
int[] colours = new int[10 * 4]; // 10 dots, 4 colour components per dot 


ByteBuffer vbb3 = ByteBuffer.allocateDirect(10 * 4 * 4); 
vbb3.order(ByteOrder.nativeOrder()); 
mColourBuffer = vbb3.asIntBuffer(); 
mColourBuffer.put(colours); 
mColourBuffer.position(0); 

gl.glColorPointer(4, GL10.GL_FIXED, 0, mColourBuffer); 

我想更改这个缓冲区,但它从Java太慢了,所以我想用本地代码来做到这一点。我一直在寻找一个简单的例子,但我找不到任何我可以理解的或者可行的东西。我见过很多关于传递元素的文档,但我想要的只是一个指针。传递一个指针并在它指向的内存上运行应该非常有效;路过之间的Java和C会杀死可能做出的任何速度提升内存负载通过能够从C

上的内存操作

到目前为止,我想出了这一点:

void Java_com_poldie_myTouch2_myclass_mymethod(JNIEnv* env, jobject thiz, jintArray arr, int n) 
{ 
    jint *c_array; 

    c_array = (*env)->GetIntArrayElements(env, arr, NULL); 

    (*env)->ReleaseIntArrayElements(env, arr, c_array, 0); 


return; 


} 

,我可以这样调用:

public native void mymethod(IntBuffer intbuf, int n); 

mymethod(mColourBuffer , n); 

其中至少运行,并似乎做了电话,但对c_array操作任何企图(无论是作为一个复引用指针或数组)导致程序立即退出。

我在正确的轨道上吗?我可以将指向mColourBuffer后面的内存的指针传递给我的C代码,并在返回到我的Java代码时对其进行操作?

回答

2

在这里回答我自己的问题,看起来答案是采用您的顶点数组(您正在使用Java操纵每个框架)并将它们写入直接缓冲区。

在我上面的例子中,我想以某种方式填充直接缓冲区mColourBuffer每个框架与任何在本地数组'颜色'。原来你想要的东西是这样的:

JNIfastPutf(mfColourBuffer, colours, nCount); 

其中nCount是要复制的字节数。在(本地,C)函数JNIfastPutf看起来是这样的:

void Java_com_a_b_c_JNIfastPutf(JNIEnv* env, jobject thiz, jobject jo, jfloatArray jfa, int n) 
{ 
    float* pDst = (float*) (*env)->GetDirectBufferAddress(env, jo); 
    float* pSrc = (float*) (*env)->GetPrimitiveArrayCritical(env, jfa, 0);    
    memcpy(pDst, pSrc, n ); 

    (*env)->ReleasePrimitiveArrayCritical(env, jfa, pSrc, 0); 
} 

我发现下面的链接非常有帮助的(我的功能就是其C略加修改C版++为例):

http://www.badlogicgames.com/wiki/index.php/Direct_Bulk_FloatBuffer.put_is_slow

他们解释说,如果你使用浮动工具,你确实需要这种方法;使用整数据的速度要快得多,尽管这是我开始的地方,无论如何,他们的本地代码在“快速”int版本中显示的速度提高了20%到100%,所以似乎没什么原因不要这样做!

+0

不同版本的Android之间的速度不同。更新版本的Dalvik核心库具有更好的性能。 – fadden 2011-03-01 20:04:50