programing

JNI에서 C 구조를 Java 코드로 주고받는 방법은 무엇입니까?

coolbiz 2023. 1. 17. 21:44
반응형

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그러나 실제로는 구조물을 반환하고 있습니다.MyStructCheckJ에서 실행한 경우NI가 네이블로 되어 있으면 VM이 큰 소리로 불만을 제기하고 중단됩니다.당신의.processData()함수는 또한 전달되는 내용에 대해 상당히 혼란스러워할 것입니다.arguments.

A jobject는 관리대상 힙상의 객체입니다.선언된 필드 앞 또는 뒤에 추가 정보를 포함할 수 있으며 필드를 메모리에 특정 순서로 배치할 필요가 없습니다.따라서 Java 클래스 위에 C 구조를 매핑할 수 없습니다.

이 문제를 해결하는 가장 간단한 방법은 이전 답변에서 확인되었습니다.jobjectJNI 기능이 있습니다.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는 이에 대처하는 솔루션을 가지고 있습니다.

  1. Java와 C++ 양쪽에서 멤버 변수만 입력하면 클래스를 만들 수 있습니다.C++ 구조는 실제로는 퍼블릭 데이터 멤버가 포함된 클래스일 뿐입니다.만약 당신이 정말로 순수한 C에 있다면, 이제 그만 읽으세요.
  2. IDE를 사용하여 멤버 변수의 세터 및 게터를 자동으로 만듭니다.
  3. Java 클래스에서 C 헤더 파일을 생성하려면 javah를 사용합니다.
  4. C++측에서 편집하여 생성된 헤더파일과 세터 및 게터를 일치시킵니다.
  5. JNI 코드를 입력합니다.

이는 이상적인 솔루션은 아니지만 시간을 절약할 수 있으며 편집 가능한 골격을 제공할 수 있습니다.이 기능은 IDE에 추가할 수 있지만 큰 요구가 없으면 아마 실현되지 않을 것입니다.대부분의 IDE는 서로 대화하는 것은 고사하고 혼합 언어 프로젝트도 지원하지 않습니다.

언급URL : https://stackoverflow.com/questions/3923299/how-to-pass-c-structs-back-and-forth-to-java-code-in-jni

반응형