呆羊在曬太陽  
          公告
          • Y:哦,是你呀。
            X:我現在正在忙。
            Y:忙什么?
            X:呵呵,今天出太陽了,我把錢搬出來曬一曬。
            ***********************
            abc
            小叉
            很高興能結識大家!
            ***********************
          日歷
          <2005年12月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567
          統計
          • 隨筆 - 164
          • 文章 - 2
          • 評論 - 196
          • 引用 - 0

          導航

          常用鏈接

          留言簿(7)

          隨筆分類(158)

          文章分類(2)

          相冊

          log

          搜索

          •  

          積分與排名

          • 積分 - 71010
          • 排名 - 779

          最新評論

          閱讀排行榜

           

          JavaC之間通過JNI傳遞中文字符串

          簡介 

          本文提供一個具體的實例,說明JavaC之間通過JNI傳遞含有中文字符串的參數,解決中文亂碼問題(雙字節或多字節亂碼)。本文給出具體的源代碼,對源代碼進行了解釋,C部分提供了 CC++兩種方式實現的完整代碼。并且所有代碼均在實驗環境下測試通過。本文讀者須對JavaC(C++)有一定的基礎知識。

          實驗環境

          Windows XP (或Windows2000

          j2sdk1.4.2/j2re1.4.2

          Microsoft VisualC++6.0

          安裝好j2sdk后需要設置環境變量

          CLASSPATH=.;C:\j2sdk1.4.2\bin;C:\j2sdk1.4.2\lib\dt.jar;C:\j2sdk1.4.2\lib\tools.jar;C:\j2sdk1.4.2\lib\htmlconverter.jarj2sdk安裝在c:\j2sdk1.4.2目錄下)

          源代碼及代碼說明

          Java代碼:

          /*

           * javactransfer.java

           * By dpwu

           * e-maildpwu_js@sina.com.cn

           */

          public class javactransfer

          {

            public String hypotenuse(String send_buf,String recv_buf,int errno)

            {

              return hypotenuse0(send_buf,recv_buf,errno);

            }

           

            private native String  hypotenuse0(String send_buf,String recv_buf,int errno);

           

            static

            {

              System.loadLibrary("javactransfer");//調用dll

            }

            public static void main( String[] args )

            {

           

               javactransfer obj= new javactransfer();

               System.out.println("");

               System.out.println("");

               System.out.println("       begin!");

               System.out.println("");

               System.out.println("");

               String javasend="發送中文chinese!";

               System.out.println(" java send:"+"["+javasend+"]");

          String javarecv=obj.hypotenuse("teststr",javasend,1); 

          //javasend傳含有中文字符串給C

          //javarecv接受C含有中的文字符串

               System.out.println(" java recv:"+"["+javarecv+"]");

               System.out.println("");

               System.out.println("");

               System.out.println("        end!");

             }

          }

           

           

           

          C實現代碼為:

          /*

           * javactransfer.c

           * By dpwu

           * e-maildpwu_js@sina.com.cn

           */

           

          #include <windows.h>

          #include "javactransfer.h"http://通過javah –jni javactransfer 生成

          #include <stdio.h>

          #include "stdlib.h"

          #include "string.h"

           

          char* jstringToWindows( JNIEnv *env, jstring jstr );

          jstring WindowsTojstring( JNIEnv* env, char* str );

           

          JNIEXPORT jstring JNICALL

          Java_javactransfer_hypotenuse0(JNIEnv *env,jobject obj,jstring send_buf,jstring recv_buf,jint errno)

          {

            char * Buf_Return;

           

            Buf_Return  =  (char*)malloc(1024);

           

            const char * recvtest = jstringToWindows( env, recv_buf );

          /*上句recvtest接收Java傳過來的中文字符串正確,如果改為下句,則出現亂碼:

          const char * recvtest = (*env)->GetStringUTFChars( env,recv_buf,0); 

          */

          printf( " c  recv  :[%s]\n" , recvtest);

           

            sprintf(Buf_Return,"接收中文chinese!");

            printf( "\n\n\n c send   :[%s]\n" , Buf_Return);

            recv_buf = WindowsTojstring(env ,Buf_Return);

          /*上句recv_bufwindows本地C中含有中文字符串給Java正確;如果改為下句出現亂碼:

          recv_buf = (*env)->NewStringUTF( env, Buf_Return );

            */

            return recv_buf;

          }

          char* jstringToWindows( JNIEnv  *env, jstring jstr )

          {

            int length = (*env)->GetStringLength(env,jstr );

            const jchar* jcstr = (*env)->GetStringChars(env,jstr, 0 );

            char* rtn = (char*)malloc( length*2+1 );

            int size = 0;

            size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );

            if( size <= 0 )

              return NULL;

            (*env)->ReleaseStringChars(env,jstr, jcstr );

            rtn[size] = 0;

            return rtn;

          }

           

          jstring WindowsTojstring( JNIEnv* env, char* str )

          {

            jstring rtn = 0;

            int slen = strlen(str);

            unsigned short* buffer = 0;

            if( slen == 0 )

              rtn = (*env)->NewStringUTF(env,str );

            else

            {

              int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );

              buffer = malloc( length*2 + 1 );

              if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )

                rtn = (*env)->NewString( env, (jchar*)buffer, length );

            }

            if( buffer )

            free( buffer );

            return rtn;

          }

          javactransfer.java,javactransfer.c均放在d:\javac目錄下


          javac javactransfer.java :
          編譯java源代碼;

          javah –jni javactransfer :生成頭文件;

          cl -Ic:\j2sdk1.4.2\include -Ic:\j2sdk1.4.2\include\win32  -LD javactransfer.c -Fejavactransfer.dll

          通過Microsoft Visual C++C源代碼生成dll文件,供java調用。

          執行結果如下:

           

          C++實現代碼為:

          /*

           * javactransfer.cpp

           * By dpwu

           * e-maildpwu_js@sina.com.cn

           */

           

          #include <windows.h>

          #include "javactransfer.h"http://通過javah –jni javactransfer 生成

          #include <stdio.h>

          #include "stdlib.h"

          #include "string.h"

           

          char* jstringToWindows( JNIEnv *env, jstring jstr );

          jstring WindowsTojstring( JNIEnv* env, char* str );

           

          JNIEXPORT jstring JNICALL

          Java_javactransfer_hypotenuse0(JNIEnv *env,jobject obj,jstring send_buf,jstring recv_buf,jint _tperrno)

           

          {

            char * Buf_Return;

            Buf_Return  =  (char*)malloc(1024);

           

            const char * ctest = jstringToWindows( env, recv_buf );

          /*

            如果把上句改為下句,C接收Java字符串時將出現亂碼:

            const char *ctest = (env)->GetStringUTFChars(  recv_buf , 0);

          */

            printf( " c  recv  :[%s]\n" , ctest);

           

            sprintf(Buf_Return,"接收中文chinese!");

            printf( "\n\n\n c send   :[%s]\n" , Buf_Return);

            recv_buf = WindowsTojstring(env ,Buf_Return);

          /*上句執行正確,如果把上句換成下句,Java在接收C字符串時出現亂碼

          recv_buf = (env)->NewStringUTF(Buf_Return);

          */

            return recv_buf;

          }

          char* jstringToWindows( JNIEnv  *env, jstring jstr )

          {

            int length = (env)->GetStringLength(jstr );

            const jchar* jcstr = (env)->GetStringChars(jstr, 0 );

            char* rtn = (char*)malloc( length*2+1 );

            int size = 0;

            size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );

            if( size <= 0 )

              return NULL;

            (env)->ReleaseStringChars(jstr, jcstr );

            rtn[size] = 0;

            return rtn;

          }

           

          jstring WindowsTojstring( JNIEnv* env, char* str )

          {

            jstring rtn = 0;

            int slen = strlen(str);

            unsigned short * buffer = 0;

            if( slen == 0 )

              rtn = (env)->NewStringUTF(str );

            else

            {

              int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );

              buffer = (unsigned short *)malloc( length*2 + 1 );

              if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )

                rtn = (env)->NewString(  (jchar*)buffer, length );

            }

            if( buffer )

            free( buffer );

            return rtn;

          }

          當為C++實現時,只需要在編譯時改為

          cl -Ic:\j2sdk1.4.2\include -Ic:\j2sdk1.4.2\include\win32 -LD javactransfer.cpp -Fejavactransfer.dll

           

          后話

          本文所述內容可以應用于復雜系統的改造,現有大型生產系統(例如:金融等)很多都是unix+C+tuxedo基于共享內存實現,而這些系統為了滿足安全和響應時間要求不可能在短期內完全丟棄,本文中提供的方法,可以和tuxedo客戶端通過VC++封裝成各種dll,這些dll可以在tuxedo本身很多優良特性的基礎上進行基于Java的開發,以用來解決新的基于WEB應用的需求。如有錯誤之處,請與筆者聯系:dpwu_js@sina.com.cn

           

          參考資料:David Wendt NLS strings and JNI

           WebSphere programmer, IBM

          posted on 2005-12-08 10:31 小叉 閱讀(1413) 評論(3)  編輯  收藏 所屬分類: 轉載
          評論:
          • # re: jNI在C++中亂碼解決問題  王起來 Posted @ 2008-03-01 23:03
            我想知道我的聊天記錄  回復  更多評論   

          • # re: jNI在C++中亂碼解決問題  王起來 Posted @ 2008-03-01 23:06
            我要找今天的聊天記錄  回復  更多評論   

          • # re: jNI在C++中亂碼解決問題  王起來 Posted @ 2008-03-01 23:15
            能不能找到245525117和641107652今天的聊天記錄  回復  更多評論   

           
          Copyright © 小叉 Powered by: 博客園 模板提供:滬江博客
          主站蜘蛛池模板: 临夏县| 新余市| 莲花县| 思茅市| 湄潭县| 利川市| 红河县| 金塔县| 尖扎县| 酒泉市| 志丹县| 菏泽市| 定远县| 西乌珠穆沁旗| 迁安市| 清涧县| 界首市| 冕宁县| 偃师市| 共和县| 浮梁县| 盐边县| 民和| 松原市| 桐梓县| 府谷县| 静乐县| 义乌市| 嘉鱼县| 孟连| 玉田县| 邢台县| 中阳县| 仪征市| 沈阳市| 斗六市| 鹤庆县| 武隆县| 遂昌县| 微博| 四川省|