Оберните DLL в Java

У меня есть код для связи с аппаратным устройством в Windows, которое работает на C++. Код делает что-то довольно простое, чтобы реагировать на нажатие кнопки на устройстве, и я скомпилировал это в dll с наблюдателем, который вызывается при нажатии кнопки. Теперь мне нужно связать это с большой программой Java.

Я собирался использовать JNA, но он работает только с C, и я не вижу, как это сделать с шаблоном Observer в C. Я изучил использование BridJ и SWIG (оба из которых предназначены для работы с DLL C++) для создания интерфейс к скомпилированной dll (со связанным файлом заголовка), но BridJ создает огромное количество файлов (в JNAeratorStudio), а затем останавливается с ошибкой, и я не вижу, как начать работу в Windows с помощью SWIG (я использую Visual Studio Express, а не чем полная Visual Studio).

Кто-нибудь знает учебник по интеграции DLL C ++ с программой 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.


person Neil Benn    schedule 21.06.2012    source источник
comment
Наблюдатель называется обратным вызовом в SWIG. Найдите его на сайте SWIG. Удачи тебе.   -  person J-16 SDiZ    schedule 21.06.2012
comment
Я собирался использовать JNA: он называется JNI. И вам не нужно перекодировать сторону C++, чтобы использовать его. Вам необходимо создать интерфейс, совместимый с JNI, для существующей функциональности — вот и все.   -  person paulsm4    schedule 21.06.2012
comment
Я сгенерировал классы в SWIG, которые выглядят разумно, но нет никакой связи между классами и моей dll!   -  person Neil Benn    schedule 21.06.2012
comment
Нет, я имел в виду JNA: github.com/twall/jna. Для JNI мне нужно было бы написать что-то, чтобы интерпретировать вызовы JNI для моих вызовов C++. Если я собираюсь это сделать, я могу также написать оболочку C и использовать JNA.   -  person Neil Benn    schedule 21.06.2012
comment
Обратные вызовы JNA позволяют вам предоставлять собственный код с указателем функции, который отображается обратно в вызов метода Java. Вам нужно будет предоставить функцию глобального регистра из вашего собственного кода, которая установит указатель функции, который будет вызываться вашим наблюдателем. Затем JNA может вызвать функцию регистрации с помощью объекта обратного вызова на основе Java.   -  person technomage    schedule 25.06.2012


Ответы (1)


Похоже, вы ищете функции директоров от SWIG. В простейшей форме вы можете использовать директоры с 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: MyModule, MyModuleJNI и Observer. Из них MyModule будут содержать все свободные функции из вашего заголовочного файла, представленные как static функций-членов, поскольку в Java нет таких вещей, как свободные функции. Вы можете смело игнорировать MyModuleJNI - это клей, созданный SWIG для соединения MyModule с реальными реализациями C++. Вам нужно будет скомпилировать mymodule_wrap.cxx для MyModuleJNI (и, следовательно, MyModule), чтобы он работал правильно, и загрузить DLL с помощью System.loadLibrary, прежде чем вызывать какие-либо функции из них.

Класс Observer напрямую соответствует интерфейсу Observer в mydll.h. Вы должны получить его в 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 для особого случая некоторые из его оберток различными способами.

person Flexo    schedule 22.06.2012