与java调用c/c++差不多。
1.在scala文件中对将要调用的方法做本地声明,关键字为native。且只需要声明,而不需要具体实现。
class MutiMatrix {
//xM
@native def vectorMutiMatrix(lx: Array[Double],rM:Array[Double]): Array[Double]
//Mx
@native def matrixMutiVector(lM: Array[Double], rx: Array[Double]): Array[Double]
//MM
@native def matrixMutiMatrix(lM: Array[Double],rM:Array[Double], k: Int): Array[Double]
//xMx'
@native def distance(x: Array[Double],M:Array[Double]): Double
}
2.调用scalac编译我们的scala类,获得class文件
scalac MutiMatrix.scala
3.使用javah命令来帮助生成这些方法的声明的头文件
SCALA_LIB_HOME=$SCALA_HOME/lib/生成的头文件为:
SCALA_CP=$SCALA_LIB_HOME/scala-library.jar:$SCALA_LIB_HOME/scala-reflect.jar
javah -cp $SCALA_CP:. MutiMatrix
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class MutiMatrix */
#ifndef _Included_MutiMatrix
#define _Included_MutiMatrix
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: MutiMatrix
* Method: vectorMutiMatrix
* Signature: ([D[D)[D
*/
JNIEXPORT jdoubleArray JNICALL Java_MutiMatrix_vectorMutiMatrix
(JNIEnv *, jobject, jdoubleArray, jdoubleArray);
/*
* Class: MutiMatrix
* Method: matrixMutiVector
* Signature: ([D[D)[D
*/
JNIEXPORT jdoubleArray JNICALL Java_MutiMatrix_matrixMutiVector
(JNIEnv *, jobject, jdoubleArray, jdoubleArray);
/*
* Class: MutiMatrix
* Method: matrixMutiMatrix
* Signature: ([D[DI)[D
*/
JNIEXPORT jdoubleArray JNICALL Java_MutiMatrix_matrixMutiMatrix
(JNIEnv *, jobject, jdoubleArray, jdoubleArray, jint);
/*
* Class: MutiMatrix
* Method: distance
* Signature: ([D[D)D
*/
JNIEXPORT jdouble JNICALL Java_MutiMatrix_distance
(JNIEnv *, jobject, jdoubleArray, jdoubleArray);
#ifdef __cplusplus
}
#endif
#endif
4.用C++将代码补充完整
其实现文件.cpp为:
#include "MutiMatrix.h"
//#include <iostream>
#include <string.h>
#include <stdlib.h>
//using namespace std;
JNIEXPORT jdoubleArray JNICALL Java_MutiMatrix_vectorMutiMatrix
(JNIEnv *env, jobject obj, jdoubleArray lxs, jdoubleArray rMs)
{
jsize xlen = env->GetArrayLength(lxs);
jsize Mlen = env->GetArrayLength(rMs);
jsize Mcol = Mlen/xlen;
jdouble* lx = env->GetDoubleArrayElements(lxs,0);
jdouble* rM = env->GetDoubleArrayElements(rMs,0);
jdoubleArray result = env->NewDoubleArray(Mcol);
jdouble* buff = new double[Mcol];
memset(buff,Mcol*sizeof(jdouble),0);
for(int i = 0; i< Mcol; i++){
for(int j = 0; j < xlen; j++){
buff[i] += lx[j]*rM[i*Mcol+j];
}
}
env->ReleaseDoubleArrayElements(lxs, lx, 0);
env->ReleaseDoubleArrayElements(rMs, rM, 0);
env->SetDoubleArrayRegion(result,0,Mcol,buff);
return result;
}
5.用g++生成.so文件
g++ -dynamiclib -shared -fPIC -I/usr/include -I$JAVA_HOME/include -I$JAVA_HOME/include/linux MutiMatrix.cpp -o libMutiMatrix.so
6.copy .so文件到scala代码目录下,并在VM arguments中加入该.so文件的路径
-Djava.library.path=/home/liujj/code/scala/testC++/
在run as 下的Run Configurations设置
7.测试
/**
* @author liujj
*/
object test {
def main(args: Array[String]) {
System.loadLibrary("MutiMatrix")
val x = Array(1.0,2.0)
val M = Array(1.0,2.0,3.0,4.0)
val mm = new MutiMatrix
val c = mm.vectorMutiMatrix(x, M)
println(c.toList)
}
}
8.结果