2

I have an SDK with DLL libraries. I am invoking the libraries from Java 1.8 and JNA v3.0.9 I am having trouble defining the structures

The SDK documentation states:

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

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:

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

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

//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.

Any help much appreciated.

Thanks in advance

0

1 Answer 1

1

Welcome to 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.

Your NET_DVR_STDXMLConfig method call could be improved. While it works passing raw Pointer values, it would be better to pass the appropriate structures there instead. JNA will automatically treat them as their reference pointers in the method arguments, and handle the read() and write() automatically. 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"); instead of just using the original "string".

You're getting the NPE on the arraycopy because you haven't created an array for struInput.lpRequestUrl; it's simply a 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, e.g.,

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

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.

One final note -- you should probably try to use the most recent version of JNA, as there are always improvements and bug fixes.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.