JNI: 从C代码到Java和JNI

12

背景

我正在Eclipse中为Android开发一个应用程序,现在我遇到了问题,需要您的帮助。所以我必须从JAVA应用程序中调用用C编写的函数。但是在编写代码的过程中,我有一些问题,您可以在下面看到。我正在等待您的答案和想法...

C 代码:

typdef struct blobData_s {
    unsigned long length;
    unsigned char data[1];
} blobData_t;

unsigned int CheckEnrollmentExist ( unsigned long hdevice, blobData_t* pInputInfo ) {
    // Function code goes here
    ..........................
    return some_value;
}

JAVA代码:

在JAVA代码中,我使用int代替unsigned long,这样我就可以编写:

class jblobData_c {
    public int langth;
    *Question 1.*
}

public class ApplicationMainClass extends Activity {
    // Some code goes here
    ......................

    public native int JCheckEnrollmentExist( int jhdevive, *Question 2.* );

}

问题1.

  • 在JAVA代码中,我可以使用什么代替unsigned char
  • 在JAVA代码中,我需要写什么来代替unsigned char data[1];

问题2.

  • 如何在JAVA代码中使用class jblobData_c代替blobData_t* pInputInfo
  • 在JAVA代码中,我需要写什么代替blobData_t* pInputInfo

JNI代码:

JNIEXPORT jint JNICALL Java_com_Test_JCheckEnrollmentExist(JNIEnv* env, jobject obj, jint jhdevice, *Question 2.* ) {

    // Call the base function from C code.
    return CheckEnrollmentExist( jhdevice, *Question 3.*);
}

问题3.

  • 我必须在CheckEnrollmentExist函数中写什么,而不是blobData_t* pInputInfo,以便使此函数正常工作并且给定的参数相同?这是C代码函数。

参考资料

  1. 如何在JNI中来回传递C结构体到Java代码中?
  2. 高效地通过JNI传递大型C结构体
  3. 通过JNI从C返回结构体对象到Java
  4. 在Java和C之间传递数据
  5. 使用long类型在JNI和Java之间传递指针
  6. 在JNI和Java之间传递指针

1
至少对于问题1,我会说一个字节是你想要的。我还发现了这篇其他的帖子https://dev59.com/22865IYBdhLWcg3wOb5h - Maximus
"一个字节就是你想要的。" 你需要解释吗?谢谢! - Viktor Apoyan
非常抱歉,查看Java规范后发现byte确实是有符号的... - Maximus
1个回答

3

针对问题 #1:

您可以使用jchar。Java中的原始字符不是有符号的,这是唯一不是的原始类型。请注意,jchar是UTF-16字符,因此您将不得不“映射”jchar到常规字符,就像任何字符转换问题一样。对于简单的转换,通常可以通过强制转换来完成。

char c_char = (char)java_char;

由于核心ASCII在ASCII和UTF-16之间共享相同的数字值。然而,如果有人尝试通过该接口传递“特殊”字符,则容易出错。一个更好的方法是(在Java端,因为它更容易)使用适合您平台的适当字符集将字符转换为字节(以确保在C层中的平台兼容性)。然后,您只需要传递一个byte []到JNI调用,并且字节将正确对应于C可能期望的字符。
对于问题#2:
如果您的CheckEnrollmentExists(...)方法是JNI绑定入口点,则不能安全地更改数据类型。这意味着所有入口输入都必须是JNI数据类型值。虽然您可以选择C数据类型的等效项(您可能仍然可以让编译器这样做),但这种技术应受到警告。这意味着JNI入口点不能接受未在JNI标头中定义的结构数据结构。换句话说,您无法将自己的结构传递给该方法。
如果该方法需要跨调用访问C结构,请使用其他方法。我见过人们将分配的数据结构的指针存储在成员整数或长整数中(进行正确的转换)。然后,您可以重新编写本机代码端以从传递到调用中的“this”对象中检索指针,然后执行解引用以获取所需的数据。
对于问题#3:
实际上,这与问题#2相同。在您编写的“绑定包装器”中,您将检索Java对象的int或long字段中存储的指针值,将其强制转换为适当的结构指针,然后将其传递给内部方法。由于指针的传递是C到C的调用,因此不需要额外的魔法。

抱歉,您的回答并没有帮助到我,因为它没有包含任何有用的链接或示例,以便我可以解决我的问题。您能否提供更详细的信息、文章或一些链接,以便我可以查看它们并找到我的问题的答案!非常感谢! - Viktor Apoyan
2
@ViTo,有什么问题吗?你提出了三个具体的问题。所有传递到JNI绑定方法中的参数都必须是jni.h声明的数据类型。在C语言中,您需要进行适当的转换。如果您进行了分配,则需要将每个对象指针存储在Java类中,以便当该类返回到JNI层时,您可以访问这些指针。 - Edwin Buck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接