2016-04-25 6 views
0

für mein gegenwärtiges Projekt muss ich etwas C++ Code von meiner Java-Anwendung benutzen. Es scheint mir, dass die übliche Lösung darin besteht, eine DLL aus dem C++ Teil zu erstellen und über JNA darauf zuzugreifen. Da ich ein absoluter Anfänger bin, wenn es um C++ geht, gehe ich davon aus, dass ich mit einer minimalen Basis anfange und von dort weiter arbeite. Allerdings kann ich diese minimalen Beispiele nicht einmal zum Laufen bringen. Hier ist, was ich getan habe:JNA und C++ - Minimalistic Beispiel resultierend in UnatisfiedLinkError

Ich benutzte Dokumentation für Visual Studio meine DLL zu erstellen (hier: https://msdn.microsoft.com/de-de/library/ms235636.aspx)

Was Sie tun, ist, dass Sie einen Header

// MathFuncsDll.h 

#ifdef MATHFUNCSDLL_EXPORTS 
#define MATHFUNCSDLL_API __declspec(dllexport) 
#else 
#define MATHFUNCSDLL_API __declspec(dllimport) 
#endif 
namespace MathFuncs 
{ 
// This class is exported from the MathFuncsDll.dll 
class MyMathFuncs 
{ 
public: 
    // Returns a + b 
    static MATHFUNCSDLL_API double Add(double a, double b); 
}; 
} 

und eine CPP definieren Datei

// MathFuncsDll.cpp : Defines the exported functions for the DLL application. 

#include "stdafx.h" 
#include "MathFuncsDll.h" 
#include <stdexcept> 

using namespace std; 

namespace MathFuncs 
{ 
double MyMathFuncs::Add(double a, double b) 
{ 
    return a + b; 
} 
} 

Und dann bauen Sie es in eine DLL. Bisher hat das ohne Fehler funktioniert. Ich ging dann ein kleines Java-Programm zu schreiben, um diese DLL über JNA zugreifen zu können, wieder an die JNA Dokumentation kleben:

import com.sun.jna.Library; 
import com.sun.jna.Native; 
import com.sun.jna.Platform; 

/** Simple example of JNA interface mapping and usage. */ 
public class HelloWorld { 

    // This is the standard, stable way of mapping, which supports extensive 
    // customization and mapping of Java to native types. 

    public interface CLibrary extends Library { 
     CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "zChaffDLL" : "c"), CLibrary.class); 

     double Add(double a, double b); 
    } 

    public static void main(String[] args) { 
     CLibrary.INSTANCE.Add(5d, 3d); 

    } 
} 

Lauf dies führt zu diesem Fehler: Exception in thread "main" java.lang.UnsatisfiedLinkError : Fehler beim Aufrufen der Funktion 'Hinzufügen': Die angegebene Prozedur wurde nicht gefunden.

Ich bastelte etwas herum, aber konnte das Problem nicht lösen. An diesem Punkt bin ich ziemlich verloren, da ich mich nicht in der Lage sehe, ein noch einfacheres Beispiel zu konstruieren - also würde jede Hilfe oder Hinweise wirklich geschätzt werden.

+0

C++ und C haben unterschiedliche Schnittstellen (ABIs), die Tatsache, dass Sie eine C++ - Bibliothek mit dem Typ '' 'CLibrary''' laden, erscheint mir schon verdächtig. Siehe auch: [Java Native Access macht nicht C++, oder?] (Http://stackoverflow.com/questions/2241685/java-native-access-doesnt-do-c-right). Sie könnten besser JNI stattdessen verwenden, obwohl es ein bisschen mehr Arbeit ist. –

Antwort

0

C++ "Mangles" exportiert Namen nach den Launen des Compilers. Zum Beispiel könnte "void main (argc, argv)" als "_Vmain_IPP @ xzyzzy" ausgegeben werden.

Führen Sie in Ihrer DLL depends.exe aus, um zu sehen, wie die exportierten Namen aussehen. extern "C" in Ihrem Code wird verhindern, dass C++ exportierte Funktionsnamen beschädigt.

JNA behandelt statische Funktionen ganz gut; JNAerator nimmt einige zusätzliche Mangels automatisch auf, aber wenn Sie C++ - Klassen auf Java-Klassen abbilden wollen, sind Sie besser mit etwas wie SWIG vertraut.

+0

Ich habe versucht, extern "C" zu verwenden, aber es hat nicht geholfen. depends.exe zeigt die korrekten Funktionsnamen, hat aber ein? vor ihnen. Bis jetzt konnte ich nicht herausfinden, warum das – dhyr

+0

ist Zeigen Sie die aktualisierte Quelle und die depends.exe Ausgabe in Ihrer Frage. – technomage