java - 将 DLL 包装成 Java

标签 java c++ swig jna

我有一些代码可以与使用 C++ 的 Windows 上的硬件设备通信。代码做了一些非常简单的事情来对设备上的按钮按下使用react,我将它编译成一个 dll,并带有一个观察器,当按下按钮时调用该观察器。我现在需要将它与一个大型 Java 程序连接起来。

我打算使用 JNA,但它只适用于 C,我看不出如何使用 C 中的观察者模式来做到这一点。我已经研究过使用 BridJ 和 SWIG(两者都适用于 C++ DLL)为已编译的 dll(带有关联的头文件)创建一个接口(interface),但 BridJ 创建了大量文件(在 JNAeratorStudio 中),然后因错误而停止,我看不到如何使用 SWIG 在 Windows 上开始(我正在使用 Visual Studio Express 而不是完整的 Visual Studio)。

有没有人知道有关将 C++ DLL 与 Java 程序集成的教程 - SWIG 看起来很有前途,但教程很“乏味”。

我放了一些简单的 C 代码来与下面的 DLL 对话:

#include <iostream>
#include <stdio.h>

#include "DeepFocusControlDll.h"

using namespace std;
using namespace DeepFocusControl;

class MyObserver : public DeepFocusControl::DeepFocusObserver{
    void Event(){
        printf("***Button Pushed***");
    }
};

int main()
{
    DeepFocusControl::AVA6Control* dfc = new DeepFocusControl::AVA6Control();
    MyObserver* observer = new MyObserver();
    dfc->AddObserver(observer);
    bool connected = dfc->IsConnected();
    printf("Connected %s\n", (connected)?"true":"false");
    bool connectresult = dfc->Connect();
    printf("Connecting %s\n", (connectresult)?"true":"false");
    connected = dfc->IsConnected();
    printf("Connected %s\n", (connected)?"true":"false");
    dfc->SetHardwareAppLaunch(false);
    char waitChar;
    cin >> waitChar;
    dfc->SetHardwareAppLaunch(true);
    dfc->RemoveObserver(observer);
    dfc->Disconnect();
    printf("Disconnected\n");
    cin >> waitChar;
}

如果有人知道在这上面使用观察者模式的更简单方法,我也可以很高兴地重新编写 C 端代码。

最佳答案

听起来您正在寻找 SWIG 的 directors feature .在最简单的形式中,您可以通过提供如下接口(interface)文件来将 Controller 与 SWIG 结合使用:

%module(directors=1) MyModule
%feature("director");         

%{
#include "mydll.h"
%}

%include "mydll.h"

给定一个头文件“mydll.h”:

class Observer {
public:
  virtual void frobination() = 0;
  virtual ~Observer() {}
};

inline void bar(Observer *o) {
  o->frobination();
}

然后你可以运行 SWIG:

swig -Wall -java -c++ mymodule.i

This will generate three Java classes: MyModule, MyModuleJNI and Observer. Of these MyModule will contain all the free functions from your header file, exposed as static member functions since Java has no such thing as free functions. You can safely ignore MyModuleJNI - it's glue generated by SWIG for connecting MyModule to the real C++ implementations. You'll need to compile mymodule_wrap.cxx for MyModuleJNI (and hence MyModule) to work correctly though and load the DLL using System.loadLibrary before you call any functions from them.

The Observer class directly corresponds to the Observer interface in mydll.h. You should derive from it in Java and override the frobinate function to give it your own implementation:

public class Test extends Observer {
  @Override
  public void frobination() {
    System.out.println("go go gadget frobinator");
  }

  public static void main(String[] argv) {
    System.loadLibrary("mymodule");
    Test t = new Test();
    MyModule.bar(t);    
  }
}

我可以编译并运行它来完全按照您的希望去做。

如果您愿意,可以通过添加以下内容自动调用 System.loadLibrary:

%pragma(java) jniclasscode=%{
  static {
    try {
        System.loadLibrary("mymodule");
    } catch (UnsatisfiedLinkError e) {
      System.err.println("Native code library failed to load. \n" + e);
      System.exit(1);
    }
  }
%}

到您的 SWIG 接口(interface)文件。

如果您的真实头文件如此简单,那么获得相同结果也应该如此简单。如果它更复杂,您可以指示 SWIG 以各种方式对它的某些包装进行特殊处理。

关于java - 将 DLL 包装成 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11143460/

相关文章:

swig - 为 Openwrt 交叉编译 Gnu Radio

java - 在 java 类上生成 C++ 包装器的工具

java - 将 Jarbundler 与 ant 一起使用

c++ - 为什么 std::is_same 不起作用?

c++ - 优化: Hackerearth Postman Software engineer intern question

c++ - 创建随机迭代器(排列)

python - SWIG 如何包装缓冲区(字符数组)和从 C 到 Python 的指针?

java - Hazelcast 分布式 map 处理器在单个节点上执行

java - Spring Boot + JavaFx Autowiring 不起作用

java - 如何消除模拟器启动错误