JNI에서 C 구조를 Java 코드로 주고받는 방법은 무엇입니까?
JNI를 통해 호출하는 몇 가지 C 함수와 동일한 유형의 구조에 포인터를 할당/해제하여 래퍼 처리를 좀 더 쉽게 할 수 있도록 하는 몇 가지 다른 함수가 있습니다.놀랍게도 JNI 문서에는 C 구조의 취급 방법에 대해 거의 기술되어 있지 않습니다.
C 헤더 파일은 다음과 같습니다.
typedef struct _MyStruct {
float member;
} MyStruct;
MyStruct* createNewMyStruct();
void processData(int *data, int numObjects, MyStruct *arguments);
대응하는 JNI C 래퍼 파일에는 다음이 포함됩니다.
JNIEXPORT jobject JNICALL
Java_com_myorg_MyJavaClass_createNewMyStruct(JNIEnv *env, jobject this) {
return createNewMyStruct();
}
JNIEXPORT void JNICALL
Java_com_myorg_MyJavaClass_processData(JNIEnv *env, jobject this, jintArray data,
jint numObjects, jobject arguments) {
int *actualData = (*env)->GetIntArrayElements(env, data, NULL);
processData(actualData, numObjects, arguments);
(*env)->ReleaseIntArrayElements(env, data, actualData, NULL);
}
마지막으로 대응하는 Java 클래스:
public class MyJavaClass {
static { System.loadLibrary("MyJniLibrary"); }
private native MyStruct createNewMyStruct();
private native void processData(int[] data, int numObjects, MyStruct arguments);
private class MyStruct {
float member;
}
public void test() {
MyStruct foo = createNewMyStruct();
foo.member = 3.14159f;
int[] testData = new int[10];
processData(testData, 10, foo);
}
}
유감스럽게도 이 코드는 JVM을 히트시킨 직후에 크래시 합니다.createNewMyStruct()
JNI는 처음이라서 뭐가 문제인지 모르겠어요.
편집: C코드는 매우 바닐라 C이며, 테스트도 잘 되어 있고, iPhone 프로젝트로부터 이식된 것입니다.또한 이 프로젝트는 Android NDK 프레임워크를 사용하여 Android 프로젝트에서 네이티브 C 코드를 JNI 내에서 실행할 수 있습니다.하지만 NDK의 문제는 아니라고 생각합니다.JNI 셋업/초기화 에러인 것 같습니다.
C구조와 같은 멤버와 같은 자바 클래스를 만들 필요가 있으며, C 코드를 통해 C 코드 및 '맵'를 통해 C 코드를 생성해야 합니다.Infield, 환경 >환경 > 환경 > Get 필드, 환경 > 환경 >플로어필드, 그래서, 수동 노동력, 여러 수동노동자(http://code.google.com/p/jnaerator) 및 SWGIGHEROE 및 SWGIGHEGE)를 자동화할 수 있기를 바랍니다.http://www.swig.org/) 를 참조해 주세요.둘 다 장단점이 있기 때문에 선택은 당신에게 달려 있습니다.
왜 이렇게 망가져?Java_com_myorg_MyJavaClass_createNewMyStruct
반환을 선언하다jobject
그러나 실제로는 구조물을 반환하고 있습니다.MyStruct
CheckJ에서 실행한 경우NI가 네이블로 되어 있으면 VM이 큰 소리로 불만을 제기하고 중단됩니다.당신의.processData()
함수는 또한 전달되는 내용에 대해 상당히 혼란스러워할 것입니다.arguments
.
A jobject
는 관리대상 힙상의 객체입니다.선언된 필드 앞 또는 뒤에 추가 정보를 포함할 수 있으며 필드를 메모리에 특정 순서로 배치할 필요가 없습니다.따라서 Java 클래스 위에 C 구조를 매핑할 수 없습니다.
이 문제를 해결하는 가장 간단한 방법은 이전 답변에서 확인되었습니다.jobject
JNI 기능이 있습니다.Java 또는 를 사용하여 개체를 할당합니다.NewObject
,Get
/Set
오브젝트 필드(적절한 콜 포함)를 참조해 주세요.
여기서 "사기"하는 방법은 다양합니다.를 들어, '어울리다', '어울리다', '어울리다'를 수 .byte[]
에서는 Java를 하고 있습니다.sizeof(struct MyStruct)
한 후 ""를 사용합니다.GetByteArrayElements
이치노특히 Java 쪽에서 필드에 액세스하려는 경우 약간 추합니다.
C 구조는 변수의 집합입니다(일부는 함수 포인터입니다).java로 패스하는 것은 좋은 생각이 아닙니다.일반적으로 포인터처럼 좀 더 복잡한 타입을 자바에 넘기는 방법이 문제입니다.
JNI book에서는 포인터/구조를 네이티브로 유지하고 조작을 Java로 내보내는 것이 좋습니다.당신은 유용한 기사를 읽을 수 있습니다.JavaTM Native Interface Programmer's Guide와 Specification을 읽었습니다. 9.5 Peer Class는 이에 대처하는 솔루션을 가지고 있습니다.
- Java와 C++ 양쪽에서 멤버 변수만 입력하면 클래스를 만들 수 있습니다.C++ 구조는 실제로는 퍼블릭 데이터 멤버가 포함된 클래스일 뿐입니다.만약 당신이 정말로 순수한 C에 있다면, 이제 그만 읽으세요.
- IDE를 사용하여 멤버 변수의 세터 및 게터를 자동으로 만듭니다.
- Java 클래스에서 C 헤더 파일을 생성하려면 javah를 사용합니다.
- C++측에서 편집하여 생성된 헤더파일과 세터 및 게터를 일치시킵니다.
- JNI 코드를 입력합니다.
이는 이상적인 솔루션은 아니지만 시간을 절약할 수 있으며 편집 가능한 골격을 제공할 수 있습니다.이 기능은 IDE에 추가할 수 있지만 큰 요구가 없으면 아마 실현되지 않을 것입니다.대부분의 IDE는 서로 대화하는 것은 고사하고 혼합 언어 프로젝트도 지원하지 않습니다.
언급URL : https://stackoverflow.com/questions/3923299/how-to-pass-c-structs-back-and-forth-to-java-code-in-jni
'programing' 카테고리의 다른 글
왜 JavaScript 평가 기능을 사용하는 것이 나쁜 생각일까요? (0) | 2023.01.17 |
---|---|
c 파일 간에 글로벌 변수를 공유하려면 어떻게 해야 합니까? (0) | 2023.01.17 |
하위 목록에 예기치 않게 반영된 목록 변경 사항 목록 (0) | 2023.01.17 |
PHP 어레이의 예에서는 왜 말미에 쉼표가 남습니까? (0) | 2023.01.17 |
Composer 실행 시 xdebug 사용 안 함 (0) | 2023.01.17 |