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

huangapple go评论87阅读模式
英文:

Pointer to JNA Structure not resolved correctly

问题

以下是翻译好的部分:

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;

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++)
{
    gprsKonfig.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;

若有进一步需要,请随时告知。

英文:

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:

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.

To map this to Java I use this:

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] = &#39;t&#39;;
gprsKonfig.gprsUser[1] = &#39;-&#39;;
gprsKonfig.gprsUser[2] = &#39;m&#39;;
gprsKonfig.gprsUser[3] = &#39;o&#39;;
gprsKonfig.gprsUser[4] = &#39;b&#39;;
gprsKonfig.gprsUser[5] = &#39;i&#39;;
gprsKonfig.gprsUser[6] = &#39;l&#39;;
gprsKonfig.gprsUser[7] = &#39;e&#39;;
for(int i = 8; i &lt; 20; i++)
{
gprsKonfig.gprsUser [i]= 0;
}
gprsKonfig.gprsPass[0] = &#39;t&#39;;
gprsKonfig.gprsPass[1] = &#39;m&#39;;
for(int i = 2; i &lt; 20; i++)
{
prsKonfig.gprsPass [i]= 0;
}
gprsKonfig.gprsAPN[0] = &#39;i&#39;;
gprsKonfig.gprsAPN[1] = &#39;n&#39;;
gprsKonfig.gprsAPN[2] = &#39;t&#39;;
gprsKonfig.gprsAPN[3] = &#39;e&#39;;
gprsKonfig.gprsAPN[4] = &#39;r&#39;;
gprsKonfig.gprsAPN[5] = &#39;n&#39;;
gprsKonfig.gprsAPN[6] = &#39;e&#39;;
gprsKonfig.gprsAPN[7] = &#39;t&#39;;
gprsKonfig.gprsAPN[8] = &#39;.&#39;;
gprsKonfig.gprsAPN[9] = &#39;t&#39;;
gprsKonfig.gprsAPN[10] = &#39;e&#39;;
gprsKonfig.gprsAPN[11] = &#39;l&#39;;
gprsKonfig.gprsAPN[12] = &#39;e&#39;;
gprsKonfig.gprsAPN[13] = &#39;k&#39;;
gprsKonfig.gprsAPN[14] = &#39;o&#39;;
gprsKonfig.gprsAPN[15] = &#39;m&#39;;
for(int i = 16; i &lt; 20; i++)
{
gprsKonfig.gprsAPN [i]= 0;
}
gprsKonfig.gprsDNS1[0] = &#39;8&#39;;
gprsKonfig.gprsDNS1[1] = &#39;.&#39;;
gprsKonfig.gprsDNS1[2] = &#39;8&#39;;
gprsKonfig.gprsDNS1[3] = &#39;.&#39;;
gprsKonfig.gprsDNS1[4] = &#39;8&#39;;
gprsKonfig.gprsDNS1[5] = &#39;.&#39;;
gprsKonfig.gprsDNS1[6] = &#39;8&#39;;
for(int i = 7; i &lt; gprsKonfig.gprsDNS1.length; i++)
{
gprsKonfig.gprsDNS1[i] = &#39;0&#39;;
}
gprsKonfig.gprsDNS2[0] = &#39;8&#39;;
gprsKonfig.gprsDNS2[1] = &#39;.&#39;;
gprsKonfig.gprsDNS2[2] = &#39;8&#39;;
gprsKonfig.gprsDNS2[3] = &#39;.&#39;;
gprsKonfig.gprsDNS2[4] = &#39;4&#39;;
gprsKonfig.gprsDNS2[5] = &#39;.&#39;;
gprsKonfig.gprsDNS2[6] = &#39;4&#39;;
for(int i = 8; i &lt; gprsKonfig.gprsDNS2.length; i++)
{
gprsKonfig.gprsDNS2[i] = &#39;0&#39;;
}
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. However the DNS servers are not set correctly. In /etc/resolv.conf I now have 8.8.4.40000000000000internet.telekom and 8.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).

答案1

得分: 2

用长度为20进行初始化,并在末尾使用0而不是''。

英文:

Initialise it with the length of 20, and use 0 without '', as trailing.

答案2

得分: 2

虽然您通过一个正确的答案回答了自己的问题,但我想补充一些更详细的内容,可能会帮助您优化代码。

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。如果您确实实现了它,您将需要更多的代码。

您代码中的另一个错误是实现了空终止字符串。空值是实际的字节值为0。数字零(&#39;0&#39;)不同,它实际上是字节值48。如果必要,您可以使用字符&#39;\0&#39;(它的字节值为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);
英文:

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. 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. 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 (&#39;0&#39;) 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; 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.

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(). For example:

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

huangapple
  • 本文由 发表于 2020年10月5日 18:29:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/64206860.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定