1. Dashboard
  2. Forum
    1. Unerledigte Themen
  3. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team-Mitglieder
    4. Trophäen
    5. Mitgliedersuche
  4. Tutorial Bereich
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  • Alles
  • Dieses Thema
  • Dieses Forum
  • Seiten
  • Forum
  • Lexikon
  • Erweiterte Suche
  1. Informatik Forum
  2. Webmaster & Internet
  3. Entwicklung

Problem mit JNI

  • Stephe
  • 30. September 2008 um 20:15
  • Unerledigt
  • Stephe
    24
    Stephe
    Mitglied
    Reaktionen
    43
    Punkte
    6.038
    Beiträge
    968
    • 30. September 2008 um 20:15
    • #1

    Ich versuche gerade in Java auf eine DLL zuzugreifen, die wiederum auf eine fertige DLL zugreift.
    Dazu habe ich die üblichen Schritte getan: Java-Klasse mit nativen Methoden schreiben, kompilieren, JNI-Headerdatei erstellen, DLL mit VC++ 2005 erstellen. Alles ließ sich fein kompilieren, und jetzt beim Testen gibts ein Problem:

    Zitat

    Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: DMX.DMXController.startDevice()V
    at DMX.DMXController.startDevice(Native Method)

    Ich rufe zuerst init() auf, da passt noch alles. Erst beim aufrufen von startDevice() kommt die Fehlermeldung.
    Die Java-Klasse:

    Code
    public class DMXController
    {
        public static native void startDevice();
        public static native void setData(long Channel, long Data);
        public static native void setChannelCount(long Count);
        public static native void stopDevice();
    
        public static void init()
        {
            System.load(System.getProperty("user.dir")+"/light.dll");
        }
    }
    Alles anzeigen

    Die Header-Datei aus der JNI Kompilierung:

    C
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include "jni.h"
    /* Header for class DMXController */
    
    
    #ifndef _Included_DMXController
    #define _Included_DMXController
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     DMXController
     * Method:    startDevice
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_DMXController_startDevice
      (JNIEnv *, jclass);
    
    
    /*
     * Class:     DMXController
     * Method:    setData
     * Signature: (JJ)V
     */
    JNIEXPORT void JNICALL Java_DMXController_setData
      (JNIEnv *, jclass, jlong, jlong);
    
    
    /*
     * Class:     DMXController
     * Method:    setChannelCount
     * Signature: (J)V
     */
    JNIEXPORT void JNICALL Java_DMXController_setChannelCount
      (JNIEnv *, jclass, jlong);
    
    
    /*
     * Class:     DMXController
     * Method:    stopDevice
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_DMXController_stopDevice
      (JNIEnv *, jclass);
    
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    Alles anzeigen


    Die Header-Datei light.h:

    C
    // light.h : Hauptheaderdatei für die light-DLL
    //
    
    
    #pragma once
    
    
    #ifndef __AFXWIN_H__
        #error "'stdafx.h' vor dieser Datei für PCH einschließen"
    #endif
    
    
    #include "resource.h"        // Hauptsymbole
    #include <windows.h>
    #include <tchar.h>
    #include "DMXController.h"
    
    
    
    
    // ClightApp
    // Siehe light.cpp für die Implementierung dieser Klasse
    //
    
    
    class ClightApp : public CWinApp
    {
       typedef void (__stdcall *PFNSTARTDEVICE)();
       typedef void (__stdcall *PFNSETDATA)(DWORD dwChannel, DWORD dwData);
       typedef void (__stdcall *PFNSETCHANNEL)(DWORD dwCount);
       typedef void (__stdcall *PFNSTOPDEVICE)();
    
    
    public:
        ClightApp();
        ~ClightApp();
        PFNSTARTDEVICE StartDevice;
        PFNSETDATA SetData;
        PFNSETCHANNEL SetChannelCount;
        PFNSTOPDEVICE StopDevice;
    
    
    
    
    // Überschreibungen
    public:
        virtual BOOL InitInstance();
    
    
        DECLARE_MESSAGE_MAP()
    
    
    JNIEXPORT void JNICALL Java_DMXController_startDevice(JNIEnv *env, jclass c);
    JNIEXPORT void JNICALL Java_DMXController_setData(JNIEnv *env, jclass c, jlong channel, jlong data);
    JNIEXPORT void JNICALL Java_DMXController_setChannelCount(JNIEnv *env, jclass c, jlong count);
    JNIEXPORT void JNICALL Java_DMXController_stopDevice(JNIEnv *env, jclass c);
    
    
    
    
    private:
        HMODULE hLib;
    };
    Alles anzeigen

    und die light.cpp-Datei:

    C
    // light.cpp : Definiert die Initialisierungsroutinen für die DLL.
    //
    
    
    #include "stdafx.h"
    #include "light.h"
    
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    
    //
    //TODO: Wenn diese DLL dynamisch mit MFC-DLLs verknüpft ist,
    //        muss für alle aus dieser DLL exportierten Funktionen, die in
    //        MFC aufgerufen werden, das AFX_MANAGE_STATE-Makro
    //        am Anfang der Funktion hinzugefügt werden.
    //
    //        Beispiel:
    //
    //        extern "C" BOOL PASCAL EXPORT ExportedFunction()
    //        {
    //            AFX_MANAGE_STATE(AfxGetStaticModuleState());
    //            // Hier normaler Funktionsrumpf
    //        }
    //
    //        Es ist sehr wichtig, dass dieses Makro in jeder Funktion
    //        vor allen MFC-Aufrufen angezeigt wird. Dies bedeutet,
    //        dass es als erste Anweisung innerhalb der 
    //        Funktion angezeigt werden muss, sogar vor jeglichen Deklarationen von Objektvariablen,
    //        da ihre Konstruktoren Aufrufe in die MFC-DLL generieren
    //        könnten.
    //
    //        Siehe Technische Hinweise für MFC 33 und 58 für weitere
    //        Details.
    //
    
    
    
    
    // ClightApp
    
    
    BEGIN_MESSAGE_MAP(ClightApp, CWinApp)
    END_MESSAGE_MAP()
    
    
    
    
    // ClightApp-Erstellung
    
    
    ClightApp::ClightApp()
    {
        hLib = LoadLibrary(_T("K8062d.dll"));
        StartDevice = (PFNSTARTDEVICE)GetProcAddress(hLib, "StartDevice");
        SetData = (PFNSETDATA)GetProcAddress(hLib, "SetData");
        SetChannelCount = (PFNSETCHANNEL)GetProcAddress(hLib, "SetChannelCount");
        StopDevice = (PFNSTOPDEVICE)GetProcAddress(hLib, "StopDevice");
    }
    
    
    ClightApp::~ClightApp()
    {
        FreeLibrary(hLib);
    }
    
    
    // Das einzige ClightApp-Objekt
    
    
    ClightApp theApp;
    
    
    
    
    // ClightApp-Initialisierung
    
    
    BOOL ClightApp::InitInstance()
    {
        CWinApp::InitInstance();
    
    
        return TRUE;
    }
    
    
    JNIEXPORT void JNICALL Java_DMXController_startDevice(JNIEnv *env, jclass c)
    {
        ClightApp app;
        app.StartDevice();   
    }
    
    
    JNIEXPORT void JNICALL Java_DMXController_setData(JNIEnv *env, jclass c, jlong channel, jlong data)
    {
        ClightApp app;
        app.SetData(channel, data);
    }
    
    
    JNIEXPORT void JNICALL Java_DMXController_setChannelCount(JNIEnv *env, jclass c, jlong count)
    {
        ClightApp app;
        app.SetChannelCount(count);
    }
    
    
    
    
    JNIEXPORT void JNICALL Java_DMXController_stopDevice(JNIEnv *env, jclass c)
    {
        ClightApp app;
        app.StopDevice();  
    }
    Alles anzeigen

    Die DLL wird gefunden, denn wenn ich für System.load() einen anderen Parameter angeb, schreit er. Auch wenn ich statt .load() .loadLibrary() verwend und die DLL ins system32-Verzeichnis kopier, kommt dasselbe raus.

    Was kann da nicht stimmen?

    5 Mal editiert, zuletzt von Stephe (30. September 2008 um 20:27)

  • Ringding
    11
    Ringding
    Mitglied
    Reaktionen
    12
    Punkte
    1.237
    Beiträge
    244
    • 30. September 2008 um 21:53
    • #2

    Kann es sein, dass deine DLL noch andere DLLs braucht, die das Java nicht im Pfad hat? Die VC2005 dlls sollten ja eigentlich im Pfad sein, wenn du's installiert hast, aber schau mal genau nach, ob's vielleicht daran liegt. Der Rest sieht eigentlich recht vernünftig aus.

  • Stephe
    24
    Stephe
    Mitglied
    Reaktionen
    43
    Punkte
    6.038
    Beiträge
    968
    • 1. Oktober 2008 um 09:33
    • #3

    Hab das Problem gelöst. Die Java-Klasse ist in einem Package, und dieses Package muss in den JNIEXPORT-Signaturen auch angegeben werden.

    2 Mal editiert, zuletzt von Stephe (1. Oktober 2008 um 09:42)

  • Ringding
    11
    Ringding
    Mitglied
    Reaktionen
    12
    Punkte
    1.237
    Beiträge
    244
    • 1. Oktober 2008 um 11:05
    • #4

    Die Übersetzung "einschließen" für #include gefällt mir :D. Waahhhhhhhhh!

  • Maximilian Rupp 27. Dezember 2024 um 12:04

    Hat das Thema aus dem Forum Programmieren nach Entwicklung verschoben.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!

Benutzerkonto erstellen Anmelden

Benutzer online in diesem Thema

  • 1 Besucher

Rechtliches

Impressum

Datenschutzerklärung