簡體   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