# mkdir -p /data/jni/src/com/example/
# cd /data/jni/src/com/example
編寫(xiě)java源文件
# vi HelloNative.java
package com.example;
import java.io.UnsupportedEncodingException;
public class HelloNative {
static {
System.loadLibrary("HelloJNI");// java.library.path
//System.load("/data/jni/Test/HelloJNI");// 絕對(duì)路徑
}
public native void sayHello();
public native int sum(int a, int b);
public native String concat(String a, String b);
public static void main(String[] args) {
HelloNative hello = new HelloNative();
hello.sayHello();
System.out.println(hello.sum(1,2));
try {
String result = hello.concat("apple is ", "一種水果");
System.out.println(result);
System.out.println(new String(result.getBytes("UTF-8")));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
# cd /data/jni/src
編譯java源文件為class文件,Windows CMD命令行默認(rèn)為GBK編碼
# javac -encoding UTF-8 com/example/HelloNative.java
從 class 文件生成C/C++語(yǔ)言的函數(shù)接口帮孔, .h 頭文件
# javah com.example.HelloNative
com_example_HelloNative.h 由包名+類(lèi)名組成,注意下劃線,不是點(diǎn)。
JNIEnv * : JNI接口本身的一個(gè)對(duì)象
jobject: 代表native方法的調(diào)用者,即HelloNative拯爽。具體值取決于當(dāng)前方法是靜態(tài)方法還是實(shí)例方法赵讯,若是靜態(tài)方法,則表示類(lèi)對(duì)象滔灶,若是實(shí)例方法,則表示實(shí)例對(duì)象
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_HelloNative */
#ifndef _Included_com_example_HelloNative
#define _Included_com_example_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_HelloNative
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_HelloNative_sayHello
(JNIEnv *, jobject);
/*
* Class: com_example_HelloNative
* Method: sum
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_HelloNative_sum
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_example_HelloNative
* Method: concat
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_HelloNative_concat
(JNIEnv *, jobject, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif
編寫(xiě)Hello.cpp源文件吼肥,實(shí)現(xiàn).h接口录平。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "com_example_HelloNative.h"
char* jstringToChar(JNIEnv *env, jstring jstr)
{
char * rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("UTF-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr,mid,strencode);
jsize alen = env->GetArrayLength(barr);
jbyte * ba = env->GetByteArrayElements(barr,JNI_FALSE);
if(alen > 0)
{
rtn = (char*)malloc(alen+1); //new char[alen+1];
memcpy(rtn,ba,alen);
rtn[alen]=0;
}
env->ReleaseByteArrayElements(barr,ba,0);
printf("char is %s\n", rtn);
return rtn;
}
jstring charTojstring(JNIEnv* env, const char* pat) {
//定義java String類(lèi) strClass
jclass strClass = (env)->FindClass("java/lang/String");
//獲取String(byte[],String)的構(gòu)造器,用于將本地byte[]數(shù)組轉(zhuǎn)換為一個(gè)新String
jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
//建立byte數(shù)組
jbyteArray bytes = (env)->NewByteArray(strlen(pat));
//將char* 轉(zhuǎn)換為byte數(shù)組
(env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat);
// 設(shè)置String, 保存語(yǔ)言類(lèi)型,用于byte數(shù)組轉(zhuǎn)換至String時(shí)的參數(shù)
jstring encoding = (env)->NewStringUTF("utf-8");
//將byte數(shù)組轉(zhuǎn)換為java String,并輸出
return (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding);
}
JNIEXPORT void JNICALL Java_com_example_HelloNative_sayHello(JNIEnv *env, jobject obj)
{
printf("Hello Native World。中文顯示@&*\n");
}
JNIEXPORT jint JNICALL Java_com_example_HelloNative_sum(JNIEnv *env, jobject obj, jint x, jint y)
{
return x+y;
}
JNIEXPORT jstring JNICALL Java_com_example_HelloNative_concat(JNIEnv *env, jobject obj, jstring javaStringOne, jstring javaStringTwo)
{
//const char *nativeStringOne = env->GetStringUTFChars(javaStringOne, NULL);
//const char *nativeStringTwo = env->GetStringUTFChars(javaStringTwo, NULL);
char *nativeStringOne = jstringToChar(env,javaStringOne);
char *nativeStringTwo = jstringToChar(env,javaStringTwo);
strcat(nativeStringOne, nativeStringTwo);//拼接字符串
// int length = sizeof(nativeStringOne) + sizeof(nativeStringTwo) + 1;
// char* concatstring = (char*)malloc(length * sizeof(char));
// memset(concatstring, 0, length);
// strcat(concatstring, nativeStringOne);
// strcat(concatstring, nativeStringTwo);
// printf("cast string is %s\n", concatstring);
// free(concatstring);
//env->ReleaseStringUTFChars(javaStringOne, nativeStringOne);
//env->ReleaseStringUTFChars(javaStringTwo, nativeStringTwo);
printf("nativeStringOne is %s\n", nativeStringOne);
//jstring result = (env)->NewStringUTF( nativeStringOne);
jstring result = charTojstring(env, nativeStringOne);
return result;
}
gcc(g++)編譯選項(xiàng)
-shared :指定生成動(dòng)態(tài)鏈接庫(kù)缀皱。
-static :指定生成靜態(tài)鏈接庫(kù)斗这。
-fPIC :表示編譯為位置獨(dú)立的代碼,用于編譯共享庫(kù)啤斗。目標(biāo)文件需要?jiǎng)?chuàng)建成位置無(wú)關(guān)碼表箭, 念上就是在可執(zhí)行程序裝載它們的時(shí)候,它們可以放在可執(zhí)行程序的內(nèi)存里的任何地方钮莲。
-L. :表示要連接的庫(kù)所在的目錄免钻。
-l:指定鏈接時(shí)需要的動(dòng)態(tài)庫(kù)。編譯器查找動(dòng)態(tài)連接庫(kù)時(shí)有隱含的命名規(guī)則崔拥,即在給出的名字前面加上lib极舔,后面加上.a/.so來(lái)確定庫(kù)的名稱(chēng)。
-Wall :生成所有警告信息链瓦。
-ggdb :此選項(xiàng)將盡可能的生成gdb 的可以使用的調(diào)試信息拆魏。
-g :編譯器在編譯的時(shí)候產(chǎn)生調(diào)試信息盯桦。
-c :只激活預(yù)處理、編譯和匯編,也就是把程序做成目標(biāo)文件(.o文件) 渤刃。
-Wl,options :把參數(shù)(options)傳遞給鏈接器ld 拥峦。如果options 中間有逗號(hào),就將options分成多個(gè)選項(xiàng),然后傳遞給鏈接程序
從Hello.cpp生成Hello.o目標(biāo)文件(windows)
64位MingGW: https://sourceforge.net/projects/mingw-w64/ x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z
# gcc -fPIC -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -c Hello.cpp
從Hello.o生成動(dòng)態(tài)鏈接庫(kù),Linux是.so文件卖子,Windows是.dll文件略号,文件名為System.loadLibrary("HelloJNI")中的名稱(chēng)HelloJNI
# gcc -shared Hello.o -o HelloJNI.dll
# gcc -shared Hello.o -o HelloJNI.so
直接從cpp生成動(dòng)態(tài)鏈接庫(kù)
# gcc -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o HelloJNI.dll Hello.cpp
調(diào)用方法
# java com.example.HelloNative
C/C++ 調(diào)用java,參考:http://www.reibang.com/p/3d68d65db468.
HelloNative.java
package com.example;
import java.io.UnsupportedEncodingException;
public class HelloNative {
static {
System.loadLibrary("HelloJNI");// java.library.path
//System.load("/data/jni/Test/HelloJNI");// 絕對(duì)路徑
}
public native void sayHello();
public native int sum(int a, int b);
public native String concat(String a, String b);
/**
* 供c/c++代碼調(diào)用的一個(gè)類(lèi)成員方法
*/
public void printDescription() {
System.out.println("printDescription called by c/c++");
}
/**
* 供c/c++代碼調(diào)用的一個(gè)類(lèi)靜態(tài)方法
*/
public static void notifyJava(String msg) {
System.out.println("notifyJava called by c/c++. " + msg);
}
public static void main(String[] args) {
HelloNative hello = new HelloNative();
hello.sayHello();
System.out.println(hello.sum(1,2));
try {
String result = hello.concat("apple is ", "一種水果");
System.out.println(result);
System.out.println(new String(result.getBytes("UTF-8")));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
Hello.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "com_example_HelloNative.h"
int callObjectMethod(JNIEnv *, jobject);
int callStaticMethod(JNIEnv *, jobject);
/**
* 調(diào)用 類(lèi)成員方法
* @return
*/
int callObjectMethod(JNIEnv *pEnv, jobject obj) {
jclass ndktestclass = pEnv->GetObjectClass(obj);
// 獲取方法printDescription 方法id洋闽,()V為返回值參數(shù)
jmethodID methodID = pEnv->GetMethodID(ndktestclass, "printDescription", "()V");
// CallVoidMethod沒(méi)有返回值
pEnv->CallVoidMethod(obj, methodID);
return 0;
}
/**
* 調(diào)用 類(lèi)靜態(tài)方法
* @param pEnv
* @param obj
* @return
*/
int callStaticMethod(JNIEnv *pEnv, jobject obj) {
jclass ndktestclass = pEnv->GetObjectClass(obj);
jmethodID methodID = pEnv->GetStaticMethodID(ndktestclass, "notifyJava", "(Ljava/lang/String;)V");
pEnv->CallStaticVoidMethod(ndktestclass, methodID, pEnv->NewStringUTF("new msg from jni"));
return 0;
}
char* jstringToChar(JNIEnv *env, jstring jstr)
{
char * rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("UTF-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr,mid,strencode);
jsize alen = env->GetArrayLength(barr);
jbyte * ba = env->GetByteArrayElements(barr,JNI_FALSE);
if(alen > 0)
{
rtn = (char*)malloc(alen+1); //new char[alen+1];
memcpy(rtn,ba,alen);
rtn[alen]=0;
}
env->ReleaseByteArrayElements(barr,ba,0);
printf("char is %s\n", rtn);
return rtn;
}
jstring charTojstring(JNIEnv* env, const char* pat) {
//定義java String類(lèi) strClass
jclass strClass = (env)->FindClass("Ljava/lang/String;");
//獲取String(byte[],String)的構(gòu)造器,用于將本地byte[]數(shù)組轉(zhuǎn)換為一個(gè)新String
jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
//建立byte數(shù)組
jbyteArray bytes = (env)->NewByteArray(strlen(pat));
//將char* 轉(zhuǎn)換為byte數(shù)組
(env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat);
// 設(shè)置String, 保存語(yǔ)言類(lèi)型,用于byte數(shù)組轉(zhuǎn)換至String時(shí)的參數(shù)
jstring encoding = (env)->NewStringUTF("utf-8");
//將byte數(shù)組轉(zhuǎn)換為java String,并輸出
return (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding);
}
JNIEXPORT void JNICALL Java_com_example_HelloNative_sayHello(JNIEnv *env, jobject obj)
{
printf("Hello Native World玄柠。中文顯示@&*\n");
}
JNIEXPORT jint JNICALL Java_com_example_HelloNative_sum(JNIEnv *env, jobject obj, jint x, jint y)
{
return x+y;
}
JNIEXPORT jstring JNICALL Java_com_example_HelloNative_concat(JNIEnv *env, jobject obj, jstring javaStringOne, jstring javaStringTwo)
{
// 調(diào)用java的方法
callObjectMethod(env, obj);
callStaticMethod(env, obj);
//const char *nativeStringOne = env->GetStringUTFChars(javaStringOne, NULL);
//const char *nativeStringTwo = env->GetStringUTFChars(javaStringTwo, NULL);
char *nativeStringOne = jstringToChar(env,javaStringOne);
char *nativeStringTwo = jstringToChar(env,javaStringTwo);
strcat(nativeStringOne, nativeStringTwo);//拼接字符串
// int length = sizeof(nativeStringOne) + sizeof(nativeStringTwo) + 1;
// char* concatstring = (char*)malloc(length * sizeof(char));
// memset(concatstring, 0, length);
// strcat(concatstring, nativeStringOne);
// strcat(concatstring, nativeStringTwo);
// printf("cast string is %s\n", concatstring);
// free(concatstring);
//env->ReleaseStringUTFChars(javaStringOne, nativeStringOne);
//env->ReleaseStringUTFChars(javaStringTwo, nativeStringTwo);
printf("nativeStringOne is %s\n", nativeStringOne);
//jstring result = (env)->NewStringUTF( nativeStringOne);
jstring result = charTojstring(env, nativeStringOne);
return result;
}
安裝opencv
https://www.vultr.com/docs/how-to-install-opencv-on-centos-7
Step 1: Install dependencies for OpenCV
yum groupinstall "Development Tools" -y
yum install cmake gcc gtk2-devel numpy pkconfig -y
Step 2: Download the OpenCV 2.4.9 archive
cd /opt
wget https://github.com/opencv/opencv/archive/2.4.9.zip
(或者上傳opencv-2.4.9.zip)
unzip opencv-2.4.9.zip
Step 3: Compile and install OpenCV 2.4.9
cd opencv-2.4.9
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=DEBUG -D CMAKE_INSTALL_PREFIX=/usr/local/ ..
make
make install
Step 4: Configure required variables
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig/
echo '/usr/local/lib/' >> /etc/ld.so.conf.d/opencv.conf
ldconfig
Step 5 (optional): Run tests
cd /home/xxxx
git clone https://github.com/opencv/opencv_extra.git
export OPENCV_TEST_DATA_PATH=/home/xxxx/opencv_extra/testdata
In the cmake build directory, you will find several test executables named in the same kind of format opencv_test_*. Run any one you are interested in to perform a test. For example:
cd /home/xxxx/opencv-2.4.9/build/bin
ls
./opencv_test_photo
添加動(dòng)態(tài)鏈接庫(kù)
//拷貝libopencv_softcascade.so.2.4.9和libopencv_ts.so.2.4.9到/usr/local/lib目錄
//生成軟鏈接
<pre><code>
chmod 777 libopencv_softcascade.so.2.4.9
ln -s libopencv_softcascade.so.2.4.9 libopencv_softcascade.so.2.4
ln -s libopencv_softcascade.so.2.4 libopencv_softcascade.so
chmod 777 libopencv_ts.so.2.4.9
ln -s libopencv_ts.so.2.4.9 libopencv_ts.so.2.4
ln -s libopencv_ts.so.2.4 libopencv_ts.so
</pre></code>
//使動(dòng)態(tài)鏈接庫(kù)生效
/sbin/ldconfig -v
安裝ffmpg
http://www.reibang.com/p/2b98e0f87720
1.升級(jí)系統(tǒng)
sudo yum install epel-release -y
2.安裝Nux Dextop Yum 源
sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
?
3.安裝FFmpeg 和 FFmpeg開(kāi)發(fā)包
sudo yum install ffmpeg ffmpeg-devel -y
4.測(cè)試是否安裝成功
ffmpeg
使用FFmpeg將flv轉(zhuǎn)為mp4
ffmpeg -i input.flv output.mp4