У меня есть проект Android, для которого у меня есть следующий код в моем файле c
JNIEXPORT void JNICALL Java_com_mersoft_labconco_controller_JNIStore_closeUART
(JNIEnv *env, jobject thiz) {
jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");
jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "fileDescriptor", "Ljava/io/FileDescriptor;");
jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");
jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
// LOGE("Closing port: %i", descriptor);
close(descriptor);
}
И я предоставляю все свои методы JNI в отдельном классе с именем JNITStore
class JNIStore {
@Synchronized
@Throws(IOBException::class, IOBI2cReadException::class)
external fun sendAndReceiveCommandi2c(array: ByteArray, numberOfRequestBytes: Int, numberOfResponseBytes: Int, address: Int): ByteArray
var fileDescriptor: FileDescriptor? = null
external fun openUART(): FileDescriptor
external fun closeUART()
@Synchronized
external fun updateAccessory(filename: String): Boolean
init {
System.loadLibrary("main")
}
}
Это дает мне сообщение об ошибке:
ОШИБКА JNI: GetIntField для недопустимой ссылки (0x0)
Насколько я могу судить, мой код на C правильно установленвверх по файловому дескриптору, чтобы получить его целочисленное поле здесь
jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
Единственная причина, по которой я мог подумать, что он возвращает неверную ссылку, заключается в том, что он может быть нулевым значением, так как он инициализируется как таковой, но это я даю ему значение до того, как этот closeUart
вызов функции сделан.
Есть ли что-нибудь еще, что может быть причиной этого?
РЕДАКТИРОВАТЬ: Вот код для openUART
JNIEXPORT jobject JNICALL Java_com_mersoft_labconco_controller_JNISTORE_openUART
(JNIEnv *env, jclass thiz) {
int baudrate = 115200;
int fd;
speed_t speed;
jobject mFileDescriptor;
struct serial_rs485 rs485conf;
speed = getBaudrate(baudrate);
if (speed == -1) {
LOGE("Invalid baudrate");
throwJavaException(env, "Invalid baudrate");
return NULL;
}
fd = open("/dev/ttyO1", O_RDWR);
if (fd == -1) {
/* Throw an exception */
LOGE("Cannot open port");
throwJavaException(env, "Cannot open port");
return NULL;
}
// LOGE("Opened port %i", fd);
struct termios cfg;
if (tcgetattr(fd, &cfg)) {
LOGE("tcgetattr() failed");
close(fd);
throwJavaException(env, "tcgetattr() failed");
return NULL;
}
cfmakeraw(&cfg);
cfsetispeed(&cfg, speed);
cfsetospeed(&cfg, speed);
cfg.c_cflag |= PARODD;
cfg.c_cflag |= PARENB;
cfg.c_cflag |= (CLOCAL | CREAD);
cfg.c_cflag |= CSTOPB;
//test Flags
// cfg.c_iflag |= (IXON | IXOFF | IXANY);
// cfg.c_iflag |= (INPCK | ISTRIP);
// cfg.c_iflag |= (ISTRIP | PARMRK);
if (tcsetattr(fd, TCSANOW, &cfg)) {
LOGE("tcsetattr() failed");
close(fd);
throwJavaException(env, "tcsetattr() failed");
return NULL;
}
rs485conf.flags |= SER_RS485_ENABLED;
rs485conf.flags |= SER_RS485_RTS_ON_SEND;
rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
// rs485conf.flags &= ~SER_RS485_RTS_AFTER_SEND;
//rs485conf.flags |= SER_RS485_USE_GPIO;
//rs485conf.gpio_pin = 13;//13;
if (ioctl(fd, TIOCSRS485, &rs485conf) < 0) {
LOGE("ioctl error\n");
}
jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor");
jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>", "()V");
jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I");
mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor);
(*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint) fd);
return mFileDescriptor;
}