Невозможно вызвать .dll функцию correclty - PullRequest
0 голосов
/ 03 мая 2018

Я вызываю разделяемую функцию .dll, используя JNA Java. Из документации можно вызвать функцию для получения параметров с использованием Visual C ++, как показано ниже;

PMSifEncodeKcdLcl(PCHAR ff, PCHAR Dta, BOOL Dbg, PCHAR szOpId, PCHAR szOpFirst, PCHAR szOpLast);

Из документа:

  • ff - один символ ASCII.
  • Dta - указывает на строку с нулевым символом в конце.
  • Dbg - логический флаг
  • szOpId - указывает на строку с нулевым символом в конце
  • szOpFirst - указывает на строку с нулевым символом в конце
  • szOpLast - указывает на строку с нулем в конце

Строка состоит из нескольких полей данных. Формат для каждого поля данных в строке следующий:

  • Данные RS FI
  • RS = Разделитель записей.

    Указывает начало поля данных. Один символ разделителя записей ASCII [RS] (шестнадцатеричный 1E)

  • FI = Идентификатор поля - указывает тип данных в поле. Один символ ASCII.

  • данные = фактические данные. Количество символов ASCII, в зависимости от идентификатора поля. Иногда данные имеют переменную длину. Разделитель записей в следующем поле указывает конец поля данных (или для последнего поля символ NULL в конце строки).

Код ответа возвращается в поле ff . Данные ответа (если есть) возвращаются в поле Dta

Я перепроверил документацию JNA для подтверждения сопоставления полей, но все еще безуспешно. После попытки в течение нескольких дней. Я пришел с кодом ниже;

Мой код Java:

/* JNA interface class
 */
public class JNALocksInterface {

        public interface LockLibrary extends StdCallLibrary {

            LockLibrary INSTANCE = (LockLibrary) Native.loadLibrary("path_to_dll", LockLibrary.class);

            public void PMSifEncodeKcdLcl(byte[] ff, byte[] dta, boolean debug, String szOpid, String szOpFirst, String szOpLast);

        }

    }


/*My Calling Class Code*/
 JNALocksInterface.LockLibrary INSTANCE = JNALocksInterface.LockLibrary.INSTANCE;
        String dta = "*R101*L101*TSingle Room*NMatu*FZachary*URegular Guest*D201805021347*O201805030111";
        String ff = "A";
        byte[] dataBytes = new byte[dta.length() + 1];
        System.arraycopy(dta.getBytes("UTF-8"), 0, dataBytes, 0, dta.length());
        dataBytes[dta.length()] = 0;

        byte[] dtaByteArray = new byte[dta.length() + 1];

        byte[] ffByteArray = ff.getBytes("UTF-8");



        for (int i = 0; i < dataBytes.length; i++) {

            String s1 = String.format("%8s", Integer.toBinaryString(dataBytes[i] & 0xFF)).replace(' ', '0');
         //   System.out.println(s1);

           if((char)dataBytes[i] == '*')
           {
               dtaByteArray[i] = 30;
           }
           else{
                int val = Integer.parseInt(s1, 2);
               byte b = (byte) val;
               dtaByteArray[i] = b;
           }


        }
        byte[] commandCodeFinal = new byte[1];
        for (int i = 0; i < ffByteArray.length; i++) {
            String s2 = String.format("%8s", Integer.toBinaryString(ffByteArray[i] & 0xFF)).replace(' ', '0');
            System.out.println(s2);

            int val = Integer.parseInt(s2, 2);
            byte b = (byte) val;
            commandCodeFinal[i] = b;
        }



        String userNameBytes = "test";
        String userFirstNameBytes = "test";
        String userLastNameBytes = "test";

        INSTANCE.PMSifEncodeKcdLcl(commandCodeFinal, dtaByteArray, false, userNameBytes, userFirstNameBytes, userLastNameBytes);

Я получаю неправильный ответ на поля ff и dta, как показано ниже.

FF Response >>  :

DTA Response >>  0101IR101L101TSingle RoomNMatuFZacharyURegular GuestD201805021347O2018050

Я заменяю «*» на разделитель записей ascii.

Может кто-нибудь показать мне, как правильно вызывать функцию с помощью JNA? Я искал по всему, но до сих пор не удалось.

1 Ответ

0 голосов
/ 04 мая 2018

Решено. Использовал разделитель полей Unicode и объект памяти JNA, и это сработало!

также использовал Windows 10 64 бит. Поменял на Windows 7 32 бит и все заработало !!

Заменен код на приведенный ниже фрагмент;

String fieldSeparator = "\u001e"
      String dataTest = fieldSeparator+"R101"+fieldSeparator+"TSingle Room"+fieldSeparator+"FShujaa"+fieldSeparator+"NMatoke"
                    + fieldSeparator+"URegular Guest"+fieldSeparator+"D201805040842"+fieldSeparator+"O201805051245";

          String  dataTestPadded = org.apache.commons.lang.StringUtils.rightPad(dataTest,30,'0');  

          System.out.println("Padded string >> " + dataTestPadded);

            String data = dataTest;
                    //getPayloadToSend(payLoadSample) + (char)00;


            String commandCode = "A";


            Memory commandCodeMemory = new Memory(commandCode.length()+1);
            commandCodeMemory.setString(0, commandCode);

            Memory dataMemory = new Memory(data.length()+1);
            dataMemory.setString(0, data);
            //dataMemory.setString(1, "0");


            System.out.println("Registerring >> " + INSTANCE.PMSifRegister("42860149", "BatchClient")) ;

            INSTANCE.PMSifEncodeKcdLcl(commandCodeMemory, dataMemory, false, "ZKMATU", "zACHARY", "tESTING");




            System.out.println("FF Response >>  " + commandCodeMemory.getString(0));
             System.out.println("DTA Response >>  " + dataMemory.getString(0));

         INSTANCE.PMSifUnregister();
...