如何通过JNI传递对象执行回调

举报
ShaderJoy 发表于 2021/12/30 00:48:06 2021/12/30
1.4k+ 0 0
【摘要】 JNI的全称是java native interface,用来调用某些特定于系统平台或者硬件的操作,但是它只能调用c/c++的代码,若是其它语言代码,只能通过c/c++进行二次调用。 关于JNI的完整技术文档,大家可以查看下面这个网址: http://java.sun.com/j2se/1.5.0/docs/guide/j...
JNI的全称是java native interface,用来调用某些特定于系统平台或者硬件的操作,但是它只能调用c/c++的代码,若是其它语言代码,只能通过c/c++进行二次调用。
关于JNI的完整技术文档,大家可以查看下面这个网址:
http://java.sun.com/j2se/1.5.0/docs/guide/jni/

下面我们看下JNI如何执行回调函数:
我们知道在c/c++回调函数可以通过函数指针执行,但是在Java中已经没有指针的概念,在这里,我们先传递一个类对象给native函数,然后再dll中调用期望的函数即可。
下面的这个例子中,我们通过回调传递一个字符串给java,这在java和c/c++混合编程时传递dll内部的出错或其他信息到java层是很有用的。
1. 首先创建一个java类文件,封装一个native函数和一个用于回调的函数

       package jni;
       public class Log{
       static{
       System.loadLibrary("mylib");
       }
       //用来回调,输出c代码层的信息
       public void output(String out){
       System.out.println(out);
       }
       //native函数,用来传递Log对象,在jni中调用Log对象的output方法
       public native void test(Log log);
       public static void main(String[] args){
       Log log = new Log();
       log.test(log);
       }
       }
   
  

2. 调用javah命令,生成对应的c/c++都文件

       /* DO NOT EDIT THIS FILE - it is machine generated */
       #include <jni.h>
       /* Header for class jni_Log */
       #ifndef _Included_jni_Log
       #define _Included_jni_Log
       #ifdef __cplusplus
       extern "C" {
       #endif
       /*
       * Class: jni_Log
       * Method: test
       * Signature: (Ljni/Log;)V
       */
       JNIEXPORT void JNICALL Java_jni_Log_test
       (JNIEnv *, jobject, jobject);
       #ifdef __cplusplus
       }
       #endif
       #endif
   
  

3. 利用vc和生成的头文件完成一个dll

       #include <windows.h>
       #include "jni_Log.h"
       int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReasion,PVOID pvReserved)
       {
       return TRUE;
       }
       JNIEXPORT void JNICALL Java_jni_Log_test(JNIEnv * env, jobject obj, jobject log)
       {
       jclass cls = (*env)->GetObjectClass(env, log);//得到Log类
       jmethodID jmid = (*env)->GetMethodID(env, cls, "output", "(Ljava/lang/String;)V");
       jstring info = (*env)->NewStringUTF(env, "i am a error!");
       (*env)->CallVoidMethod(env,log, jmid,info);
       (*env)->ReleaseStringUTFChars(env,info,(*env)->GetStringUTFChars(env, info, FALSE));
       }
   
  

编译完成后,将mylib.dll放到与jni同级的目录中,运行命令java jni.Log,即可看到控制台成功打印信息
"i am a error!"。

文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/8520498

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。