我有一个Modbus类
public class Modbus {
// init TCP
public native void init(String ip, int port, int id);
public native short[] read_registers(int slaveid, int addr, int len);
如果我执行read_registers
,init方法中的id
将被打印到标准输出
如果我愿意
Modbus mb1 = new Modbus("192.168.0.250", 502, 1);
Modbus mb2 = new Modbus("192.168.0.250", 502, 2);
然后
mb1.read_registers(....);
mb2.read_registers(....);
在这两种情况下,它都会将 2
打印到标准输出。所以看来第二个实例覆盖了第一个实例。如何使用 jni-wrapper 的多个实例?
编辑:
这里是我使用的 C 代码,我的目标是使用与 samre 或不同 modbus 设备的多个连接
#include "eu_company_lib_comm_modbus_Modbus.h"
#include <modbus/modbus-rtu.h>
#include <modbus/modbus.h>
#include <errno.h>
modbus_t *mb;
int readError;
int writeError;
int errnr;
const char* errStr;
int c_id;
JNIEXPORT void JNICALL
Java_eu_company_lib_comm_modbus_Modbus_init__Ljava_lang_String_2I(
JNIEnv * env, jobject obj, jstring ip, jint port, jint id) {
const char* c_ip = (*env)->GetStringUTFChars(env, ip, 0);
mb = modbus_new_tcp(c_ip, port);
c_id=id;
if (mb == NULL) {
fprintf(stderr, "Unable to allocate libmodbus context\n");
fflush(stderr);
return;
}
modbus_set_debug(mb, 1);
if (modbus_connect(mb) == -1) {
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
fflush(stderr);
modbus_free(mb);
return;
}
(*env)->ReleaseStringUTFChars(env, ip, c_ip);
}
JNIEXPORT jshortArray JNICALL Java_eu_company_lib_comm_modbus_Modbus_read_1registers(
JNIEnv * env, jobject obj, jint slave_id, jint address, jint len) {
jshortArray result = (*env)->NewShortArray(env, len);
uint16_t tab_reg[len];
printf("%d\n",c_id);
fflush(stdout);
readError = modbus_read_registers(mb, address, len, tab_reg);
errnr = errno;
errStr = modbus_strerror(errno);
(*env)->SetShortArrayRegion(env, result, 0, len, tab_reg);
return result;
}
最佳答案
您的主要问题是在 JNI 部分中您正在使用全局变量。全局变量。因此,这些变量与 Modbus
实例没有任何关系。
从我的角度来看,您应该将尽可能多的代码从 JNI 移至 ModBus
的 Java 实现中,并使用本地字段来存储 Java JNI 级别上所需的所有持久值:
公共(public)类 Modbus {
private final String ip;
private final int port;
private final int id;
public ModBus(String ip, int port, ind id) {
this.ip = ip;
this.port = port;
this.id = id;
}
// init TCP
public native void init(String ip, int port, int id);
public native short[] read_registers(int slaveid, int addr, int len);
}
在 JNI 端,您可以使用 JNI 方法 GetObjectClass(..)
、GetFieldID(..)
和 访问所有 Java 字段以检索值GetObjectField(..)
.
搜索 SO 示例,您会发现很多 C 和 C++ 示例。
或者,您可以将 native 方法设置为私有(private),并添加一个包装方法,该方法在每次调用时将所需的值传递给 JNI 部分:
public void init() {
init(ip, port, id);
}
private native void init(String ip, int port, int id);
关于java - JNI 包装器的多个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38633147/