如何从java调用用户定义的数据类型作为参数的本机方法?

时间:2012-05-29 08:40:14

标签: java java-native-interface native

我有一个本地方法,用户定义的数据类型(结构)作为参数。如何使用JNI从java调用此方法?

2 个答案:

答案 0 :(得分:2)

如果你有这样的方法:

int cFunction(mydatatype data) ...

你无法直接调用它。你需要一层JNI将它粘合在一起。


因此,您的代码会生成一个JNI函数:

class JavaTest {
    public native int jMethod(int a);
}

在该类上运行javah,您将获得如下的头文件:

JNIEXPORT jint JNICALL Java_Javatest_jMethod(JNIEnv*, jobject obj, jint a);

实施该方法以调用cFunction(mydatatype)

JNIEXPORT jint JNICALL Java_Javatest_jMethod(JNIEnv*, jobject obj, jint a) {
    mydatatype data;
    data.count = a;
    return (jint) cFunction(data);
}

答案 1 :(得分:2)

有读取java对象字段的方法:

jint _JMETHODNAME(MyClass,myMethod) (JNIEnv *env, jclass jcMyClass, jobject joMyObject)
{
    //Get the class
    jcMyObjectClass = env->FindClass("test/native/MyObject");
    if (jtException = env->ExceptionOccurred()) 
    {
        //Error management
    }
    if (jcMyObjectClass == NULL) 
    {
        //Error management
    }

    //Check if the class matchs the object
    jboolean jbFlag = env->IsInstanceOf(joMyObject,jcMyObjectClass);
    if (jtException = env->ExceptionOccurred()) 
    {
        //Error management
    }
    if (jbFlag == JNI_FALSE) 
    {
        //Error management
    }

    //Get a field
    jfieldID jfIdentField = env->GetFieldID(jcMyObjectClass,"fieldName","Ljava/lang/String;");
    if (jtException = env->ExceptionOccurred())
    {
        //Error management
    }
    if (jfIdentField == NULL) 
    {
        //Error management
    }

    //Read a field
    jstring jsMyString = (jstring)env->GetObjectField(joMyObject,jfIdentField);
    if (jtException = env->ExceptionOccurred()) 
    {
        //Error management
    }
    if (jsMyString == NULL) 
    {
        //Error management
    }

    //Convert to C++ format
    LPCTSTR strMyString = (LPTSTR)env->_tGetString(jsMyString, NULL);
    jsize myStringLen = env->_tGetStringLength(jsMyString);
    if (strMyString == NULL) 
    {
        //Error management
    }   
}

因此,您可以使用Java Object作为参数,并根据需要将其转换为C结构。

也许这有助于你。

对于自引用对象,你可以像这样经历所有这些:

//Get a field
jfieldID jfIdentField = env->GetFieldID(jcMyObjectClass,"selfReference","test/native/MyObject");
if (jtException = env->ExceptionOccurred())
{
    //Error management
}
if (jfIdentField == NULL) 
{
    //Error management
}

//Read a field
jobject joNextMyObject = (jstring)env->GetObjectField(joMyObject,jfIdentField);
if (jtException = env->ExceptionOccurred()) 
{
    //Error management
}
while (joNextMyObject != NULL) 
{
    //Process object

    //Read a field
     joNextMyObject = (jstring)env->GetObjectField(joNextMyObject,jfIdentField);
    if (jtException = env->ExceptionOccurred()) 
    {
        //Error management
    }
}