Reputation: 15
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
Upvotes: 2
Views: 619
Reputation: 9130
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.
Upvotes: 1