2017-02-08 16 views
1

Я пишу приложение Java, которое будет иметь доступ к C++ dll usnig JNA. Поэтому я подготовил C dll для связи между dll JNA и C++ thrid. У меня есть эти два структур: кодКак передать структуру, содержащую char * в java, используя JNA и избежать копирования данных?

C:

struct Struct1 
    { 
    uint32_t Size; 
    unsigned char* Data; 
    }; 
    struct Struct2 
    { 
    uint32_t Struct1_Nbr; 
    Struct1* struct1_elements; 
    }; 
    bool Open(char* fileName, Struct2** struct2); 

Теперь я пишу соответствующую ЮНУ коды приложения Java, и я хочу, чтобы получить доступ к «неподписанному символу * Data» без копирования этих данных, как это большое количество данных. Как я могу использовать типы «Память» или «Указатель» для выполнения этой задачи?

Вот моя попытка:

public class Test 
    { 
    public static class Struct1 extends com.sun.jna.Structure {   
    public Struct1(){} 
    public Struct1(Pointer pointer){ 
     super(pointer); 
     read(); 
    } 

    public static class Struct1ByValue extends Struct1 implements com.sun.jna.Structure.ByValue{}; 
    public int Size; 
    public Memory Data; 
    public static class Struct1ByReference extends Struct1 implements com.sun.jna.Structure.ByReference{} 

    @Override 
    protected List getFieldOrder() { 
     // TODO Auto-generated method stub 
     return Arrays.asList("Size", "Data"); 
    }; 

public static class Struct2 extends com.sun.jna.Structure {  
    public Struct2(){} 
    public Struct2 (Pointer pointer){ 
     super(pointer); 
     read(); 
    } 
    public int Struct2_Nbr; 
    public Struct1.Struct1ByReference struct1_elements = new Struct1.Struct1ByReference(); 

    public static class Struct2ByValue extends Struct2 implements com.sun.jna.Structure.ByValue{}; 
    public static class Struct2ByReference extends Struct2 implements com.sun.jna.Structure.ByReference{} 

    @Override 
    protected List getFieldOrder() { 
     // TODO Auto-generated method stub 
     return Arrays.asList("Struct1_Nbr", "struct1_elements")); 
    }; 
} 
    public interface StructureProtocol extends com.sun.jna.Library{ 
    Boolean Open(String fileName, PointerByReference struct2); 
    } 
    public StructureProtocol lib; 
    public Test(){ 
    this.lib = (StructureProtocol) Native.loadLibrary("TestAPI", StructureProtocol.class); 
} 

    public static void main(String[] args) { 

      Test test = new Test(); 
    PointerByReference pref = new PointerByReference(); 

    test.lib.Open("filePath", pref); 
    Pointer ptr = pref.getValue(); 
    Struct2 struct2= new Struct2(ptr); 
    Struct1[] struct1_array= (Struct1[])(struct2.struct1_elements).toArray(struct2.struct1_Nbr); 
    System.out.println("struct1_array[0]: Size = " + struct1_array[0].Size); 
    System.out.println("struct1_array[0]: Data= " + struct1_array[0].Data); 
    } 
    } 

Любые советы будут очень высокую оценку.

+0

Какова твоя роль? Ошибка? Неожиданный результат? – Alex

+0

Я получаю ожидаемый результат: System.out.println ("Struct2.struct1_Nbr ==" + struct2.struct1_Nbr); возвращает Struct2.struct1_Nbr == 0. поэтому у меня есть exeption в этой инструкции «Struct1 [] struct1_array = (Struct1 []) (struct2.struct1_elements) .toArray (struct2.struct1_Nbr);" – benayedh

ответ

0

Вот мой Solutiuon, первый проект:

  1. Объявите класс в Java, который расширяет структуру

    (com.sun.jna.Structure)

    (все поля в классе должны быть быть общедоступными или вы получаете ошибку, что размер th е структура расширенный класс не может быть измерен)

    public class Struct1 extends Structure{ 
        public int Size; 
        public String Data; 
    } 
    
  2. Declare и определить метод в C Dll, которая принимает указатель на структуру в качестве аргумента (я создал структуру и наполнил ее значением для тестирования)

    void __declspec(dllexport) GetStruct(Struct1* a){ 
    Struct1 s; 
    s.Size = 9; 
    s.Data = "Output"; 
    *a = s; 
    } 
    
  3. Я предполагаю, что вы уже успешно подключили приложение Java к DLL с, так что я пропустить эту часть (если мое предположение неверно, скажите мне в комментариях, и я редактировать свой ответ)

  4. Если вы добавите t HESE строки в код Java (примечание cdll является дескриптор моей библиотеки C)

    Struct1 test = new Struct1(); 
    cdll.GetStruct(test); 
    System.out.println("Struct1: " + test.Size + " " + test.Data); 
    

Вы должны получить данные из структуры s в C Dll.

+1

Использование 'String' для представления произвольного блока данных - плохая идея. – technomage

0

Если поле данных указывает на произвольные данные, используйте Pointer. Если нативная сторона выделяет, то вы ничего не делаете. Если сторона Java выделяет, используйте объект Memory, назначенный этому полю.

Что касается struct* и struct**, было бы полезно, чтобы увидеть некоторые машинный код, используя эти конструкции для того, чтобы сказать, что они представляют, так как существует некоторая неясность (struct* может быть указателем на одной структуры, или указатель на смежный массив из них). struct** может быть хранилище, выделенное для возврата struct*, или это может быть что-то другое.