JNI使用实例之C、C++ DLL回调java成员函数
来源:互联网 发布:ubuntu cmd命令窗口 编辑:程序博客网 时间:2024/05/21 10:17
使用场景描述如下:
1、使用java程序调用C开发的DLL,传入一个已封装的socket对象
2、在C开发的DLL中根据传入的对象调用java提供的recv()、send()函数发送数据
java部分对应的代码如下:
// ISocketBase.javapackage com.tms;public interface ISocketBase {public void send(byte [] data);public byte [] recv(int timeout);}
// SocketImp.javapackage com.tms;import java.io.*;import java.net.*;import java.nio.*;import java.nio.charset.*;public class SocketImp implements ISocketBase{ private ServerSocket server; private Socket socket; private OutputStream dos; private InputStream dis; public SocketImp() { } public void EndSocket() { try { dis.close(); dos.close(); socket.close(); server.close(); } catch (IOException e) { } } public void StartSocket() { try { server = new ServerSocket(8888); System.out.println("start server connetion, port = 8888."); socket = server.accept(); dos = socket.getOutputStream(); dis = socket.getInputStream(); } catch (SocketException e) { System.out.println("The network connection is exception, the program exits."); } catch (IOException e) { e.printStackTrace(); } } private static void printHexString(byte[] b, int iLen) { for (int i = 0; i < iLen; i++) { String hex = Integer.toHexString(b[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } System.out.print(hex.toUpperCase() + " "); } System.out.println(""); } @Override public void send(byte[] bytes) { try { dos.write(bytes); System.out.println("[java send] length = " + bytes.length + "."); } catch (Exception e) { e.printStackTrace(); } } @Override public byte[] recv(int timeout) { byte[] cRecvData = new byte[1024 * 3]; int iLength = 0; try { socket.setSoTimeout(timeout); iLength = dis.read(cRecvData); printHexString(cRecvData, iLength); System.out.println("java read length: " + iLength); } catch (Exception e) { e.printStackTrace(); } byte[] cRet = new byte[iLength]; for(int i = 0; i < iLength; ++i) { cRet[i] = cRecvData[i]; } return cRet; }}
// CallDllNative.javapackage com.tms;import java.io.*;public class CallDllNative { static{ System.loadLibrary("C_DLL_NAME"); } public native static void Download(ISocketBase socketBase, String binFile, StringBuffer retCode); public static void main(String args[]) { String binFile = new String("./123.txt"); SocketImp socket; StringBuffer retCode = new StringBuffer("23"); socket = new SocketImp(); socket.StartSocket(); System.out.println("CallDllNative is running... ..."); try { Download(socket, binFile, retCode); } catch (Exception e) { e.printStackTrace(); } System.out.println("retCode = " + retCode); socket.EndSocket(); }}
c部分对应的代码如下:
// Download.h/* DO NOT EDIT THIS FILE - it is machine generated */#include "jni.h"/* Header for class com_tms_CallDllNative */#ifndef _Included_com_tms_CallDllNative #define _Included_com_tms_CallDllNativeextern int SendData(char* pSendData, int iSendDataLen);extern int RecvData(char* pRecvData, int iRecvDataLen, int timeout);#ifdef __cplusplusextern "C" {#endif/* * Class: com_tms_CallDllNative * Method: Download * Signature: (Lcom/tms/ISocketBase;Ljava/lang/String;Ljava/lang/StringBuffer;)V */JNIEXPORT void JNICALL Java_com_tms_CallDllNative_Download (JNIEnv *, jclass, jobject, jstring, jobject);#ifdef __cplusplus}#endif#endif
// Download.c#include <stdio.h>#include <string.h>#include "Download.h"static JNIEnv* s_env;static jobject s_socketBase;static jclass s_clsSocket;extern int Download(const char* pFilePath);int SendData(char* pSendData, int iSendDataLen){ jmethodID sendFun = (*s_env)->GetMethodID(s_env, s_clsSocket, "send", "([B)V"); jbyteArray pSend = (*s_env)->NewByteArray(s_env, iSendDataLen); if(NULL == sendFun || NULL == pSend) { printf("NULL == sendFun || NULL == pSend.\n"); return -1; // OutOfMemoryError already thrown } (*s_env)->SetByteArrayRegion(s_env, pSend, 0, iSendDataLen, (jbyte*)pSendData); (*s_env)->CallVoidMethod(s_env, s_socketBase, sendFun, pSend); (*s_env)->ReleaseByteArrayElements(s_env, pSend, (*s_env)->GetByteArrayElements(s_env, pSend, NULL), 0); return iSendDataLen;}int RecvData(char* pRecvData, int iRecvDataLen, int timeout){ jbyteArray jRecvArray; jbyte* jRecv; int iRecvLen; jmethodID recvFun = (*s_env)->GetMethodID(s_env, s_clsSocket, "recv", "(I)[B"); jRecvArray = (jbyteArray)(*s_env)->CallObjectMethod(s_env, s_socketBase, recvFun, timeout); if(NULL == jRecvArray) { printf("NULL == jRecvArray.\n"); return -1; } jRecv = (*s_env)->GetByteArrayElements(s_env, jRecvArray, 0); if(NULL == jRecv) { printf("NULL == jRecv.\n"); return -1; } iRecvLen = (*s_env)->GetArrayLength(s_env, jRecvArray); if(iRecvLen > iRecvDataLen) { iRecvLen = iRecvDataLen; } memcpy(pRecvData, jRecv, iRecvLen); (*s_env)->ReleaseByteArrayElements(s_env, jRecvArray, jRecv, 0); return iRecvLen;}static int SetRetValue(int iRetValue, jobject retCode){ char cRetCode[20]; int iLen = 0; jstring strRetCode; jclass clsRetCode = (*s_env)->GetObjectClass(s_env, retCode); jmethodID lenFunID = (*s_env)->GetMethodID(s_env, clsRetCode, "length", "()I"); jmethodID deleteFunID = (*s_env)->GetMethodID(s_env, clsRetCode, "delete", "(II)Ljava/lang/StringBuffer;"); jmethodID appendFunID = (*s_env)->GetMethodID(s_env, clsRetCode, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); printf("iRetValue = %d\n", iRetValue); if(iRetValue < 0) { iRetValue = -iRetValue; } cRetCode[0] = iRetValue / 10 + '0'; cRetCode[1] = iRetValue % 10 + '0'; cRetCode[2] = '\0'; strRetCode = (*s_env)->NewStringUTF(s_env, cRetCode); if(NULL == clsRetCode || NULL == lenFunID || NULL == deleteFunID || NULL == appendFunID || NULL == strRetCode) { printf("SetRetValue == NULL.\n"); return -1; } iLen = (*s_env)->CallIntMethod(s_env, retCode, lenFunID); (*s_env)->CallObjectMethod(s_env, retCode, deleteFunID, 0, iLen); (*s_env)->CallObjectMethod(s_env, retCode, appendFunID, strRetCode); (*s_env)->DeleteLocalRef(s_env, strRetCode); return 0;}/* * Class: com_tms_DownloadNative * Method: tmsDownload * Signature: (Lcom/tms/ISocketBase;Ljava/lang/String;Ljava/lang/StringBuffer;)V */JNIEXPORT void JNICALL Java_com_tms_CallDllNative_Download (JNIEnv* env, jclass cls, jobject socketBase, jstring binFile, jobject retCode){ int iRet = 0; const char *pFilePath = (*env)->GetStringUTFChars(env, binFile, NULL); s_clsSocket = (*env)->GetObjectClass(env, socketBase); if(NULL == pFilePath || NULL == s_clsSocket) { printf("NULL == pFilePath || NULL == s_clsSocket.\n"); return ; } s_env = env; s_socketBase = socketBase; iRet = Download(pFilePath); if(0 != SetRetValue(iRet, retCode)) { printf("Failed to SetRetValue().\n"); return ; } (*env)->ReleaseStringUTFChars(env, binFile, pFilePath);}
对应的java编译命令如下:
javac -d . com\tms\*.java
java -Djava.library.path=. com.tms.CallDllNative
0 0
- JNI使用实例之C、C++ DLL回调java成员函数
- Java jni调用c函数实例
- JNI使用—java使用C++dll及dll回调java
- JNI 之c/c++和Java交互,调用java成员
- JNI引用C++dll若干问题总结-如何导出C++中的类成员函数
- JNI之c调用java的函数,调用java的构造生成对象,得到java的成员,以及C返回Java字符串乱码
- JNI之C代码访问java中的成员和java调C
- 使用 JNI 调用 c 的 DLL
- 使用JNI调用dll(C++)
- JAVA JNI调用C编写的dll
- Ndk学习之JNI构造函数(java-->C-->Java)
- android使用c通过jni回调java
- Chap5:使用JNI技术实现java程序调用第三方dll(c/c++)文件的功能
- 使用JNI技术实现java程序调用第三方dll(c/c++)文件的功能
- JNI之 c/c++调用java构造函数
- jni C调用java的实例
- 【转载整理】eclipse 开发c/c++、Java使用JNI调用C程序、生成64位dll动态链接库
- JNI简单使用之二:C/C++调用JAVA
- 异常机制 :try、catch、 finally 、throw 、throws
- 你所不知道的Android Studio调试技巧
- 线程并发共享资源同步原理解析1
- ubuntu完美搭建git服务器
- 动态规划的思考(1)
- JNI使用实例之C、C++ DLL回调java成员函数
- cv::inRange的作用,注意它的区间是闭区间,而不是开区间...
- MyEclipse 全局替换与选择替换
- android studio LeakCanary 找出内存泄漏
- 终于做了这个决定
- Qt学习之路(41): QTableWidget
- Leetcode 3. Longest Substring Without Repeating Characters (Medium) (cpp)
- Unreal Engine 4 —— 版本兼容的工作原理以及一些可优化项
- 简书---不错的博文网站