【问题标题】:Reading BSTR in JAVA through JACOB通过JACOB读取JAVA中的BSTR
【发布时间】:2014-03-20 21:13:03
【问题描述】:

我正在尝试通过 JAVA 接口中的 COM 对象访问设备。

具体调用(如制造商所述)是:

名称:ScanUSB

参数:[out] VARIANT* serialNumbers

使用:serialNumbers 是指向包含 BSTR 数组的 VARIANT 的指针。

确切的调用无关紧要,但我需要通过 Java 接口为其提供 BSTR 数组。 COM 接口的 VB 演示只需使用命令lm_Co1.ScanUSB(snNum)Dim snNum As Object = Nothing 即可。然后将 snNum 中的项目显示在下拉菜单中。

我正在尝试与 JACOB 一起做这件事,因为我在沟通方面最幸运。这或多或少是我正在使用的:

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);
    }
}

当我运行它时,一切都正确编译,我可以确认我正在与设备通信,但我得到的只是我输入的 null Variant。

我的问题是:如何通过 JAVA 接口将 BSTR 数组提供给 COM 对象?

谢谢!

【问题讨论】:

    标签: java vb.net com jacob


    【解决方案1】:

    因此,一个月零空闲时间后,我对自己的问题有了一个答案,答案是“使用 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 的位置。我只需要clsid。为了构建 python COM 服务器,我按照“服务器端 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 COM,然后使用不同的 clsid 重新注册。 Java 很难建立与更新代码的连接,除非我每次更改文件时都使用新的 clsid。

    我为什么要花这么多时间来打字?因为大多数与将本机数据类型读入 Java 相关的建议都涉及某些版本的 JNI 和 JNA。我花了数周时间试图编译教程,但没有取得任何进展。另一方面,我昨天想到了这种方法,现在可以通过 Java 与我的设备进行通信。 Python COM 服务器提供了一种简单、直接的方式来将 Java 与本机应用程序接口。没有UnsatisfiedLinkErrors、没有Can't find librarys、没有ClasspathJAVA_HOME 问题。我不需要学习 C 或 C++,所有 Python 教程都按照描述的方式工作,无需进行必要的修改。

    总而言之,如果您在将本机数据类型读入 Java 时遇到问题,只需设置一个 Python COM 服务器,让 Python 的动态类型为您完成这项工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 2011-05-03
      • 2011-12-04
      • 1970-01-01
      • 2023-03-18
      相关资源
      最近更新 更多