JNI: от кода C до Java и JNI

Фон

Я разрабатываю приложение для android в eclipse, и теперь у меня есть проблема, и мне нужна ваша помощь. Поэтому я должен вызывать функцию, написанную в C из приложения JAVA. Но по моему способу написания кода у меня есть несколько Вопросов, которые вы можете увидеть ниже. Я жду ваших ответов и идей...

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 вместо unsigned long я использую int, чтобы писать.

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.

  • Что я могу использовать вместо unsigned char в JAVA-коде?
  • Что я должен написать в JAVA-коде вместо unsigned char data[1];?

Вопрос 2.

  • Как я могу использовать class jblobData_c вместо blobData_t* pInputInfo в JAVA-коде?
  • Что я должен писать в 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, которая является функцией кода C вместо blobData_t* pInputInfo, чтобы эта функция работала правильно, и данный параметр был тем же самым

Ссылка

Ответ 1

За вопрос №1:

Вы можете использовать jchar. Примитивные символы в java не подписаны, а о единственном примитиве, который не является. Обратите внимание, что jchar является UTF-16 char, поэтому вам придется "сопоставить" jchar с обычным char, как и с любой проблемой преобразования символов. Для простых преобразований это обычно можно выполнить путем литья

char c_char = (char)java_char;

поскольку основной ASCII имеет одни и те же числовые значения между ASCII и UTF-16. Однако это подвержено ошибкам, если кто-то действительно попытается передать "специальный" символ через интерфейс. Лучше всего было бы (в java-стороне, как это проще) преобразовать символы в байты, используя соответствующий набор символов для вашей платформы (чтобы обеспечить совместимость платформ в слоях C). Затем вам нужно только передать байт [] в JNI-вызов, и байты будут правильно соответствовать символам, которые вероятнее всего ожидаются.

За вопрос №2:

Если ваш метод CheckEnrollmentExists(...) является точкой входа привязки JNI, вы не можете безопасно изменять типы данных. Это означает, что все входные данные должны быть значениями типа данных JNI. Хотя вы можете выбрать эквиваленты типа данных C (и вы, возможно, сможете заставить свой компилятор сделать это в любом случае), следует избегать таких методов. Это неявно означает, что точки входа JNI не могут принимать структуру структурных данных, не определенную в заголовках JNI. Другими словами, вы не можете передать свою собственную структуру методу.

Если для метода требуется доступ к C-структуре через вызовы, используйте другое средство. Я видел, как люди сохраняют указатель на выделенную структуру данных в целочисленном или длинном члене (правильное кастинг). Затем вы можете переписать исходную кодовую часть для извлечения указателя из объекта "this", передаваемого в вызов, и сделать разыменование для получения требуемых данных.

Для вопроса № 3:

Это на самом деле то же самое, что и вопрос №2. В "привязывающей обертке", которую вы положили, вы должны получить хранимое значение указателя в объекте int или long, а затем передать его внутреннему методу. Поскольку передача указателя является вызовом от C до C, никакой дополнительной магии не требуется.