Mã cpp của tôi chứa hàm jni mà tôi muốn chuyển đổi thành const char*. Đây là mã tôi đang sử dụng
bên ngoài "C" {
void Java_com_sek_test_JNITest_printSomething(JNIEnv * env, jclass cl, jstring str) {
const char* mystring = env->GetStringUTFChars(env, str, 0);
PingoScreen::notify();
}
Tôi gặp lỗi
không có chức năng khớp để gọi tới '_JNIEnv::GetStringUTFChars(JNIEnv*&, _jstring*&, int)
我做错了什么?
Có một số điều chưa hoàn toàn đúng về mã và cách tiếp cận của bạn:
- 如您所见,
(env*)->JNIFunc(env,...)
Trong C++ thì phải như vậy env->JNIFunc(...)
.jni.h của nhà cung cấp (Google Android) đơn giản hóa cú pháp C++ thay vì cú pháp C.
- Bạn đã không gọi hàm "phát hành" (ReleaseStringUTFChars) tương ứng với hàm "cố định" (GetStringUTFChars). Điều này rất quan trọng vì việc ghim các đối tượng làm giảm hiệu suất bộ nhớ của trình thu gom rác JVM.
- bạn đã hiểu lầm
GetStringUTFChars
tham số cuối cùng. Nó là một con trỏ tới tham số đầu ra. Kết quả không thú vị lắm nên bỏ qua nullptr
.
- bạn đang sử dụng tay cầmÔn lại Mã hóa UTF-8 (
GetStringUTFChars
v.v.) Các hàm JNI. Không cần thiết phải sử dụng mã hóa này. Các lớp Java rất giỏi trong việc chuyển đổi mã hóa. Chúng cũng cho phép bạn kiểm soát điều gì sẽ xảy ra khi một ký tự không thể được mã hóa trong mã hóa đích. (Mặc định là chuyển đổi nó thành ?
。)
- Tham chiếu đối tượng JVM (
chuỗi ký tự
) được chuyển đổi thành điểm lưu trữ một byte (char*
) cần nhiều sự hoàn thiện. Bạn có thể muốn chuyển đổi JVM thành một mã hóa mặc định cụ thể hoặc của hệ điều hành java.lang.String
Các ký tự được sao chép dưới dạng chuỗi "gốc". Chuỗi Java chứa các ký tự Unicode được mã hóa bằng UTF-16. Android thường sử dụng bộ ký tự Unicode được mã hóa UTF-8. Nếu bạn cần cái gì khác, bạn có thể sử dụng Bộ ký tự
Đối tượng chỉ định nó.
- Ngoài ra, trong C++, sử dụng STL
std::chuỗi
Sẽ thuận tiện hơn khi lưu một chuỗi các byte được đếm của một chuỗi. bạn có thể nhận đượcmột con trỏ tới bộ đệm kết thúc nullNếu cần, từ std::chuỗi
.
Hãy nhớ đọc Android Lời khuyên của JNI .
Đây là cách triển khai chức năng của bạn, cho phép triển khai JVM của nhà cung cấp chọn mã hóa đích (UTF-8 cho Android):
bên ngoài "C" JNIEXPORT void Java_com_sek_test_JNITest_printS Something
(JNIEnv * env, jclass cl, jstring str) {
// TODO kiểm tra các ngoại lệ của JVM khi thích hợp
// javap -s -public java.lang.String |
const auto stringClass = env->FindClass("java/lang/String");
const auto getBytes = env->GetMethodID(stringClass, "getBytes", "()[B");
const auto stringJbytes = (jbyteArray) env->CallObjectMethod(str, getBytes);
const auto length = env->GetArrayLength(stringJbytes);
const auto pBytes = env->GetByteArrayElements(stringJbytes, nullptr);
std::string s((char *)pBytes, độ dài);
env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT);
const auto pChars = s.c_str(); // nếu bạn thực sự cần một con trỏ
}
Tuy nhiên, tôi có thể gọi phía Java String.getBytes
, xác định phương thức gốc để lấy mảng byte thay vì chuỗi.
(Tất nhiên, việc triển khai bằng GetStringUTFChars có hiệu quả đối với một số tập hợp con chuỗi Unicode, nhưng tại sao lại áp đặt các hạn chế bí truyền và không cần thiết?)
Tôi là một lập trình viên xuất sắc, rất giỏi!