繁体   English   中英

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

[英]Pointer to JNA Structure not resolved correctly

我目前在用于 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;

wBearerParameter指向GPRS 结构之一,并且wBearer通过使用常数来决定是哪个。

要将其映射到 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;
}

然后使用它:

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;

它编译没有错误。 有时 C 库告诉我我的 GPRS 参数有错误,但在大多数情况下没有。 但是 DNS 服务器设置不正确。 /etc/resolv.conf我现在有8.8.4.40000000000000internet.telekom8.8.8.800000000000008.8.4.40000000000000internet.telekom 看起来它不知道数组在哪里结束。 此外,我需要尾随 0 消失,因为我的互联网提供商告诉我将两个 DNS 服务器留空(我上面使用的那些只是为了查看/etc/resolv.conf )。

虽然您用正确的答案回答了自己的问题,但我想为其添加更多细节,以帮助您简化代码。

JNA 结构在为它们分配本机内存时必须知道它们的大小。 因此,必须在结构实例化时以完整大小初始化数组。 在您的特定情况下,这意味着像这样初始化数组:

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];
}

我还要注意的是,除非结构通过引用(作为指针)嵌套在另一个结构中,否则不需要实现ByReference 如果你确实实现了它,你需要更多的代码。

代码中的另一个错误是空终止字符串的实现。 Null 是实际的字节值 0。字符零( '0' )不一样,它实际上是 48 的字节值。您可以使用字符 '\\0'(其字节值为 0)来完成如有必要,这; 但是通常不需要。

如果您使用new byte[SIZE]初始化原始字节数组,则 0 值已在数组中初始化,因此您无需执行任何特殊操作即可显式设置它们。

您可能还会发现通过使用StringgetBytes()然后使用System.arraycopy()复制数组中的值来设置字符值更容易。 例如:

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