我试图通过JAVA接口中的COM对象访问设备。
具体的呼叫(如制造商所述)是:
名称: ScanUSB
参数: out变量* serialNumbers
使用: serialNumbers是指向包含BSTR数组的变量的指针。
确切的调用并不重要,但我需要通过Java接口向它提供一个BSTR数组。COM接口的VB演示只需使用命令lm_Co1.ScanUSB(snNum)和Dim snNum As Object = Nothing即可完成。然后,snNum中的项将显示在下拉菜单中。
我正试图和雅各布一起做这件事,因为我在沟通上最幸运。这或多或少是我所使用的:
import com.jacob.com.Variant;
import com.jacob.com.Dispatch;
public class JunoReader {
public JunoReader() {
Dispatch oOphirLink = new Dispatch("clsid:{--the id of the device here--}");
Variant snNum = new Variant();
Variant testing = Dispatch.call(oOphirLink,"ScanUSB", snNum);
println(testing);
}
}当我运行这个程序时,一切都会正确编译,我可以确认我正在与设备通信,但我得到的只是我输入的空变量。
我的问题是:如何通过JAVA接口将BSTR数组提供给COM对象?
谢谢!
发布于 2014-04-25 19:47:31
所以,在一个月之后,没有空闲时间,我对我自己的问题有了一个答案,这个答案是“使用Python”。
Python允许用户使用comtypes模块访问COM对象,有效地使用一个命令:
from comtypes.client import CreateObject
target_guid = CreateObject("{TARGET-COM-CLSID-HERE}")这允许python与COM对象进行任何对话,因此Java没有给我带来任何麻烦。单行:target_guid.ScanUSB()生成(u'717610',),目标设备的序列号。请注意,Python在读取COM对象生成的Unicode时没有问题。
第二个技巧涉及Python的COM服务器,它是由win32com模块生成的。因为COM服务器可以注册到Windows,所以我不必担心dll位于何处。我只需要那个阴蒂。为了构建python服务器,我遵循了“快速启动服务器端COM和Python”的说明。那这一切看起来都是什么样子?
Python代码:
class OphirPyCOM:
_reg_clsid_ = "{PYTHON-COM-CLSID-HERE}"
_reg_desc_ = "Python COM server"
_reg_progid_ = "Python COM server"
_public_methods_ = [ 'Hello',
'ConnectOphir',
'ScanUSB', """More methods here"""
]
_public_attrs_ = ["""Some public attributes"""]
_readonly_attrs_ = ["""some read-only attributes"""]
def __init__(self):
"""some variables declared here"""
def Hello(self, who):
"""Verifies a connection"""
return "{PYTHON-COM-CLSID-HERE}" + str(who)
def ConnectOphir(self,clsid):
"""Connects to the target COM Object"""
from comtypes.client import CreateObject
self.target_guid = CreateObject(clsid)
return "OphirLMMeasurement object created."
def ScanUSB(self):
"""Communicates with the target device"""
self.connected_inst = self.target_guid.ScanUSB()
for i in range(0,len(self.connected_inst)):
self.inst_list.append(str(self.connected_inst[i]))
return self.inst_list
if __name__ == "__main__":
# use 'python com.py' to register the COM server
# use 'python com.py --unregister' to unregister it
print "Registering COM server..."
import win32com.server.register
win32com.server.register.UseCommandLine(OphirPyCOM)我们可以使用命令行运行该命令并将其注册。然后我们将这些值与JACOB一起转到Java中:
import com.jacob.com.Variant;
import com.jacob.com.Dispatch;
public class JunoReader {
String pyClsid = "{PYTHON-COM-CLSID-HERE}"; // This is where your python COM clsid goes
String opClsid = "{TARGET-COM-CLSID-HERE}"; // This is where your ultimate target clsid goes
public JunoReader() {
_pyClsid = "clsid:" + pyClsid
// This finds the COM object location:
Dispatch oOphirLink = new Dispatch(_pyClsid);
}
public String HandShake() {
String _talkBack = "is connected.";
Variant _handShake = Dispatch.call(oOphirLink,"Hello",_talkBack); // I am trying to look for the Juno...
return (_handShake.toString());
}
public String ConnectOphir() {
Variant _connectOphir = Dispatch.call(oOphirLink,"ConnectOphir", opClsid); // Connect to the target COM object
return (_connectOphir.toString());
}
public String ScanUSB() {
Variant _serialNumberList = Dispatch.call(oOphirLink,"ScanUSB"); // This scans the USB ports for devices
return (_serialNumberList.toString());
}
}调用JunoReader.ScanUSB()会产生:717610,就像它应该做的那样。通过实现制造商dll的后续方法,我可以将此设备中的数据读入Java。问题解决了。
注意:每次更改源文件时,可能都需要取消Python的注册,然后使用不同的clsid重新注册。Java很难建立到更新代码的连接,除非我每次更改文件时都使用一个新clsid。
为什么我花这么多时间打这个?因为大多数与将本机数据类型读入Java有关的建议都涉及到JNI和JNA的某些版本。我花了几周的时间来编写教程,但没有取得任何进展。另一方面,我昨天想到了这种方法,现在可以通过Java与我的设备进行通信了。Python服务器提供了一种简单、直观的方法来将Java与本机应用程序接口。没有UnsatisfiedLinkError,没有Can't find library,没有Classpath和JAVA_HOME问题。我不需要学习C或C++,所有的Python教程都像描述的那样工作,没有必要的修改。
总之,如果您在将本机数据类型读入Java时遇到困难,只需设置一个Python服务器,让Python的动态类型为您工作。
https://stackoverflow.com/questions/22545206
复制相似问题