【问题标题】:Passing an HWND from a java program to a C library将 HWND 从 java 程序传递到 C 库
【发布时间】:2017-04-15 22:35:51
【问题描述】:

我的任务是将 C# Windows 窗体 GUI 转换为 Java Swing GUI。我必须使用用 C 编写的同一个库。库中的一个函数需要窗口的本机句柄才能将 C 程序链接到窗口。在 C# 代码中,本机句柄的使用相当简单,并且将 Intptr 传递给函数。在java中,情况就不同了。我找到了一种使用 JNA(Java Native Access)和 HWND 本地句柄表示来获取窗口句柄的方法。问题是当我使用HWND 给句柄时,每次都会弹出一个无效的内存访问异常。这是我正在使用的代码。

主类:

    public class main {
    public static void main(String[] args) {
        JFrame jFrame = new JFrame();
        jFrame.setSize(5000,5000);
        jFrame.setVisible(true);
        final HWND ptrRef = new HWND(Native.getComponentPointer(jFrame));
        CLibrary cl = CLibrary.INSTANCE;
        System.out.println("Handle: "+ptrRef);
        String sPath = "C:\\Users\\markm\\IdeaProjects\\JFrameHandle\\Release";
        cl.clStart(ptrRef, sPath, true);

    }

}

CL 库接口:

    public interface CLibrary extends Library {
         Clibrary INSTANCE = (CLibrary) Native.loadLibrary("C:\\Users\\markm\\IdeaProjects\\JFrameHandle\\Release\\clibrary",CLibrary.class);
         void clStart(HWND parent, String libraryPath, boolean hidePanel);
}

不幸的是,我无法访问 C 代码,因为我只有 .dll 文件,但在我可以访问该代码之前,我需要知道我是否做错了什么。如果有人可以为我指出如何使用窗口句柄的正确方向,或者可能有一种方法可以在另一端通过 JNI 传递句柄,请发表评论,我可以使用我能获得的所有帮助。

提前致谢。

【问题讨论】:

  • 这个 C 库到底在做什么,它应该直接操作托管运行时拥有的 GUI 窗口?
  • 由于您使用的是 dll,因此您有效地绑定了 Windows 操作系统。重写的意义何在?
  • @chrylis - C 库在主窗口上放置了一个“窗口”。这就是为什么我试图将主窗口的句柄传递给库,以便它具有点引用
  • @Amit - 我知道这可能很奇怪,但有必要证明它也可以在 java 中完成。我是学生,这是一项作业,所以对不起,我不能就这个问题争论。
  • 我必须使用用 C 语言编写的同一个库。 谁说的? 为什么?这个 C 库是为在 C# 创建的窗口上工作而编写的?有人认为它在 Java 创建的窗口上也能正常工作吗?福特皮卡的零件可以在丰田普锐斯上使用吗?听起来你被赋予了一项不可能完成的任务。

标签: java c java-native-interface jna window-handles


【解决方案1】:

Invalid Memory Access 错误表明您没有为传递给函数的任何指针分配本机端内存。由于 String 和 boolean 不是问题,您知道传递 HWND 不是正确的映射。

没有看到 C API,我只能猜测,但根据您对它的描述,它采用 IntPtr,它期望本机地址为整数(intlong,取决于 32 位或 64 位)。

我怀疑您需要将接口映射更改为longint 并将Pointer.nativeValue(HWND.getPointer()) 传递给它。 (或者简化您的代码以绕过HWND 存储,并简单地最初使用Pointer.nativeValue(Native.getComponentPointer(jFrame)) 获取整数。)

【讨论】:

  • 感谢您的意见。我刚刚尝试了您的解决方案,这对我来说很有意义,因为 C# 代码给出了相似的值,但它仍然给出了相同的异常。我还尝试给它一个 IntByReference,我发现它与 Java 中的 IntPtr 等效,但结果仍然相同。我开始怀疑 String 参数是问题所在。有人告诉我,编码(UTF-8 与 UTF-16)可能存在差异,但我不确定该怎么做。
  • 你能链接到你的 dll 文档吗?
  • 不幸的是,我没有任何文档。我将很快获得有关 dll 的更多信息。我也会要求提供文件。我知道没有文档很奇怪,但任务是关于分析代码并能够提取并使用另一种语言创建另一个版本的代码。此外,该 dll 现在是私有财产,所以我必须非常小心地显示什么(这就是为什么该库被称为 CLibrary。试图非常通用)。很抱歉,如果很难提供帮助。
  • 那么 clStart() 的 C 方法签名怎么样? :)
  • 我会继续向clStart 抛出各种类型的整数。也许NativeLong。您可以传递一个指针而不是字符串,使用String.getBytes("UTF-16") 来获取一个字节数组,使用该长度加一来初始化一个新的Memory 对象,然后使用Memory.write() 填充缓冲区。不要忘记在末尾添加一个 0 字节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
相关资源
最近更新 更多