Java中,使用JNA调用Visa32.dll,控制频谱仪~~
C:\Program Files\Agilent\IO Libraries Suite\
有visa.chm,是方法和属性的说明。
首先,难倒在viOpen方法上。连不上频谱仪,什么都白搭啊~~
在visa.chm中,viOpen的格式如下:
viOpen(ViSession sesn, ViRsrc rsrcName, ViAccessMode accessMode, ViUInt32 timeout, ViPSession vi);
在
C:\Program Files\IVI Foundation\VISA\WinNT\include
visa.h
visatype.h
两个文件中,可以查看类型定义。visa.chm中也有说明。
ViSession、ViPSession,ViAccessMode 和ViUInt32,其实都是unsigned long
ViRsrc其实是char
所以,初始JNA代码如下:
package jna;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.LongByReference;
public class InstrumentWrong {
public interface VISA32 extends Library {
// VISA32 INSTANCE = (VISA32) Native.loadLibrary("VISA32",
// VISA32.class);
VISA32 INSTANCE = (VISA32) Native.loadLibrary(
"C:\\WINDOWS\\system32\\VISA32.dll", VISA32.class);
public static final long VI_NULL = 0;
public static final long VI_SUCCESS = 0;
public int viOpenDefaultRM(LongByReference session);
public int viOpen(long viSession, String rsrcName, long accessMode,
long timeout, LongByReference session);
public int viClose(long vi);
}
LongByReference defaultSession;
LongByReference vipSession;
public boolean open(String deviceType, String ip) {
VISA32 visa32 = VISA32.INSTANCE;
defaultSession = new LongByReference(0);
int result = visa32.viOpenDefaultRM(defaultSession);
if (result != VISA32.VI_SUCCESS) {
return false;
}
vipSession = new LongByReference(0);
String cmd = "TCPIP0::<ip>::inst0::INSTR".replace("<ip>", ip);
result = visa32.viOpen(defaultSession.getValue(), cmd, VISA32.VI_NULL,
VISA32.VI_NULL, vipSession);
if (result != VISA32.VI_SUCCESS) {
System.out.println(result);
return false;
}
return true;
}
/**
* 关闭设备.
*
* @return 成功返回true,失败返回false
*/
public boolean close() {
int result = VISA32.INSTANCE.viClose(vipSession.getValue());
if (result != VISA32.VI_SUCCESS) {
return false;
}
result = VISA32.INSTANCE.viClose(defaultSession.getValue());
if (result != VISA32.VI_SUCCESS) {
return false;
}
return true;
}
/**
* @param args
*/
public static void main(String[] args) {
InstrumentWrong device = new InstrumentWrong();
boolean isOpen = device.open("xxx", "192.168.1.10");
if (!isOpen) {
System.out.println("open failed.");
return;
}
device.close();
}
}
运行,始终报错:
-1073807342
open failed.
在visa.h中搜错误号,可知定义是VI_ERROR_INV_RSRC_NAME。
是资源名字不正确~~~
搜了N久,以为是编码的问题,试过传递byte[]什么的,依然报此错误。
烦恼N久~~~
后经牛人指定,恍然大悟~~~
JNA的文档说明在此:
http://jna.java.net/javadoc/overview-summary.html#buffers
--------------------------
C Type Native Representation Java Type
long long, __int64 64-bit integer long
long platform-dependent (32- or 64-bit integer) NativeLong
-----------------------------
原来VISA中是32位的long,所以java中应该用NativeLong,而不是long~~~
修改后代码如下:
package jna;
import com.sun.jna.Library;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.ptr.LongByReference;
public class InstrumentRight {
public interface VISA32 extends Library {
// VISA32 INSTANCE = (VISA32) Native.loadLibrary("VISA32",
// VISA32.class);
VISA32 INSTANCE = (VISA32) Native.loadLibrary(
"C:\\WINDOWS\\system32\\VISA32.dll", VISA32.class);
public static final long VI_NULL = 0;
public static final long VI_SUCCESS = 0;
public int viOpenDefaultRM(LongByReference session);
public int viOpen(NativeLong viSession, String rsrcName,
NativeLong accessMode, NativeLong timeout,
LongByReference session);
public int viClose(NativeLong vi);
public int viScanf(NativeLong vi, String readFmt, Object... args);
public int viPrintf(NativeLong vi, String writeFmt, Object... args);
}
LongByReference defaultSession;
LongByReference vipSession;
public boolean open(String deviceType, String ip) {
VISA32 visa32 = VISA32.INSTANCE;
defaultSession = new LongByReference(0);
int result = visa32.viOpenDefaultRM(defaultSession);
if (result != VISA32.VI_SUCCESS) {
return false;
}
vipSession = new LongByReference(0);
String cmd = "TCPIP0::<ip>::inst0::INSTR".replace("<ip>", ip);
NativeLong a = new NativeLong(defaultSession.getValue());
NativeLong b = new NativeLong(0);
result = visa32.viOpen(a, cmd, b, b, vipSession);
if (result != VISA32.VI_SUCCESS) {
System.out.println(result);
return false;
}
return true;
}
/**
* 关闭设备.
*
* @return 成功返回true,失败返回false
*/
public boolean close() {
NativeLong a = new NativeLong(vipSession.getValue());
int result = VISA32.INSTANCE.viClose(a);
if (result != VISA32.VI_SUCCESS) {
System.out.println(result);
return false;
}
NativeLong b = new NativeLong(defaultSession.getValue());
result = VISA32.INSTANCE.viClose(b);
if (result != VISA32.VI_SUCCESS) {
System.out.println(result);
return false;
}
return true;
}
public boolean writeCmd(String cmdStr) {
NativeLong a = new NativeLong(vipSession.getValue());
int result = VISA32.INSTANCE.viPrintf(a, "%s\n", cmdStr);
if (result != VISA32.VI_SUCCESS) {
System.out.println(result);
return false;
}
return true;
}
public String readResult() {
NativeLong a = new NativeLong(vipSession.getValue());
Memory mem = new Memory(200);
int result = VISA32.INSTANCE.viScanf(a, "%t", mem);
if (result != VISA32.VI_SUCCESS) {
System.out.println(result);
return null;
}
return mem.getString(0);
}
/**
* @param args
*/
public static void main(String[] args) {
InstrumentRight device = new InstrumentRight();
boolean isOpen = device.open("xxx", "192.168.1.10");
if (!isOpen) {
System.out.println("open failed.");
return;
}
// 查询设备名称
device.writeCmd("*IDN?");
// 读取返回值
String s = device.readResult();
System.out.println(s);
device.close();
}
}
执行,得到设备名称,OK啦~~哈
--------------------------
好像直接用int也可以~~~