简体   繁体   English

使用 Java JNA 调用 DLL 库

[英]Invoking DLL Library with Java JNA

I have an SDK with DLL libraries.我有一个带有 DLL 库的 SDK。 I am invoking the libraries from Java 1.8 and JNA v3.0.9 I am having trouble defining the structures我正在从 Java 1.8 和 JNA v3.0.9 调用库我在定义结构时遇到问题

The SDK documentation states: SDK 文档指出:

Call NET_DVR_STDXMLConfig to pass through the request URL: GET /ISAPI/AccessControl/UserInfo/capabilities?format=json for getting the person management capability to know the configuration details and notices.调用 NET_DVR_STDXMLConfig 传递请求 URL: GET /ISAPI/AccessControl/UserInfo/capabilities?format=json 获取人员管理能力,了解配置详情和注意事项。

NET_DVR_STDXMLConfig API call definiton is: 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.

Definition of NET_DVR_XML_CONFIG_INPUT structure: 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.

The definition of NET_DVR_MIME_UNIT structure is 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.

And this is what I have done in Java so far: DLL call and Structure definition这就是我到目前为止在 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");
    }               
}   

And this is my library invocation这是我的图书馆调用

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

I am not sure about my structures.我不确定我的结构。 Im gettign a nullpointer when setting the requestURL Also my invocation returns a generic "parameters not valid" error message.我在设置 requestURL 时获取了一个空指针我的调用也返回了一个通用的“参数无效”错误消息。

Any help much appreciated.非常感谢任何帮助。

Thanks in advance提前致谢

Welcome to StackOverflow.欢迎来到 StackOverflow。

Your structure mappings look good.您的结构映射看起来不错。 You didn't list the SDK structure or docs for NET_DVR_XML_CONFIG_OUTPUT so I can't help much with what you expect there.您没有列出 SDK 结构或NET_DVR_XML_CONFIG_OUTPUT的文档,所以我对您的期望无能为力。

Your NET_DVR_STDXMLConfig method call could be improved.您的NET_DVR_STDXMLConfig方法调用可以改进。 While it works passing raw Pointer values, it would be better to pass the appropriate structures there instead.虽然它可以传递原始Pointer值,但最好在那里传递适当的结构。 JNA will automatically treat them as their reference pointers in the method arguments, and handle the read() and write() automatically. JNA 会在方法 arguments 中自动将它们视为它们的引用指针,并自动处理read()write() So this is a better mapping:所以这是一个更好的映射:

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

Not sure why you're doing new String("string");不知道你为什么要这样做new String("string"); instead of just using the original "string" .而不是只使用原始的"string"

You're getting the NPE on the arraycopy because you haven't created an array for struInput.lpRequestUrl ;您在 arraycopy 上获得了 NPE,因为您还没有为struInput.lpRequestUrl创建一个数组; it's simply a Pointer .它只是一个Pointer Rather than an array copy, you probably want to define that String buffer as a Memory object, and then copy the string into it, eg,而不是数组副本,您可能希望将该字符串缓冲区定义为Memory object,然后将字符串复制到其中,例如,

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();

Passing the Structure pointer for the other argument is good but you need to set the struInput.dwInBufferSize to match that structure's size() .为另一个参数传递结构指针很好,但您需要设置struInput.dwInBufferSize以匹配该结构的size() As written it looks like you're passing a size of 0 (the default int ) in the input structure for that buffer size, which may be the source of the invalid argument.正如所写的那样,您在输入结构中为该缓冲区大小传递了一个大小 0 (默认int ),这可能是无效参数的来源。 Or it's possible you haven't fully initialized the NET_DVR_MIME_UNIT structure, as you've left the String null and didn't set its length.或者您可能还没有完全初始化NET_DVR_MIME_UNIT结构,因为您留下了String null 并且没有设置它的长度。

You will need to define your own buffers similar to the above for the OUTPUT structure, as well, and since you don't know the full size of the strings, you would put a max value (I assume MAX_XML_CONFIG_LEN based on what you're trying to do but I haven't read the DLL docs) which you'll have to find the value of of in your dll's header files.您还需要为OUTPUT结构定义您自己的缓冲区,并且由于您不知道字符串的完整大小,因此您需要设置一个最大值(我假设MAX_XML_CONFIG_LEN基于您的尝试这样做,但我还没有阅读 DLL 文档),您必须在 dll 的 header 文件中找到 的值。

One final note -- you should probably try to use the most recent version of JNA, as there are always improvements and bug fixes.最后一点——您可能应该尝试使用最新版本的 JNA,因为总会有改进和错误修复。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM