6 Stimmen

Rückrufe von C++ zurück nach Java

Ich habe das Folgende für numerische Integration in C++ programmiert:

// integrate.h:
#ifdef BUILDING_DLL
#define  DLL_MACRO __declspec(dllexport)
#else
#define  DLL_MACRO __declspec(dllimport)
#endif

extern "C" {
  typedef double (*Function1VariablePtr)(double x);
  double DLL_MACRO integrate(Function1VariablePtr function, double min, double max);
}

// integrate.cpp: 
#include "integrate.h"
double integrate(Function1VariablePtr function, double min, double max) {
  const int n = 1001;
  double dx  = (max - min)/(1.0*(n - 1));
  double sum = 0.0;
  for(int i = 0; i < n; i++) {
    double xmid = min + (i + 0.5)*dx;
    sum += function(xmid)*dx;
  }
  return sum;
}

Nun möchte ich diese Funktion von Java aus aufrufen. Ich habe herausgefunden, wie ich die Integration direkt in den JNI-"Bridge"-Code implementieren kann:

// C++ "bridge" code to from/to Java:  
JNIEXPORT jdouble JNICALL 
Java_IntegrateJApp_JIntegrate(JNIEnv *jnienv, jclass jc,    
                              jdouble xmin, jdouble xmax) {
  jmethodID mid = jnienv->GetStaticMethodID(jc, "Function1D","(D)D");
  if (mid == 0)
    return - 1.0;
  const int n = 1001;
  double dx  = (xmax - xmin)/(1.0*(n - 1));
  double sum = 0.0;
  for(int i = 0; i < n; i++) {
    double xmid = xmin + (i + 0.5)*dx;
    double f = jnienv->CallStaticDoubleMethod(jc, mid, xmid);
    sum += f*dx;
  }
  return sum;
}

// Java code calling "bridge":
class IntegrateJApp { 
  public static void main(String[] args) { 
      System.loadLibrary("JIntegrate");
      double I = JIntegrate(0.0, 2*Math.PI);
      System.out.println( Double.toString(I) ); 
  } 
  public static double Function1D(double x) {
      return Math.sin(x);
  }
  public static native double JIntegrate(double xmin, double xmax);
} 

Ich möchte jedoch die numerische Integration nicht direkt im C++-Brückencode implementieren, sondern den Code in integrate.cpp aufrufen.

Wie kann ich das tun? Die Funktion integrate() in integrate.cpp erfordert einen Funktionszeiger, den ich nicht habe. Gibt es eine Möglichkeit, mit JNI einen Zeiger auf eine Funktion in Java zu erhalten?

Vielen Dank im Voraus für alle Antworten!

3voto

RamonBoza Punkte 8681

Sie müssen eine DLL mit Ihrem C++-Code erstellen und diese über JNI aufrufen

Laden Sie die DLL:

System.loadLibrary("PATH\\yourdllname.dll");

Erstellen des Links zu Ihrer Funktion

public static native integrate(parameters);

2voto

Nick Punkte 5705

Eine Möglichkeit, dies zu tun, ist die Verwendung eines Zeigers auf eine Mitgliedsfunktion und die Änderung der Signatur der Integrationsfunktion.

Siehe unten die allgemeine Idee:

functionwrapper.h

Deklarieren Sie eine Funktionsverschalungsklasse.

class FunctionWrapper
{
public:
    typedef double (FunctionWrapper::*Function1VariablePtr)(double x);

    FunctionWrapper(JNIEnv*, jclass);
    double compute(double x);
};

integrieren.h

Beseitigen Sie den vorherigen Zeiger auf den Funktionstyp und ändern Sie die Methodensignatur so, dass sie das Wrapper-Objekt und einen Zeiger auf seine Mitgliedsfunktion enthält.

#include "functionwrapper.h"
extern "C" {
    double DLL_MACRO integrate(FunctionWrapper*, FunctionWrapper::Function1VariablePtr, double min, double max);
}

integrieren.cpp

Ändern Sie den Funktionsaufruf in einen Aufruf einer Mitgliedsfunktion.

#include "integrate.h"
double integrate(FunctionWrapper* wrapper, FunctionWrapper::Function1VariablePtr function, double min, double max)
{
    // ...
    sum += (wrapper->*function)(xmid)*dx;
    // ...
}

Summe zurückgeben; }

JNI "Brücken"-Code:

Definieren Sie den Wrapper-Code und definieren Sie die Funktion, die den eigentlichen Aufruf durchführt. Rufen Sie die integrate Funktion direkt von der JNI-Funktion:

#include "functionwrapper.h"

FunctionWrapper::FunctionWrapper(JNIEnv *jnienv, jclass jc) : m_jnienv(jnienv), m_jc(jc) {
    m_method= jnienv->GetStaticMethodID(jc, "Function1D","(D)D");
}

double FunctionWrapper:compute(double x) {
    return m_jnienv->CallStaticDoubleMethod(m_jc, m_method, x);;
}

// C++ "bridge" code to from/to Java:
JNIEXPORT jdouble JNICALL
Java_IntegrateJApp_JIntegrate(JNIEnv *jnienv, jclass jc,
                              jdouble xmin, jdouble xmax) {
    FunctionWrapper wrapper(jnienv, jc);
    return integrate(&wrapper, &FunctionWrapper::compute, 2, 3);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X