回答編集履歴

4

TEXT マクロ対応について追記

2018/10/23 17:51

投稿

atata0319
atata0319

スコア881

test CHANGED
@@ -121,3 +121,105 @@
121
121
  }
122
122
 
123
123
  ```通常は JNI でもプラットフォーム互換を考慮して iconv 等を使用しますが、今回は MinGW 限定ということで Windows API を使用しています。malloc/free でコンパイルエラーになる場合、適宜必要なヘッダを追記してください。
124
+
125
+
126
+
127
+ ---
128
+
129
+ **2018/10/24 追記**
130
+
131
+ TEXT マクロ(回答では _TEXT ですが)を使用する場合、明確にコードを分ける必要がでてきます。UTF-8 の文字列は char の配列であるため、これを Shift-JIS の char 配列 または wchar_t の配列に変換することになります。
132
+
133
+ ```C
134
+
135
+ #include <windows.h>
136
+
137
+ #include <tchar.h>
138
+
139
+
140
+
141
+ #include "jni.h"
142
+
143
+ #include "org_yukkuri_jyl_base_JylConsole.h"
144
+
145
+
146
+
147
+ JNIEXPORT void JNICALL Java_org_yukkuri_jyl_base_JylConsole_nput( JNIEnv *env, jclass cls, jstring message )
148
+
149
+ {
150
+
151
+ /* UTF-8文字列は TCHAR* ではなく char* に格納する。*/
152
+
153
+ const char* cmsg = (*env)->GetStringUTFChars( env, message, 0 );
154
+
155
+
156
+
157
+ #ifdef _UNICODE
158
+
159
+ /*
160
+
161
+ * UTF-8 => Unicode
162
+
163
+ * _UNICODE の場合、wchar_t にまで変換すれば問題ない。
164
+
165
+ */
166
+
167
+ int widecharlength = MultiByteToWideChar( CP_UTF8, 0, cmsg, -1, NULL, 0 );
168
+
169
+ wchar_t* msg = malloc( sizeof(wchar_t) * (widecharlength + 1) );
170
+
171
+ MultiByteToWideChar( CP_UTF8, 0, cmsg, -1, msg, widecharlength + 1 );
172
+
173
+ #else
174
+
175
+ /*
176
+
177
+ * UTF-8 => Unicode
178
+
179
+ * _UNICODE の定義がない場合、char に変換する必要があるため、UTF-8 => Unicode => Shift-JIS の順に変換する。
180
+
181
+ */
182
+
183
+ int widecharlength = MultiByteToWideChar( CP_UTF8, 0, cmsg, -1, NULL, 0 );
184
+
185
+ wchar_t* wmsg = malloc( sizeof(wchar_t) * (widecharlength + 1) );
186
+
187
+ MultiByteToWideChar( CP_UTF8, 0, cmsg, -1, wmsg, widecharlength + 1 );
188
+
189
+
190
+
191
+ /* Unicode => Shift-JIS */
192
+
193
+ int sjislength = WideCharToMultiByte( CP_ACP, 0, wmsg, -1, NULL, 0, NULL, NULL );
194
+
195
+ char* msg = malloc( sjislength + 1 );
196
+
197
+ WideCharToMultiByte( CP_ACP, 0, wmsg, -1, msg, sjislength + 1, NULL, NULL );
198
+
199
+
200
+
201
+ free( wmsg );
202
+
203
+ #endif
204
+
205
+
206
+
207
+ _tprintf( _TEXT("%s"), msg );
208
+
209
+
210
+
211
+ /* 確保した文字列のメモリを解放する。*/
212
+
213
+ free( msg );
214
+
215
+
216
+
217
+ (*env)->ReleaseStringUTFChars( env, message, cmsg );
218
+
219
+ }
220
+
221
+ ```上の例では _UNICODE マクロしか対応していませんが、ヘッダファイルの中にはアンダースコア無しの UNICODE マクロで記載されているものもあります。コンパイル時には両方指定することをお勧めします。Unicode でコンパイルしない場合、当然ですが両方指定しないことになります。
222
+
223
+
224
+
225
+ この場合、当然ですが最初にあげているコマンドプロンプトの文字コードを UTF-8 にする対応では対応できなくなります。

3

回答を追記

2018/10/23 17:51

投稿

atata0319
atata0319

スコア881

test CHANGED
@@ -37,3 +37,87 @@
37
37
  ```
38
38
 
39
39
  上記以外の問題がある場合、質問に追記してください。
40
+
41
+
42
+
43
+ ---
44
+
45
+ **2018/10/23 追記**
46
+
47
+ 日本語を表示する必要がある場合、いろいろやり方はありますが、代表的な2件を紹介しておきます。
48
+
49
+
50
+
51
+ ### 1.コマンドプロンプトのコードページを UTF-8 に変更
52
+
53
+ コマンドプロンプトのコードページを UTF-8 に変更すると GetStringUTFChars の戻り値である文字列を直接出力することができます。
54
+
55
+ ```cmd
56
+
57
+ chcp 65001
58
+
59
+ ```この場合、元のソースを修正する必要はありません。
60
+
61
+ ### 2.UTF-8 を Shift-JIS に変換して出力
62
+
63
+ コマンドプロンプトはもともと Shift-JIS なので UTF-8 文字列を Shift-JIS に変換して出力すれば問題ありません。以下のようなコードになります。
64
+
65
+ ```C
66
+
67
+ #include <windows.h>
68
+
69
+ #include <stdio.h>
70
+
71
+
72
+
73
+ #include "jni.h"
74
+
75
+ #include "org_yukkuri_jyl_base_JylConsole.h"
76
+
77
+
78
+
79
+ JNIEXPORT void JNICALL Java_org_yukkuri_jyl_base_JylConsole_nput( JNIEnv *env, jclass cls, jstring message )
80
+
81
+ {
82
+
83
+ const char* cmsg = (*env)->GetStringUTFChars( env, message, 0 );
84
+
85
+
86
+
87
+ // UTF-8 => Unicode
88
+
89
+ int widecharlength = MultiByteToWideChar( CP_UTF8, 0, cmsg, -1, NULL, 0 );
90
+
91
+ wchar_t* wmsg = malloc( sizeof(wchar_t) * (widecharlength + 1) );
92
+
93
+ MultiByteToWideChar( CP_UTF8, 0, cmsg, -1, wmsg, widecharlength + 1 );
94
+
95
+
96
+
97
+ // Unicode => Shift-JIS
98
+
99
+ int sjislength = WideCharToMultiByte( CP_ACP, 0, wmsg, -1, NULL, 0, NULL, NULL );
100
+
101
+ char* msg = malloc( sjislength + 1 );
102
+
103
+ WideCharToMultiByte( CP_ACP, 0, wmsg, -1, msg, sjislength + 1, NULL, NULL );
104
+
105
+
106
+
107
+ printf( "%s", msg );
108
+
109
+
110
+
111
+ // 確保した文字列のメモリを解放する。
112
+
113
+ free( wmsg );
114
+
115
+ free( msg );
116
+
117
+
118
+
119
+ (*env)->ReleaseStringUTFChars( env, message, cmsg );
120
+
121
+ }
122
+
123
+ ```通常は JNI でもプラットフォーム互換を考慮して iconv 等を使用しますが、今回は MinGW 限定ということで Windows API を使用しています。malloc/free でコンパイルエラーになる場合、適宜必要なヘッダを追記してください。

2

コードの誤りを修正

2018/10/22 16:24

投稿

atata0319
atata0319

スコア881

test CHANGED
@@ -30,9 +30,9 @@
30
30
 
31
31
  ```C
32
32
 
33
- (*env)->GetStringUTFChars( message, 0 );
33
+ (*env)->GetStringUTFChars( env, message, 0 );
34
34
 
35
- (*env)->ReleaseStringUTFChars( message, cmsg );
35
+ (*env)->ReleaseStringUTFChars( env, message, cmsg );
36
36
 
37
37
  ```
38
38
 

1

誤字を修正

2018/10/21 18:54

投稿

atata0319
atata0319

スコア881

test CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  ```
12
12
 
13
- また、提示されているコードで言えば、strdup 自体不要です。以下の Wiki ページのように直接 printf して問題ありません。※日本語が入っていない場合
13
+ また、提示されているコードで言えば、strdup 自体不要です。以下の wikipedia のように直接 printf して問題ありません。※日本語が入っていない場合
14
14
 
15
15
  [https://ja.wikipedia.org/wiki/Java_Native_Interface](https://ja.wikipedia.org/wiki/Java_Native_Interface)
16
16
 
@@ -36,4 +36,4 @@
36
36
 
37
37
  ```
38
38
 
39
- 上記以外の問題が発生した場合、質問に追記ください。
39
+ 上記以外の問題がある場合、質問に追記してください。