[英]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.telekom
和8.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 值已在数组中初始化,因此您无需执行任何特殊操作即可显式设置它们。
您可能还会发现通过使用String
类getBytes()
然后使用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.