# mkdir -p /data/jni/src/com/example/
# cd /data/jni/src/com/example
编写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");// 绝对路径
}
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命令行默认为GBK编码
# javac -encoding UTF-8 com/example/HelloNative.java
从 class 文件生成C/C++语言的函数接口, .h 头文件
# javah com.example.HelloNative
com_example_HelloNative.h 由包名+类名组成,注意下划线,不是点。
JNIEnv * : JNI接口本身的一个对象
jobject: 代表native方法的调用者,即HelloNative。具体值取决于当前方法是静态方法还是实例方法,若是静态方法,则表示类对象,若是实例方法,则表示实例对象
/* 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
编写Hello.cpp源文件,实现.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类 strClass
jclass strClass = (env)->FindClass("java/lang/String");
//获取String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
//建立byte数组
jbyteArray bytes = (env)->NewByteArray(strlen(pat));
//将char* 转换为byte数组
(env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat);
// 设置String, 保存语言类型,用于byte数组转换至String时的参数
jstring encoding = (env)->NewStringUTF("utf-8");
//将byte数组转换为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++)编译选项
-shared :指定生成动态链接库。
-static :指定生成静态链接库。
-fPIC :表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码, 念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方。
-L. :表示要连接的库所在的目录。
-l:指定链接时需要的动态库。编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a/.so来确定库的名称。
-Wall :生成所有警告信息。
-ggdb :此选项将尽可能的生成gdb 的可以使用的调试信息。
-g :编译器在编译的时候产生调试信息。
-c :只激活预处理、编译和汇编,也就是把程序做成目标文件(.o文件) 。
-Wl,options :把参数(options)传递给链接器ld 。如果options 中间有逗号,就将options分成多个选项,然后传递给链接程序
从Hello.cpp生成Hello.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生成动态链接库,Linux是.so文件,Windows是.dll文件,文件名为System.loadLibrary("HelloJNI")中的名称HelloJNI
# gcc -shared Hello.o -o HelloJNI.dll
# gcc -shared Hello.o -o HelloJNI.so
直接从cpp生成动态链接库
# gcc -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o HelloJNI.dll Hello.cpp
调用方法
# java com.example.HelloNative
C/C++ 调用java,参考:https://www.jianshu.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");// 绝对路径
}
public native void sayHello();
public native int sum(int a, int b);
public native String concat(String a, String b);
/**
* 供c/c++代码调用的一个类成员方法
*/
public void printDescription() {
System.out.println("printDescription called by c/c++");
}
/**
* 供c/c++代码调用的一个类静态方法
*/
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);
/**
* 调用 类成员方法
* @return
*/
int callObjectMethod(JNIEnv *pEnv, jobject obj) {
jclass ndktestclass = pEnv->GetObjectClass(obj);
// 获取方法printDescription 方法id,()V为返回值参数
jmethodID methodID = pEnv->GetMethodID(ndktestclass, "printDescription", "()V");
// CallVoidMethod没有返回值
pEnv->CallVoidMethod(obj, methodID);
return 0;
}
/**
* 调用 类静态方法
* @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类 strClass
jclass strClass = (env)->FindClass("Ljava/lang/String;");
//获取String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新String
jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
//建立byte数组
jbyteArray bytes = (env)->NewByteArray(strlen(pat));
//将char* 转换为byte数组
(env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*) pat);
// 设置String, 保存语言类型,用于byte数组转换至String时的参数
jstring encoding = (env)->NewStringUTF("utf-8");
//将byte数组转换为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)
{
// 调用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
添加动态链接库
//拷贝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>
//使动态链接库生效
/sbin/ldconfig -v
安装ffmpg
https://www.jianshu.com/p/2b98e0f87720
1.升级系统
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开发包
sudo yum install ffmpeg ffmpeg-devel -y
4.测试是否安装成功
ffmpeg
使用FFmpeg将flv转为mp4
ffmpeg -i input.flv output.mp4