2013-01-16 1 views
0

이 문제의 일부는 여기에있는 일부 게시물에서 알 수 있습니다. 나는 그 부분을 살펴보고 행운을 가지고 테스트했습니다.JNA - byref 인수로 구조 배열을 사용하십시오.

CBadgeData 구조로 구현됩니다
int elc_GetBadges(int nHandle, char* cErr, int* nRecCount, CBadgeData** arr) 

은 다음과 같습니다 :

package test.elcprog; 

import java.util.Arrays; 
import java.util.List; 
import com.sun.jna.Pointer; 
import com.sun.jna.Structure; 

public class CBadgeData extends Structure{ 

    public static class ByReference extends CBadgeData implements Structure.ByReference { } 

    public int nBadgeID, nTrigger, nExtraData; 
    public String cName; 

    public CBadgeData(Pointer pointer){ 
     super(pointer); 
    } 

    public CBadgeData(){ } 

    public String ToString() { 
     return nBadgeID + "," + nTrigger + "," + nExtraData + "," + cName; 
    } 

    @Override 
    protected List getFieldOrder() { 
     String[] s = new String[]{"nBadgeID","nTrigger","nExtraData","cName"}; 
     return Arrays.asList(s); 
    } 
} 

내 마지막 시도는이 인수를 정교하고 나는 결과와 함께 제공된 CBadgeData 구조 배열를 채워야이 네이티브 메소드 서명이 이 메소드를 다음과 같이 호출하십시오 :

CBadgeData.ByReference[] badges = new CBadgeData.ByReference[max_items]; 
new CBadgeData.ByReference().toArray(badges); 
int ret = inst.elc_GetBadges(handle, err, recCount, badges); 

세분화 오류로 실패합니다.

내 질문 여기 elc_GetBadges으로 전화 할 때 CBadgeData** 네이티브에 대한 인수로 Java 형식을 제공해야합니까?

편집 -1-

작동하지 않았다 (또는 널 포인터를 종료하지 않고) 배열 자신을 채우기 추가 원세그 충돌을 일으켰습니다.

Pointer[] pointers = new Pointer[max_items]; 
for(int i=0; i<max_items; i++){ 
    pointers[i] = new CBadgeData.ByReference().getPointer(); 
} 
int ret = inst.elc_GetBadges(handle, err, recCount, pointers); 

이것은 오류의 원인이 없지만이 있어야 돌아 오는 구조체에 대한 변경이 경우 4 개 항목을 포함하지 보인다 :

int bid = new CBadgeData(pointers[i]).nBadgeID; // this returns null for all items 

을 그때 technomage 제안 인수로 포인터 [] 사용 Seg로 유도 된 구조체에 명시 적 read()/write()를 사용하면 다시 읽습니다 (읽음) : 나는 아직도 여기에 무엇이 없습니까?


편집 -2-

흥미롭게도 - 네이티브 메소드를 호출 한 후, 올바른 결과를 얻을, 직접 Memory.get를 사용하여 :

Memory m= (Memory)pointers[0]; 
System.out.println("1st int: "+m.getInt(0)); // this gets 24289 which is 5ee1 
System.out.println("2nd int: "+m.getInt(4)); // this gets 3 
System.out.println("3rd int: "+m.getInt(8)); // this gets 255 
System.out.println("String: "+m.getString(12)); // this gets "Badge[5EE1]" as supposed 

하지만 여전히 충돌합니다 read(). 이견있는 사람?

+0

메모리 덤프가 주소 순서로 바이트를 인쇄합니다. int (little-endian)에서 최하위 바이트가 먼저 나타나므로 [e15e0000]은 값 00005ee1을 나타냅니다. 이것을 바이트 순서라고하는데, 정렬과 같은 것이 아닙니다. – technomage

+0

기본 및 Java 구조 정의를 게시하십시오. – technomage

+0

저는 (q에서 삭제되었습니다) 이해합니다. 'Memory() '를 읽는 동안'read()'에 문제가있을 수 있습니다. – Aditi

답변

1

나는 CBadgeData ** 입력이 CBadgeData에 대한 포인터의 배열이되도록 의도되었다고 추측합니다.

이와 같이 Structure.ByReference 태그 지정이 정확합니다.

Structure.toArray()은 아마도 이 아니며 여기서이 아니거나 적어도 필요하지 않습니다 (메모리에 구조체 블록을 연속적으로 할당합니다). CBadgeData.ByReference 인스턴스로 배열을 채울 수 있습니다.

아마도 피 호출자가 배열 끝에 NULL 포인터를 기대합니까? 수신자에게 배열 길이에 대한 또 다른 표시기가 보이지 않습니다.

CBadgeData.ByReference[] badges = new CBadgeData.ByReference[max_items+1]; 
for (int i=0;i < badges.length-1;i++) { 
    badges[i] = new CBadgeData.ByReference(); 
} 
badges[badges.length-1] = null; 

정말 확실합니다.어떠한 이유로 든 Structure.ByReference[]을 처리하는 버그가있는 경우, 나는 Pointer[]이 신뢰할 만하며 같은 것을 할 것이라는 것을 알고 있습니다.

편집

당신이 (Structure.ByReference[]가 작동하지 않을 경우 프로젝트 사이트에 버그를 게시하시기 바랍니다), 당신이 있기 때문에, 수동으로 네이티브 함수 호출 후 전/Structure.write/read를 호출해야합니다 대신 Structure.ByReference[]Pointer[]를 사용하는 경우 JNA는 포인터가 원시 메모리와 동기화되어야하는 구조를 참조하는지 알 수 없습니다. 그러나 Structure.ByReference[]을 사용할 때 충돌의 원인은 호출 후 JNA가 자동으로 Structure.read()을 호출하고 명시 적으로 호출 할 때와 동일한 오류를 유발했기 때문입니다.

읽을 때 segfault가 발생하면 구조 필드가 제대로 정렬되거나 정의되지 않았거나 제대로 읽을 수없는 데이터가 손상되었을 가능성이 적습니다. 이를 진단하려면 jna.dump_memory=true을 설정하고 Structure.write()을 호출 한 후 구조체를 인쇄하여 원하는대로 구조체의 내용이 표시되는지 확인합니다. 가능하다면 네이티브 및 JNA 형식의 구조를 여기에 게시하는 것도 도움이 될 것입니다.

+0

고마워요! 귀하의 제안을 따르는 제 '응답'을 참조하십시오. 전체적인 내용으로 답변에 답변 할 수없는 이유는 무엇입니까? – Aditi

+0

일반적으로 원래 질문에 별첨을 추가하는 것이 가장 바람직합니다. – technomage

+0

- ** EDIT -2 - **를 참조하십시오. – Aditi