Вызов библиотеки DLL с помощью Java JNA - PullRequest
2 голосов
/ 26 сентября 2019

У меня есть SDK с библиотеками DLL.Я вызываю библиотеки из Java 1.8 и JNA v3.0.9 У меня возникают проблемы с определением структур

В документации SDK говорится:

Вызов NET_DVR_STDXMLConfig для прохождения через URL запроса: GET/ ISAPI / AccessControl / UserInfo /abilities? Format = json для получения возможности управления персоналом узнать подробности и уведомления о конфигурации.

NET_DVR_STDXMLConfig Определение вызова API:

BOOL NET_DVR_STDXMLConfig(
LONG                         lUserID,
NET_DVR_XML_CONFIG_INPUT     *lpInputParam,
NET_DVR_XML_CONFIG_OUTPUT    *lpOutputParam
);

lpInputParam
[IN] Input parameters, refer to the structure NET_DVR_XML_CONFIG_INPUT for details.

lpOutputParam
[IN/OUT] Output parameters, refer to the structure NET_DVR_XML_CONFIG_OUTPUT for details.

Определение структуры NET_DVR_XML_CONFIG_INPUT:

struct{
DWORD       dwSize;
void        *lpRequestUrl;
DWORD       dwRequestUrlLen;
void        *lpInBuffer;
DWORD       dwInBufferSize; 
DWORD       dwRecvTimeOut;
BYTE        byForceEncrpt;
BYTE        byNumOfMultiPart;  
BYTE        byRes[30];
}

dwSize
Structure size.

lpRequestUrl
Request URL (command) for implement different functions, and it is in string format.

dwRequestUrlLen
Request URL size.

lpInBuffer
Buffer for storing input parameters (request messages), see the input content details structure in NET_DVR_MIME_UNIT.

dwInBufferSize
Input buffer size.

dwRecvTimeOut
Receiving timeout, unit: ms, 0-5000ms (default).

byForceEncrpt
Whether to enable force encryption (the messages will be encrypted by AES algorithm for transmission): 0-no, 1-yes.

byNumOfMultiPart
Number of message segments: 0-invalid; other values-number of message segments, which is transmitted by the parameter lpInBuffer in the structure NET_DVR_MIME_UNIT.

Определение структуры NET_DVR_MIME_UNIT:

struct{
  char     szContentType[32];
  char     szName[MAX_FILE_PATH_LEN/*256*/];
  char     szFilename[MAX_FILE_PATH_LEN/*256*/];
  DWORD    dwContentLen;
  char*    pContent;
  BYTE     byRes[16];
}

szContentType
Content type (corresponds to Content-Type field in the message), e.g., text/json. text/xml, and so on. The content format must be supported by HTTP.

zName
Content name (corresponds to name field in the message), e.g., name="upload".

szFilename
Content file name (corresponds to filename field in the message), e.g., filename="C:\Users\test\Desktop\11.txt".

dwContentLen
Content size.

pContent
Data point.

И это то, что я до сих пор делал в Java: вызов DLL и определение структуры

//DLL native call
boolean NET_DVR_STDXMLConfig(int lUserID, Pointer lpInputParam, Pointer lpOutputParam);

public static class NET_DVR_XML_CONFIG_INPUT extends Structure
{
    public int      dwSize;
    public Pointer  lpRequestUrl;
    public int      dwRequestUrlLen;
    public Pointer  lpInBuffer;
    public int      dwInBufferSize;
    public int      dwRecvTimeOut;
    public byte     byForceEncrpt;
    public byte     byNumOfMultiPart;
    public byte[]   byRes = new byte[30];
    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("dwSize", "lpRequestUrl", "dwRequestUrlLen", "lpInBuffer", "dwInBufferSize", 
                "dwRecvTimeOut","byForceEncrpt","byNumOfMultiPart", "byRes");
    }       
}

public static class NET_DVR_XML_CONFIG_OUTPUT extends Structure {
    public int dwSize;
    public Pointer lpOutBuffer;
    public int dwOutBufferSize;
    public int dwReturnedXMLSize;
    public Pointer lpStatusBuffer;
    public int dwStatusSize;
    public byte[] byRes = new byte[32];
    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("dwSize", "lpOutBuffer",
                "dwOutBufferSize", "dwReturnedXMLSize", "lpStatusBuffer",
                "dwStatusSize", "byRes");
    }
}

public static class NET_DVR_MIME_UNIT extends Structure{
    public byte[] szContentType = new byte[32];
    public byte[] szName = new byte[MAX_FILE_PATH_LEN];
    public byte[] szFilename = new byte[MAX_FILE_PATH_LEN];
    public int dwContentLen;
    public String pContent;
    public byte[] byRes = new byte[16];

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("szContentType", "szName", "szFilename", "dwContentLen", "pContent","byRes");
    }               
}   

И это мой библиотечный вызов

NET_DVR_XML_CONFIG_INPUT    struInput = new NET_DVR_XML_CONFIG_INPUT();
NET_DVR_XML_CONFIG_OUTPUT   struOuput = new NET_DVR_XML_CONFIG_OUTPUT();
String strInput = new String("GET /ISAPI/AccessControl/UserInfo/capabilities?format=json\r\n\"");
byte[] byInput = strInput.getBytes();
System.arraycopy(byInput, 0, struInput.lpRequestUrl, 0, byInput.length);        // Nullpointer exception
struInput.dwRequestUrlLen = byInput.length;
NET_DVR_MIME_UNIT mimeUnit = new NET_DVR_MIME_UNIT();
//mimeUnit.pContent = new Memory(MAX_XML_CONFIG_LEN);                       // Dont know what to put in here
struInput.lpInBuffer = mimeUnit.getPointer();
struOuput.dwOutBufferSize = MAX_XML_CONFIG_LEN;
struOuput.dwStatusSize = struOuput.dwOutBufferSize;     

struInput.write();  
struOuput.write();

NET_DVR_STDXMLConfig(userID,struInput.getPointer(), struOuput.getPointer());    // Getting a generic "parameters not valid" error msg

Я не уверен насчет своих структур.Я получаю нулевой указатель при установке requestURL. Также мой вызов возвращает общее сообщение об ошибке «параметры не действительны».

Любая помощь, высоко ценимая.

Заранее спасибо

1 Ответ

0 голосов
/ 26 сентября 2019

Добро пожаловать в StackOverflow.

Ваши структурные отображения выглядят хорошо.Вы не перечислили структуру SDK или документы для NET_DVR_XML_CONFIG_OUTPUT, поэтому я не могу помочь с тем, что вы там ожидаете.

Ваш NET_DVR_STDXMLConfig вызов метода может быть улучшен.Хотя он работает, передавая необработанные значения Pointer, было бы лучше вместо этого передавать соответствующие структуры.JNA автоматически обрабатывает их как их ссылочные указатели в аргументах метода и автоматически обрабатывает read() и write().Так что это лучшее отображение:

boolean NET_DVR_STDXMLConfig(int lUserID, 
    NET_DVR_XML_CONFIG_INPUT lpInputParam, NET_DVR_XML_CONFIG_OUTPUT lpOutputParam);

Не уверен, почему вы делаете new String("string"); вместо того, чтобы просто использовать исходный "string".

Вы получаете NPE наarraycopy, потому что вы не создали массив для struInput.lpRequestUrl;это просто Pointer.Вместо копирования массива вы, вероятно, захотите определить этот строковый буфер как объект Memory, а затем скопировать в него строку, например,

Memory requestUrl = new Memory(strInput.length + 1); // add space for null
requestUrl.clear(); // ensure last byte is null
requestUrl.setString(0, strInput); // set all the other bytes
struInput.lpRequestUrl = requestUrl;
struInput.dwRequestUrlLen = requestUrl.size();

Передача указателя структуры для другого аргумента хорошано вам нужно установить struInput.dwInBufferSize в соответствии с size() этой структуры.Как написано, похоже, что вы передаете размер 0 (по умолчанию int) во входной структуре для этого размера буфера, который может быть источником неверного аргумента.Или, возможно, вы не полностью инициализировали структуру NET_DVR_MIME_UNIT, так как вы оставили значение String пустым и не установили его длину.

Вам необходимо определить свои собственные буферы, аналогичныевыше для структуры OUTPUT, а также, так как вы не знаете полный размер строк, вы бы поставили максимальное значение (я предполагаю MAX_XML_CONFIG_LEN в зависимости от того, что вы пытаетесь сделать, но у меня нетчитать документацию DLL), значение которой вы должны найти в заголовочных файлах вашей dll.

Последнее замечание - вам, вероятно, следует попробовать использовать самую последнюю версию JNA, поскольку всегда есть улучшения и исправления ошибок.

...