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
原创粉丝点击