简体   繁体   English

指向 JNA 结构的指针未正确解析

[英]Pointer to JNA Structure not resolved correctly

I am currently using JNA on a Linux device that is used for m2m purposes and comes with a C Library that includes the following code:我目前在用于 m2m 目的的 Linux 设备上使用 JNA,并附带一个包含以下代码的 C 库:

typedef struct _INET_MODULE_CONFIG{
       unsigned char  wBearer;                   
       void* wBearerParameters;
       void  (*inet_action)( INET_Events * );
    }INET_MODULE_CONFIG;

    typedef struct _GPRS_CONFIG{
       unsigned char gprsUser[ 20];             
       unsigned char gprsPass[ 20];             
       unsigned char gprsDNS1[ 20];             
       unsigned char gprsDNS2[ 20];             
       unsigned char gprsAPN [ 20];            
    }GPRS_CONFIG;

    typedef struct _GPRS_ENHANCED_CONFIG{
       unsigned char gprsUser[ USER_SIZE];        
       unsigned char gprsPass[ PWD_SIZE];         
       unsigned char gprsDNS1[ IP_SIZE];      
       unsigned char gprsDNS2[ IP_SIZE];      
       unsigned char gprsAPN [ APN_SIZE];     
    }GPRS_ENHANCED_CONFIG;

The wBearerParameter points to one of the GPRS Structs, and wBearer decides to which, by using a constant. wBearerParameter指向GPRS 结构之一,并且wBearer通过使用常数来决定是哪个。

To map this to Java I use this:要将其映射到 Java,我使用以下命令:

public class INET_MODULE_CONFIG extends Structure implements Structure.ByReference
{
    public byte wBearer;
    public Pointer wBearerParameters;
    public inet_event_handler inet_action;
}
    
public class GPRS_CONFIG extends Structure implements Structure.ByReference
{       
    public byte[] gprsUser;
    public byte[] gprsPass;
    public byte[] gprsDNS1;
    public byte[] gprsDNS2;
    public byte[] gprsAPN;
}
    
public class GPRS_ENHANCED_CONFIG extends Structure implements Structure.ByReference
{
    public byte[] gprsUser;
    public byte[] gprsPass;
    public byte[] gprsDNS1;
    public byte[] gprsDNS2;
    public byte[] gprsAPN;
}

And then this to use it:然后使用它:

grsKonfig.gprsUser = new byte[20];
gprsKonfig.gprsPass = new byte[20];
gprsKonfig.gprsAPN = new byte[20];
gprsKonfig.gprsDNS1 = new byte[20];
gprsKonfig.gprsDNS2 = new byte[20];
        
gprsKonfig.gprsUser[0] = 't';
gprsKonfig.gprsUser[1] = '-';
gprsKonfig.gprsUser[2] = 'm';
gprsKonfig.gprsUser[3] = 'o';
gprsKonfig.gprsUser[4] = 'b';
gprsKonfig.gprsUser[5] = 'i';
gprsKonfig.gprsUser[6] = 'l';
gprsKonfig.gprsUser[7] = 'e';
for(int i = 8; i < 20; i++)
{
    gprsKonfig.gprsUser [i]= 0;
}

gprsKonfig.gprsPass[0] = 't';
gprsKonfig.gprsPass[1] = 'm';
for(int i = 2; i < 20; i++)
{
    prsKonfig.gprsPass [i]= 0;
}
        
gprsKonfig.gprsAPN[0] = 'i';
gprsKonfig.gprsAPN[1] = 'n';
gprsKonfig.gprsAPN[2] = 't';
gprsKonfig.gprsAPN[3] = 'e';
gprsKonfig.gprsAPN[4] = 'r';
gprsKonfig.gprsAPN[5] = 'n';
gprsKonfig.gprsAPN[6] = 'e';
gprsKonfig.gprsAPN[7] = 't';
gprsKonfig.gprsAPN[8] = '.';
gprsKonfig.gprsAPN[9] = 't';
gprsKonfig.gprsAPN[10] = 'e';
gprsKonfig.gprsAPN[11] = 'l';
gprsKonfig.gprsAPN[12] = 'e';
gprsKonfig.gprsAPN[13] = 'k';
gprsKonfig.gprsAPN[14] = 'o';
gprsKonfig.gprsAPN[15] = 'm';
for(int i = 16; i < 20; i++)
{
    gprsKonfig.gprsAPN [i]= 0;
}
        
gprsKonfig.gprsDNS1[0] = '8';
gprsKonfig.gprsDNS1[1] = '.';
gprsKonfig.gprsDNS1[2] = '8';
gprsKonfig.gprsDNS1[3] = '.';
gprsKonfig.gprsDNS1[4] = '8';
gprsKonfig.gprsDNS1[5] = '.';
gprsKonfig.gprsDNS1[6] = '8';
for(int i = 7; i < gprsKonfig.gprsDNS1.length; i++)
{
    gprsKonfig.gprsDNS1[i] = '0';
}
    
gprsKonfig.gprsDNS2[0] = '8';
gprsKonfig.gprsDNS2[1] = '.';
gprsKonfig.gprsDNS2[2] = '8';
gprsKonfig.gprsDNS2[3] = '.';
gprsKonfig.gprsDNS2[4] = '4';
gprsKonfig.gprsDNS2[5] = '.';
gprsKonfig.gprsDNS2[6] = '4';
for(int i = 8; i < gprsKonfig.gprsDNS2.length; i++)
{
    gprsKonfig.gprsDNS2[i] = '0';
}

inetKonfig.wBearer = InternetBibliothek.NORMAL_BEARER_GPRS;
inetKonfig.wBearerParameters = gprsKonfig.getPointer();
inetKonfig.inet_action = callback;

It compiles without an error.它编译没有错误。 Sometimes the C Library tells me I have an error in my GPRS params, but in most cases not.有时 C 库告诉我我的 GPRS 参数有错误,但在大多数情况下没有。 However the DNS servers are not set correctly.但是 DNS 服务器设置不正确。 In /etc/resolv.conf I now have 8.8.4.40000000000000internet.telekom and 8.8.8.800000000000008.8.4.40000000000000internet.telekom ./etc/resolv.conf我现在有8.8.4.40000000000000internet.telekom8.8.8.800000000000008.8.4.40000000000000internet.telekom It looks like it does not know where the arrays end.看起来它不知道数组在哪里结束。 Also I need the trailing 0 to go away, since my internet provider tells me to leave both DNS server empty (The ones I used above are just to see what stands in /etc/resolv.conf ).此外,我需要尾随 0 消失,因为我的互联网提供商告诉我将两个 DNS 服务器留空(我上面使用的那些只是为了查看/etc/resolv.conf )。

While you answered your own question with a correct answer , I want to add a bit more detail to it that may help you streamline your code.虽然您用正确的答案回答了自己的问题,但我想为其添加更多细节,以帮助您简化代码。

JNA Structures must know their size when allocating native memory for them. JNA 结构在为它们分配本机内存时必须知道它们的大小。 Therefore, arrays must be initialized with full size at the time of structure instantiation.因此,必须在结构实例化时以完整大小初始化数组。 In your specific case, this means initializing the arrays like this:在您的特定情况下,这意味着像这样初始化数组:

public class GPRS_CONFIG extends Structure {       
    public byte[] gprsUser = new byte[20];
    public byte[] gprsPass = new byte[20];
    public byte[] gprsDNS1 = new byte[20];
    public byte[] gprsDNS2 = new byte[20];
    public byte[] gprsAPN = new byte[20];
}

public class GPRS_ENHANCED_CONFIG extends Structure {
    public byte[] gprsUser = new byte[USER_SIZE];
    public byte[] gprsPass = new byte[PWD_SIZE];
    public byte[] gprsDNS1 = new byte[IP_SIZE];
    public byte[] gprsDNS2 = new byte[IP_SIZE];
    public byte[] gprsAPN = new byte[APN_SIZE];
}

I'll also note that there's no need to implement ByReference unless the struture is nested by reference (as a pointer) inside another structure.我还要注意的是,除非结构通过引用(作为指针)嵌套在另一个结构中,否则不需要实现ByReference If you do implement it, there's more code you'd need.如果你确实实现了它,你需要更多的代码。

Another error in your code is implementation of null terminated strings.代码中的另一个错误是空终止字符串的实现。 Null is an actual byte value of 0. The character zero ( '0' ) is not the same, it is actually the byte value of 48. You could use the character '\\0' (which has the byte value 0) to accomplish this if necessary; Null 是实际的字节值 0。字符零( '0' )不一样,它实际上是 48 的字节值。您可以使用字符 '\\0'(其字节值为 0)来完成如有必要,这; however it's not usually needed.但是通常不需要。

If you are initializing a primitive byte arrays with new byte[SIZE] , the 0 values are already initialized in the array, so you don't need to do anything special to explicitly set them.如果您使用new byte[SIZE]初始化原始字节数组,则 0 值已在数组中初始化,因此您无需执行任何特殊操作即可显式设置它们。

You might also find it eaiser to set the character values by using the String class getBytes() and then copying the values in the array over using System.arraycopy() .您可能还会发现通过使用StringgetBytes()然后使用System.arraycopy()复制数组中的值来设置字符值更容易。 For example:例如:

byte[] dnsBytes = "8.8.8.8".getBytes("ASCII");
System.arraycopy(dnsBytes, 0, gprsKonfig.gprsDNS1, 0, dnsBytes.length);

用 20 的长度初始化它,并使用 0 不带 '',作为尾随。

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

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