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

如何使用用户定义的数据类型作为参数从java调用本机方法?,java,java-native-interface,native,Java,Java Native Interface,Native,我有一个以用户定义的数据类型(结构)为参数的本机方法。如何使用JNI从java调用此方法?如果您有这样的方法: int cFunction(mydatatype data) ... JNIEXPORT jint JNICALL Java_Javatest_jMethod(JNIEnv*, jobject obj, jint a); //Get a field jfieldID jfIdentField = env->GetFieldID(jcMyObjectClass,"selfRef

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

如果您有这样的方法:

int cFunction(mydatatype data) ...
JNIEXPORT jint JNICALL Java_Javatest_jMethod(JNIEnv*, jobject obj, jint a);
//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
    }
}
你不能直接叫它。您需要一层JNI将其粘合在一起


因此,JNI函数是从您的代码生成的:

class JavaTest {
    public native int jMethod(int a);
}
在该类上运行
javah
,您将得到如下头文件:

int cFunction(mydatatype data) ...
JNIEXPORT jint JNICALL Java_Javatest_jMethod(JNIEnv*, jobject obj, jint a);
//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
    }
}
实现该方法以调用
cFunction(mydatatype)


有一种读取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对象作为参数,并根据需要将其转换为C结构

也许这对你有帮助

对于自引用对象,可以按如下方式遍历所有对象:

int cFunction(mydatatype data) ...
JNIEXPORT jint JNICALL Java_Javatest_jMethod(JNIEnv*, jobject obj, jint a);
//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
    }
}

谢谢你的回答。首先,我可以知道这个方法的本机声明。假设方法签名是int-Cmethod(mydatatype m),其中mydatatype是C的结构。@dacwe:你能再详细一点吗?(对于该示例:C-struct as parameter)。为此,我需要使用结构mydatatype的相同成员创建java类。我是否正确?是的,我将。我有一个方法,它需要一个结构并返回一个整数。现在我想使用JNI从java调用这个方法。我如何从java端发送这个方法的参数?我们不能直接从java调用这个方法吗?如果我将自引用指针作为C结构的一个成员,该怎么办?您可以在java,并通过itI放置直接字段访问,因为它更简单,但如果需要,也可以使用方法