将DLL包装到Java中

时间:2012-06-21 17:23:56

标签: java c++ swig jna

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

我打算使用JNA,但它只适用于C,我无法看到如何使用C中的Observer模式执行此操作。我已经研究过使用BridJ和SWIG(两者都使用cliam来处理C ++ DLL)创建一个编译的dll接口(与相关的头文件),但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方。

1 个答案:

答案 0 :(得分:2)

听起来你正在寻找SWIG的directors feature。在最简单的形式中,您可以通过提供如下界面文件来使用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

这将生成三个Java类:MyModuleMyModuleJNIObserver。其中MyModule将包含头文件中的所有自由函数,公开为static成员函数,因为Java没有自由函数这样的东西。您可以放心地忽略MyModuleJNI - 它是SWIG生成的用于将MyModule连接到真正的C ++实现的粘合剂。您需要为MyModuleJNI编译mymodule_wrap.cxx(因此MyModule)才能正常工作,并在调用任何函数之前使用System.loadLibrary加载DLL。

Observer类直接对应mydll.h中的Observer接口。您应该使用Java派生它并覆盖frobinate函数,为其提供您自己的实现:

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界面文件。

如果您的真实头文件很简单,那么获得相同结果应该很简单。如果它更复杂,你可以用各种方式指示SWIG特殊情况下的一些包装。