概述
Jni dll 开发教程 vs2019 + idea
创建java类 native方法
???? 加载动态库
- 函数System.loadLibrary()是加载dll(windows)或so(Linux)库
- System.loadLibrary(“hello”); 需要将此库放到环境变量的路径中
- 或者 System.load( System.getProperty(“user.dir”) + “/hello.dll”); 用户目录即程序目录下
- 若此dll或so依赖别的动态库,需要根据依赖性先后添加动态库
- 检查动态库依赖 windows:
dumpbin.exe /dependents D:pyhell0.dll
创建Native 方法 生成接口c++头文件
在java中编写jni c++ 要实现的方法 native 修饰
private native long createNativeAvTranscodeObj(int id);
idea 项目 src目录下 :格式 javah package.className
javah AVProcess.AVTranscodeJNI
生成 AVProcess_AVTranscodeJNI.h 有文件 接下来c++ 实现头文件生成动态库便可
生成如下c++函数接口
c++ jni 接口 头文件
#include <jni.h>
/* Header for class AVProcess_AVTranscodeJNI */
#ifndef _Included_AVProcess_AVTranscodeJNI
#define _Included_AVProcess_AVTranscodeJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:
AVProcess_AVTranscodeJNI
* Method:
createNativeAvTranscodeObj
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_AVProcess_AVTranscodeJNI_createNativeAvTranscodeObj
(JNIEnv *, jobject, jint);
/*
* Class:
AVProcess_AVTranscodeJNI
* Method:
ReleaseNativeAvTranscodeObj
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_AVProcess_AVTranscodeJNI_ReleaseNativeAvTranscodeObj
(JNIEnv *, jobject, jlong);
java jni接口
package AVProcess;
public class AVTranscodeJNI {
static {
// hello.dll (Windows) or libhello.so (Unixes)
//System.out.println("当前dll加载路径:"+System.getProperty("java.library.path"));
//System.setProperty("java.library.path", System.getProperty("user.dir") + "/lib");
System.out.println(System.getProperty("user.dir"));
System.load( System.getProperty("user.dir") + "/lib/avutil-57.dll");
System.load( System.getProperty("user.dir") + "/lib/swscale-6.dll");
System.load( System.getProperty("user.dir") + "/lib/libx264-164.dll");
System.load( System.getProperty("user.dir") + "/lib/libx265.dll");
System.loadLibrary(AVTranscode);
}
private long nativeAvTranObj;
public AVTranscodeJNI(int id) {
nativeAvTranObj = createNativeAvTranscodeObj(id);
}
public void finalize(){
if(nativeAvTranObj != 0){
ReleaseNativeAvTranscodeObj(nativeAvTranObj);
nativeAvTranObj = 0;
}
}
public void SetCallback(Callback callback){
SetNativeCallback(nativeAvTranObj, callback);
};
public
int SetCompressLevel(int compressLevel){
return SetNativeCompressLevel(nativeAvTranObj, compressLevel);
};
public int Pause(){
return NativePause(nativeAvTranObj);
};
public int Running(){
return NativeRunning(nativeAvTranObj);
};
public AVTranscoderState GetState(){
return GetNativeState(nativeAvTranObj);
};
public int StartTranscode(String inAvPath, String outAvPath, int compressLevel){
return StartNativeTranscode(nativeAvTranObj, inAvPath, outAvPath, compressLevel);
};
public int GetAvInfo(String avPath, VideoInfo avInfo){
return GetNativeAvInfo(nativeAvTranObj, avPath, avInfo);
};
//native c++
private native long createNativeAvTranscodeObj(int id);
private native void ReleaseNativeAvTranscodeObj(long nativeAvTranObj);
private native void SetNativeCallback(long nativeAvTranObj, Callback callback);
private native int SetNativeCompressLevel(long nativeAvTranObj, int compressLevel);
private native int NativePause(long nativeAvTranObj);
private native int NativeRunning(long nativeAvTranObj);
private native AVTranscoderState GetNativeState(long nativeAvTranObj);
private native int StartNativeTranscode(long nativeAvTranObj, String inAvPath, String outAvPath, int compressLevel);
private native int GetNativeAvInfo(long nativeAvTranObj, String avPath, VideoInfo avInfo);
public static void main(String[] args) {
System.out.println("Hello world!");
AVTranscodeJNI transcoder = new AVTranscodeJNI(0);
System.out.println(transcoder.GetState());
VideoInfo avInfo = new VideoInfo();
int ret = transcoder.GetAvInfo("00003.mp4", avInfo);
System.out.println(avInfo);
ret = transcoder.StartTranscode("000003.mp4", "out.mp4", 0);
System.out.println(ret);
}
}
开发 c++ dll
采用vs2019 开发 创建项目->动态库 直接将AVProcess_AVTranscodeJNI.h 复制到项目目录中便可
接口参数
JNIEnv 运行线程环境,jobject java调用对象 这两个是固定参数,其余是函数参数
保存c++ 对象方便调用
保存c++类对象地址存储为 java long nativeAvTranObj
java
private long nativeAvTranObj;
public AVTranscodeJNI(int id) {
nativeAvTranObj = createNativeAvTranscodeObj(id);
}
JNIEXPORT jlong JNICALL Java_AVProcess_AVTranscodeJNI_createNativeAvTranscodeObj(JNIEnv* env, jobject obj, jint id) {
Transcode* transcoder = NULL;
transcoder = new Transcode(id);
if (transcoder)
return jlong(transcoder);
}
传入修改java对象
java 实现
public int GetAvInfo(String avPath, VideoInfo avInfo){
return GetNativeAvInfo(nativeAvTranObj, avPath, avInfo);
};
c++jni 实现
JNIEXPORT jint JNICALL Java_AVProcess_AVTranscodeJNI_GetNativeAvInfo(JNIEnv* env, jobject obj, jlong tranObjAddr, jstring javPath, jobject javInfo) {
Transcode* transcoder = (Transcode*)tranObjAddr;
std::string avPath = JavaStringToString(env, javPath);
if (avPath.empty()) {
return -10000;
}
AVFileInfo avInfo;
transcoder->GetVideoinfo(avPath, avInfo);
jclass jclass_AvInfo = env->GetObjectClass(javInfo);
jfieldID jformatId = env->GetFieldID(jclass_AvInfo, "format", "Ljava/lang/String;");
jstring jfmtStr = StringToJavaString(env, avInfo.format);
env->SetObjectField(javInfo, jformatId, jfmtStr);
jfieldID jdurationSecsId = env->GetFieldID(jclass_AvInfo, "durationSecs", "I");
env->SetIntField(javInfo, jdurationSecsId, avInfo.durationSecs);
env->DeleteLocalRef(jclass_AvInfo);
return 0;
}
c++ 中获得 java对象字段 方法
jclass jclass_AvInfo = env->GetObjectClass(javInfo);
获得java 类对象引用
jfieldID jformatId = env->GetFieldID(jclass_AvInfo, "format", "Ljava/lang/String;");
获得类数据字段Id
env->SetObjectField(javInfo, jformatId, jfmtStr);
设置数据字段值
JavaNative Interface FieldDescriptors
jni 字段描述符
Ljava/lang/String; string 数据字段
javac VideoInfo.java
生成 VideoInfo.class
javap -s -p VideoInfo.class
查看字段描述命令
java.lang.String format;
descriptor: Ljava/lang/String;
int durationSecs;
descriptor: I
long bitrate;
descriptor: J
方法描述:
private native AVProcess.VideoInfo GetNativeInAVInfo(long);
descriptor: (J)LAVProcess/VideoInfo;
private native AVProcess.VideoInfo GetNativeOutAVInfo(long);
descriptor: (J)LAVProcess/VideoInfo;
private native AVProcess.VideoInfo GetNativeAvInfo(long, java.lang.String);
descriptor: (JLjava/lang/String;)LAVProcess/VideoInfo;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
static {};
c++ string 与java jstring 互转
windows 下 c++ 17
#include <windows.h>
std::string JavaStringToString(JNIEnv* env, jstring str) {
if (env == nullptr || str == nullptr) {
return "";
}
const jchar* chars = env->GetStringChars(str, NULL);
if (chars == nullptr) {
return "";
}
std::wstring wstring = reinterpret_cast<const wchar_t*>(chars);
std::string u8_string;
int dstWStrSize = WideCharToMultiByte(CP_ACP, 0, wstring.c_str(), wstring.size(), NULL, 0, NULL, NULL);
if (dstWStrSize <= 0) {
return "";
}
u8_string.resize(dstWStrSize);
dstWStrSize = WideCharToMultiByte(CP_ACP, 0, wstring.c_str(), wstring.size(), &u8_string[0], u8_string.size(), NULL, NULL);
//env->GetStringLength(str));
env->ReleaseStringChars(str, chars);
return u8_string;
}
jstring StringToJavaString(JNIEnv* env, const std::string& u8_string) {
int dstStrSize = MultiByteToWideChar(CP_ACP, 0, u8_string.c_str(), u8_string.size(), NULL, 0);
if (dstStrSize <= 0) {
return NULL;
}
std::wstring wstring;
wstring.resize(dstStrSize);
int writedCharLen = MultiByteToWideChar(CP_UTF8, 0, u8_string.c_str(), u8_string.size(), &wstring[0], wstring.size());
auto result = env->NewString(reinterpret_cast<const jchar*>(wstring.data()),
wstring.length());
return result;
}
设置c++ 回调java 函数
java
package AVProcess;
public interface Callback {
public default void call(int id, int state, int progressRate){
System.out.printf("id: %d, state: %d, progressRate: %d", id, state,progressRate);
}
}
public void SetCallback(Callback callback){
SetNativeCallback(nativeAvTranObj, callback);
};
jni c++
static JavaVM* jvm = NULL;
static jclass jcls = NULL;
static jmethodID methodId = NULL;
JNIEXPORT void JNICALL Java_AVProcess_AVTranscodeJNI_SetNativeCallback(JNIEnv* env, jobject obj, jlong tranObjAddr, jobject callObj) {
jcls = env->GetObjectClass(callObj);
methodId = env->GetMethodID(jcls, "call", "(I)V");
Transcode* transcoder = (Transcode*)tranObjAddr;
transcoder->SetCallback(ReportProgress);
//env->CallVoidMethod(callObj, method, 5);
}
全局保存回调接口类引用、字段id、方法
c++ 回调
void CallBacl(int id, int state, int progressRate) {
JNIEnv* env;
if (!jvm || !jcls || !methodId)
return;
jvm->AttachCurrentThread(reinterpret_cast<void**>(&env), nullptr);
jobject jobj = env->NewObject(jcls, methodId);
env->CallVoidMethod(jobj, methodId, id, state, progressRate);
env->DeleteLocalRef(jobj);
jvm->DetachCurrentThread();
}
jvm: java 运行虚拟机环境
在 jni c++ 中获取 在java中执行 System.loadLibrary(AVTranscode);
时自动执行此函数
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
jvm = vm;
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_8) != JNI_OK) {
return JNI_ERR;
}
return JNI_VERSION_1_8;
}
返回java 枚举对象
java
getAVTranState 方便 jni c++ 通过互相对应的值调用生成
package AVProcess;
public enum AVTranscoderState{
READY, RUNNING, PAUSE, ENDING, FINISHED, EXIT, FAILURE;
public static AVTranscoderState getAVTranState(int ordinal){
AVTranscoderState states[] = values();
if(ordinal < states.length && ordinal >= 0)
return states[ordinal];
return null;
}
};
c++
JNIEXPORT jobject JNICALL Java_AVProcess_AVTranscodeJNI_GetNativeState(JNIEnv* env, jobject obj, jlong tranObjAddr) {
Transcode* transcoder = (Transcode*)tranObjAddr;
int state = int(transcoder->GetState());
jclass jState = env->FindClass("AVProcess/AVTranscoderState");
jmethodID j_method_getAVState = env->GetStaticMethodID(jState, "getAVTranState", "(I)LAVProcess/AVTranscoderState;");
jobject objState = env->CallStaticObjectMethod(jState, j_method_getAVState, state);
env->DeleteLocalRef(jState);
return objState;
}
jmethodID: 获取java 方法
最后
以上就是犹豫学姐为你收集整理的Jni dll 开发教程 vs2019 + idea的全部内容,希望文章能够帮你解决Jni dll 开发教程 vs2019 + idea所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复