And*_*ndy 6 c++ java java-native-interface
我已经编写了以下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;
}
Run Code Online (Sandbox Code Playgroud)
现在我想从Java调用这个函数.我发现如何直接在JNI"桥"代码中实现集成:
// 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);
}
Run Code Online (Sandbox Code Playgroud)
但是,我不想直接在C++桥代码中实现数值集成,而是在integrate.cpp中调用代码.
我该怎么做呢?integrate.cpp中的integrate()函数需要一个我没有的函数指针.有没有办法使用JNI获取Java内部函数的指针?
提前感谢您的任何答案!
一种方法是使用指向成员函数的指针并更改集成函数的签名。
总体思路如下:
函数包装器.h
声明一个函数包装类。
class FunctionWrapper
{
public:
typedef double (FunctionWrapper::*Function1VariablePtr)(double x);
FunctionWrapper(JNIEnv*, jclass);
double compute(double x);
};
Run Code Online (Sandbox Code Playgroud)
集成.h
消除先前指向函数 typedef 的指针,并更改方法签名以包含包装器对象和指向其成员函数的指针。
#include "functionwrapper.h"
extern "C" {
double DLL_MACRO integrate(FunctionWrapper*, FunctionWrapper::Function1VariablePtr, double min, double max);
}
Run Code Online (Sandbox Code Playgroud)
集成.cpp
将函数调用更改为成员函数调用。
#include "integrate.h"
double integrate(FunctionWrapper* wrapper, FunctionWrapper::Function1VariablePtr function, double min, double max)
{
// ...
sum += (wrapper->*function)(xmid)*dx;
// ...
}
Run Code Online (Sandbox Code Playgroud)
返回总和;}
JNI“桥”代码:
定义包装器代码并定义执行实际调用的函数。integrate直接从 JNI 函数调用该函数:
#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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1581 次 |
| 最近记录: |