首页 > 解决方案 > Java 进程通过 JNA 从一个非常复杂的 C++ Win32 DLL 调用方法,其中包含大量类

问题描述

我有一个由其他部门的开发人员用 C++ 为 Win32 编写的非常复杂且大的 DLL,我的 java 进程需要使用它。我有的:

限制:我不允许(尽管我有一个 .sol 文件)对该 DLL 进行任何更改。

目标:我希望我的 java 进程能够从这个 DLL 调用一些方法。

Instruments:首先我想用 JNA(第二个和 JNI)来试试。

问题:

我阅读了一些有关 JNA 的一般信息并理解,首先您要构建要在接口中调用的方法的原型。好的,现在的问题如下:我要调用的方法,将DLL项目中的自定义对象作为参数。例如,我在 DLL 中有一个函数,例如:

__declspec(dllexport) BOOL WINAPI NiceFunction( 
          Dummy_State *ModuleState, Dummy_Handle Handle, Dummy_Exception &Exception,
          LPCTSTR name, DWORD timer);

所有Dummy_对象都属于类,在此 DLL 中定义。

问题1:如何在我的java进程中用JNA调用这样的函数?

问题 2:是否可以在我的 java 进程中以某种方式直接使用这些对象?也许以某种方式导入构造函数?然而,这些对象的构造函数经常需要调用父类的构造函数。

问题 3:最后但同样重要的是,我的 DLL 还调用了两个额外的 DLL,并广泛使用了来自它们的数据(一些Dummy_对象)。我是否还需要通过 JNA 在我的 java 进程中导入(以某种方式)它们?

标签: javac++dlljna

解决方案


JNA 仅适用于 C 函数,不适用于 C++。您可以映射的唯一 C++ 函数必须已使用extern "C". 如果它们不是,并且您无法更改 DLL,则可能必须编写自己的具有extern "C"版本的 DLL 包装器。

如何使用 JNA 调用此类函数:

您必须将它们映射到 Java 接口。例如:

public interface ComplicatedAndBigLibrary {
    // Create an instance to access the mapped functions with
    // the String in quotes is the filename, minus .dll
    ComplicatedAndBigLibrary INSTANCE = 
        (ComplicatedAndBigLibrary) Native.load("compbiglib", W32APIOptions.DEFAULT_OPTIONS);

    // Map the C structures or typedefs
    // Use "extends" as needed for parents
    @FieldOrder({"field1", "field2"})
    class Dummy_State extends Structure {
        // map structure fields here
        public int field1;
        public byte field2;
    }

    class Dummy_Handle extends WinNT.HANDLE {
        // any overrides you need
    }

    // Map your functions (that were externalized)
    boolean NiceFunction( 
          Dummy_State ModuleState, Dummy_Handle Handle, Dummy_Exception ExceptionPointer,
          LPCTSTR name, DWORD timer);
}

查看软件包中的 JNA源代码,com.sun.jna.platform.win32了解基于 Windows DLL 的多种类型的示例。您实际上是在为您的 DLL 做同样的事情。

在我的 java 进程中以某种方式直接使用这些对象

ComplicatedAndBigLibrary CABL = ComplicatedAndBigLibrary.INSTANCE;
CABL.NiceFunction(foo, bar, ...)

也称为两个额外的 DLL,并广泛使用来自它们的数据

您需要类似地映射其他 DLL(创建接口,使用Native.load()和映射函数/常量/等)


推荐阅读