scala代码编写

Sample1.scala

class Sample1 {
// --- Native methods
@native def intMethod(n: Int): Int
def loadLibrary(libName:String):Unit = {
System.loadLibrary(libName)
}
} intMethod输入一个int类型的数,返回输入数的平方 loadLibrary函数用于载入.so文件,在类外的调用有时会出问题

编译scala文件并生成.h文件

scalac Sample1.scala
export SCALA_LIB_HOME=/home/hadoop/scala-2.11.8/lib/
export SCALA_CP=$SCALA_LIB_HOME/scala-library.jar:$SCALA_LIB_HOME/scala-refl ect.jar
javah -cp $SCALA_CP:. Sample1

编写.h文件对应的cpp文件,并编译

#include "Sample1.h"

/*
* Method: intMethod
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_Sample1_intMethod
(JNIEnv *, jobject, jint int_t)
{
return int_t*int_t;
}
g++ -dynamiclib -fPIC -shared -O3 -I /usr/include -I $JAVA_HOME/include -I $JAVA_HOME/include/linux Sample1.cpp -o libSample1.so

此处还可以使用cmake进行整理编译

直接scala shell下调用

运行命令进入shell

scala -Djava.library.path=[/path/to/lib*.so]

然后命令行输入调用

var s1 = new Sample1
s1.loadLibrary("Sample1")
s1.intMethod(5)

还可以编写scala文件调用,过程类似

object run{
def main(args: Array[String]) {
System.loadLibrary("Sample1")
var ss = new Sample1
println(ss.intMethod(5))
}
}

编译运行scala文件,需要指定c++动态链接库的路径

scalac run.scala
scala -Djava.library.path=/home/hadoop/project/jni_tmp run

此处大坑预警!!

很郁闷的问题,之前在使用以下命令在scala shell直接调用Sample1的类时,报链接错误且没有理由

   System.loadLibrary("Sample1")
var ss = new Sample1
println(ss.intMethod(5))

错误 java.lang.UnsatisfiedLinkError: Sample1.intMethod(I)

在google时发现有人提到:“System.loadLibrary("Sample1")的调用层次应该与Sample1类的载入保持一致”。没有深究调用层次的问题,和JVM调用机制有关。将System.loadLibrary函数换到类中调用后没有此问题。

ps:baidu、bing下搜了一大堆完全没答案,技术问题还得靠google。

参考 http://blog.csdn.net/funy88/article/details/44646601

05-28 08:28