Java and C pass the Chinese string through JNI
Introduction
This article provides a specific example, which shows that JAVA and C pass through the JNI passing parameters containing Chinese strings, solve Chinese garbled problems (double bytes or multi-bytes). This article gives the specific source code, explained the source code, and the C portion provides a complete code implemented by both C and C . And all code is tested in an experimental environment. The readers of this article must have a certain basis of Java and C (or C ).
lab environment
Windows XP (or Windows2000)
J2SDK1.4.2 / J2RE1.4.2
Microsoft Visualc 6.0
Environment variables need to be set after installing 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. JAR (J2SDK installed in C: /J2SDK1.4.2 directory)
Source code and code description
Java code:
/ *
* JavacTransfer.java
* By DPWU
* E-mail: dpwu_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"); // Call 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 = "Send Chinese Chinese!";
System.out.println ("Java Send:" "[" Javasend "]");
String Javarecv = Obj.hypotenuse ("Teststr", JavaSend, 1);
// javasend transmits a Chinese string to c
// javarecv Accepts C containing a word string
System.out.println ("Java Recv: " [" Javarecv "] ");
System.out.println ("");
System.out.println ("");
System.out.println ("end!");
}
}
C Implementation code is:
/ *
* JavacTransfer.c
* By DPWU
* E-mail: dpwu_js@sina.com.cn
* /
#include
#include
#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);
/ * The above sentence Recvtest receives the Chinese string of java passed correctly, if it is changed to the next sentence, there is garbled:
Const char * recvtest = (* env) -> GetStringutfchars (ENV, RECV_BUF, 0);
* /
Printf ("C RECV: [% S] / N", Recvtest);
Sprintf (buf_return, "receiving Chinese CHINESE!");
Printf ("/ N / N / N C Send: [% s] / N", buf_return);
RECV_BUF = WindowsTojstring (ENV, BUF_RETURN);
/ * The upper sentence RECV_BUF Biography Windows Local C contains Chinese string to Java correctly; if it is changed to the following sentence, garbled:
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 (MultibyToWideChar (CP_ACP, 0, (LPCSTR) STR, SLEN, (LPWSTR) Buffer, Length)> 0)
RTN = (* ENV) -> Newstring (ENV, (JCHAR *) Buffer, Length);
}
IF (buffer)
Free (buffer);
Return RTN;
}
If JavacTransfer.java, JavacTransfer.c is placed in a D: / javac directory
Do the following steps under the command operator:
Javac JavacTransfer.java: Compile Java source code;
Javah-Jni JavacTransfer: Generate header file;
Cl -ic: /j2sdk1.4.2/include -ic: /j2sdk1.4.2/include/win32-ld javacTransfer.c -fejavactransfer.dll
Generate a DLL file by Microsoft Visual C for Java calls.
The result is as follows:
Type: Java JavacTranfer can see the result
C implementation code is:
/ *
* javacTransfer.cpp
* By DPWU
* E-mail: dpwu_js@sina.com.cn
* /
#include
#include "javactransfer.h" // Generate through Javah -jni JavacTransfer
#include
#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);
/ *
If the above sentence is changed to the next sentence, the C will receive garbled when the Java string is received:
Const char * ctest = (ENV) -> getStringutfchars (Recv_buf, 0);
* /
Printf ("C RECV: [% S] / N", CTEST);
Sprintf (buf_return, "receiving Chinese CHINESE!");
Printf ("/ N / N / N C Send: [% s] / N", buf_return);
RECV_BUF = WindowsTojstring (ENV, BUF_RETURN);
/ * The sentence is executed correctly, if the sentence is changed to the following sentence, Java has garbled when receiving the C string
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 = MultibyToWideChar (CP_ACP, 0, (LPCSTR) STR, SLEN, NULL, 0);
Buffer = (unsigned short *) malloc (length * 2 1);
IF (MultibyToWideChar (CP_ACP, 0, (LPCSTR) STR, SLEN, (LPWSTR) Buffer, Length)> 0)
RTN = (ENV) -> Newstring ((Jchar *) Buffer, Length);
}
IF (buffer)
Free (buffer);
Return RTN;
}
When implementing C , you only need to change it when compiling:
Cl -ic: /j2sdk1.4.2/include -ic: /j2sdk1.4.2/include/win32-ld javacTransfer.cpp -fejavactransfer.dll
Later
The content described herein can be applied to complex systems, and there are many existing large-scale production systems (eg, finance, etc.) are all Unix C Tuxedo is based on shared memory implementation, and these systems are impossible to meet security and response time requirements. Fully discarded, the methods provided herein, can be encapsulated into various DLLs with the Tuxedo client through VC , which can develop Java-based development on the basis of tuxedo itself, to solve new web applications. Demand. If there is any mistake, please contact the author: dpwu_js@sina.com.cn.
Reference: David Wendt "NLS Strings and JNi"
WebSphere Programmer, IBM