6

I have coded the following for numerical integration in C++:

// 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;
}

Now I want to call this function from Java. I found how I can implement the integration directly in the JNI "bridge" code:

// 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);
} 

However I do not want to implement the numeric integration directly in the C++ bridge code, but rather call the code in integrate.cpp.

How do I do this? The integrate() function inside integrate.cpp requires a function pointer which I do not have. Is there a way to get a pointer to a function inside Java using JNI?

Thanks in advance for any answers!

2
  • So you're actually asking about how to link your C++ JNI wrapper with an existing library Commented Jun 17, 2011 at 9:10
  • Yes that is right. The complication is that the function inside the existing library requires a function pointer. How do I get a pointer to a function inside Java? Commented Jun 17, 2011 at 9:25

2 Answers 2

3

You have to create a DLL with your C++ code and call it from JNI

Load the DLL:

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

Creating the link to your function

public static native integrate(parameters);
Sign up to request clarification or add additional context in comments.

5 Comments

Yes I can create a dll from integrate.cpp: integrate.dll. Next I can call this dll from the "bridge": JNIintegrate.dll. But the integrate function in my integrate.cpp needs a function pointer. How can I get a function pointer inside the "bridge" code that I can pass to integrate()?
path\\yourdllname.dll? Why, you must mean path/yourlibname.so! Funny how cross-platform this java stuff is ... I guess JNI is the one place where I can forgive them for letting that lapse.
Is an example, you can use .dll, .so or nothing, but for better understanding i used it, that's a problem? :P
Answer irrelevant -- person is asking about invoking static library from the C++ JNI interface
why do people like the answer, the question is virtually only about c++ (not java)
2

One way that can be done is by using a pointer to member function and changing the signature of the integrate function.

See below the general idea:

functionwrapper.h

Declare a function wrapper class.

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

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

integrate.h

Eliminate the previous pointer to function typedef and change the method signature to include the wrapper object and a pointer to its member function.

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

integrate.cpp

Change the function invocation to a member function invocation.

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

return sum; }

JNI "bridge" code:

Define the wrapper code and define the function that does the actual invocation. Invoke the integrate function directly from the JNI function:

#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);
}

4 Comments

Thanks Nick! However to me it seems like you are declaring FunctionWrapper twice? I tried instead with an abstract base class: IFunctionWrapper and a JNI implementation of this: JFunctionWrapper. I then called integrate(jfw, (IFunctionWrapper::Function1VariablePtr) &JFunctionWrapper::compute, xmin, xmax); This approach also worked.
Yes, you are right -- the class was declared twice -- I will fix this (too many files)
The call (wrapper->*function)(xmid) was very surprising to me. I did not know this was possible. In fact you invoke a pointer to a member function on an object?
Exactly! You basically pass the member function and the object to which it is applied.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.