JNA를 사용하여 C 배열을 Java로 되돌립니다
문제
C에 너무 익숙하지는 않지만 Java 코드에서 C 라이브러리를 사용해야합니다. DLL을 만들었고 잘 액세스 할 수 있지만 C 코드에서 Java 코드로의 INT 배열을 반환하려고합니다.
CI에서는 단순히 배열에 대한 포인터를 반환 할 수 있다고 생각했지만 Java 코드에서 기대하는 것처럼 작동하지 않습니다. C 코드는 다음과 같습니다.
int * getConusXY(double latitude, double longitude) {
maparam stcprm;
double reflat = 25, reflon = -95,
lat1 = 20.191999, lon1 = -121.54001,
x1 = 0, y1 = 0, x2 = 1073, y2 = 689,
gsize = 5.079, scaLat = 25, scaLon = -95, orient = 0;
double x, y;
int* xy;
xy = malloc(2 * sizeof *xy);
stlmbr(&stcprm, reflat, reflon);
stcm1p(&stcprm, x1, y1, lat1, lon1, scaLat, scaLon, gsize, orient);
cll2xy(&stcprm, latitude, longitude, &x, &y);
xy[0] = (int) x;
xy[1] = (int) y;
return xy;
}
내가 이것을 c ++로 테스트하면
int* xy = getConusXY(33.92, -84.33);
cout << xy[0] << " " << xy[1] << endl;
그런 다음 잘 작동하고 예상대로 값 739, 255를 얻습니다.
JNA 패키지와 함께 Java로 사용하려고합니다 (그러나 이것은 나에게 739, -16777214) : :
public class DmapFDllLibrary {
interface DmapFLibrary extends Library {
DmapFLibrary INSTANCE = (DmapFLibrary) Native.loadLibrary("DmapFDll",
DmapFLibrary.class);
IntByReference getConusXY(double latitude, double longitude);
}
public static void main(String... strings) {
IntByReference xy_ref = DmapFLibrary.INSTANCE.getConusXY(33.92, -84.33);
Pointer p = xy_ref.getPointer();
System.out.println(p.getInt(0) + " " + p.getInt(1));
}
}
JNA 문서에서는 다음과 같은 원시 배열이 표시됩니다. int *buf
매핑 될 것입니다 int[] buf
Java에서는하지만 반환 유형을 변경하려고 할 때 IntByReference
에게 int[]
그런 다음 불법 행위를 얻습니다.
C에서 배열을 올바르게 반환하는지 또는 Java에서 올바르게 액세스하지 않는지 모르겠습니다. 모든 도움이 감사하겠습니다.
해결책
반환 된 배열은 절대로 해제/삭제되지 않기 때문에 그러한 함수를 사용하지 않을 것입니다. 할 수 있다면 C 함수를 변경하려고합니다.
void myFunc(Pointer resuls, int numBytes, byte const * returnArray)
다른 팁
C 코드 괜찮습니다 그러나 더 나아질 것입니다 (다른 의견 참조) 주요 문제는 내가 Java를 잘못 사용하고 있다는 것입니다. getInt()
포인터를위한 방법. 내가 사용 했어야했던 것 같다 getIntArray()
.
더 길고 아마도 더 명확한 설명은 Java 기능을 프로토 타입하여 포인터 (또는 포인터의 후계자)를 받는다는 것입니다.
byte[] myFunc(Pointer result, int numBytes);
콜백 자체를 만들 때 GetByTearRay (int) 또는 다른 GetArray 중 하나를 사용합니다.
byte[] myFunc(Pointer resuls, int numBytes)
{
return Pointer.getByteArray(numBytes);
}