www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to do alias to a C struct member?

reply dangbinghoo <dangbinghoo gmail.com> writes:
hi all,

as now we don't have the net/if.h binding, I need to do struct 
ifreq binding myself, here's my code:

----
struct ifreq {
	private union ifr_ifrn {
		byte[IFNAMSIZ] ifrn_name; /* if name, e.g. "en0" */	
	}
	
	private union ifr_ifru {
		sockaddr ifru_addr;
		sockaddr ifru_dstaddr;
		sockaddr ifru_broadaddr;
		sockaddr ifru_netmask;
		sockaddr ifru_hwaddr;
		short	ifru_flags;
		int	ifru_ivalue;
		int	ifru_mtu;
		ifmap ifru_map;
		byte[IFNAMSIZ] ifru_slave;	/* Just fits the size */
		byte[IFNAMSIZ] ifru_newname;
		byte * ifru_data;
	}
	
alias ifr_ifrn.ifrn_name	    ifr_name;	  /* interface name 	*/
alias ifr_ifru.ifru_hwaddr	    ifr_hwaddr;	  /* MAC address 		*/
alias ifr_ifru.ifru_addr	    ifr_addr;	  /* address		*/
alias ifr_ifru.ifru_dstaddr	    ifr_dstaddr;  /* other end of p-p 
lnk	*/
alias ifr_ifru.ifru_broadaddr	ifr_broadaddr;/* broadcast 
address	*/
alias ifr_ifru.ifru_netmask	    ifr_netmask;  /* interface net 
mask	*/
alias ifr_ifru.ifru_flags	    ifr_flags;	  /* flags		*/
alias ifr_ifru.ifru_ivalue	    ifr_metric;	  /* metric		*/
alias ifr_ifru.ifru_mtu	        ifr_mtu;      /* mtu			*/
alias ifr_ifru.ifru_map	        ifr_map;	  /* device map		*/
alias ifr_ifru.ifru_slave	    ifr_slave;	  /* slave device		*/
alias ifr_ifru.ifru_data	    ifr_data;	  /* for use by 
interface	*/
alias ifr_ifru.ifru_ivalue      ifr_ifindex;  /* interface index  
     */
alias ifr_ifru.ifru_ivalue	    ifr_bandwidth;/* link bandwidth	*/
alias ifr_ifru.ifru_ivalue	    ifr_qlen;	  /* queue length		*/
alias ifr_ifru.ifru_newname	    ifr_newname;  /* New name		*/
}
---

as show above we need to trun the C code



to D's alias, but when done the binding and trying to compiling 
this code:

---
	import core.sys.posix.sys.socket;
	import core.sys.posix.sys.ioctl;
	import core.sys.posix.arpa.inet;
	
	import core.stdc.string;
	import core.stdc.stdio;
	import core.sys.posix.stdio;
	import core.stdc.errno;
	import std.string;

......
                 ifreq ifr;

		strcpy(ifr.ifr_name, std.string.toStringz(if_name)); //line 172
		if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0)
		{
			return;
		}
---

DMD compiler gives an error :
```
/test.d(172): Error: need this for ifrn_name of type byte[16]
./test.d(172): Error: function core.stdc.string.strcpy(return 
scope char* s1, scope const(char*) s2) is not callable using 
argument types (_error_, immutable(char)*)
./test.d(172):        cannot pass argument __error of type 
_error_ to parameter return scope char* s1
```

So, how to do alias for a C struct member?


thanks!

Binghoo Dang
Apr 22 2019
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 22 April 2019 at 11:04:49 UTC, dangbinghoo wrote:
 alias ifr_ifrn.ifrn_name	    ifr_name;	  /* interface name 	*/

 So, how to do alias for a C struct member?
D doesn't support this kind of alias. There's two options: 1) just write the full name in the code. ifreq ifr; ifr.ifr_ifrn.ifrn_name /* instead of ifr.ifrn_name */ or, if you are linking in the D module containing the translated headers (if you don't link it in, this will cause missing symbol linker errors!) 2) write ref property functions to get to it, using ufcs for the middle. So replace that *alias* line with: property ref ifr_name(ifreq this_) { return this_.ifr_ifrn.ifrn_name; } Then you should be able to use it the same way as in C.
Apr 22 2019
parent reply dangbinghoo <dangbinghoo gmail.com> writes:
On Monday, 22 April 2019 at 13:10:45 UTC, Adam D. Ruppe wrote:
 On Monday, 22 April 2019 at 11:04:49 UTC, dangbinghoo wrote:
 alias ifr_ifrn.ifrn_name	    ifr_name;	  /* interface name 	*/

 So, how to do alias for a C struct member?
D doesn't support this kind of alias. There's two options: 1) just write the full name in the code. ifreq ifr; ifr.ifr_ifrn.ifrn_name /* instead of ifr.ifrn_name */ or, if you are linking in the D module containing the translated headers (if you don't link it in, this will cause missing symbol linker errors!) 2) write ref property functions to get to it, using ufcs for the middle. So replace that *alias* line with: property ref ifr_name(ifreq this_) { return this_.ifr_ifrn.ifrn_name; } Then you should be able to use it the same way as in C.
OK, I'd prefer with option 2. thank you in advance!
Apr 22 2019
parent dangbinghoo <dangbinghoo gmail.com> writes:
On Monday, 22 April 2019 at 15:50:11 UTC, dangbinghoo wrote:
 On Monday, 22 April 2019 at 13:10:45 UTC, Adam D. Ruppe wrote:
 On Monday, 22 April 2019 at 11:04:49 UTC, dangbinghoo wrote:
 alias ifr_ifrn.ifrn_name	    ifr_name;	  /* interface name 	*/

 So, how to do alias for a C struct member?
D doesn't support this kind of alias. There's two options: Then you should be able to use it the same way as in C.
OK, I'd prefer with option 2. thank you in advance!
hi all, the correct answer is : --- struct ifreq { private union ifr_ifrn_ { byte[IFNAMSIZ] ifrn_name; /* if name, e.g. "en0" */ } ifr_ifrn_ ifr_ifrn; private union ifr_ifru_ { sockaddr ifru_addr; sockaddr ifru_dstaddr; sockaddr ifru_broadaddr; sockaddr ifru_netmask; sockaddr ifru_hwaddr; short ifru_flags; int ifru_ivalue; int ifru_mtu; ifmap ifru_map; byte[IFNAMSIZ] ifru_slave; /* Just fits the size */ byte[IFNAMSIZ] ifru_newname; byte * ifru_data; } ifr_ifru_ ifr_ifru; // NOTE: alias will not work : alias ifr_ifrn.ifrn_name ifr_name; property ref ifr_name() { return ifr_ifrn.ifrn_name; } /* interface name */ --- the `need this` error is telling that `ifr_ifrn` is not an instance but a type for my previous code. so for C struct's union member, we need to first declare a member of that union type, and then using property to implement The C-Macro. but here I have a question in further: As showing above, ifreq has a member of ``byte[IFNAMSIZ] ifrn_name;``, when translating the C style calling code, I need to do such a cast for D byte: ``` strcpy(cast(char *)ifr.ifr_name.ptr, std.string.toStringz(if_name)); if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { return; } ``` should I keep the `ifrn_name` to a `char[]` for avoid of doing cast D byte to C (char*) ? and I can calling like this: ``` struct ifreq { private union ifr_ifrn_ { char[IFNAMSIZ] ifrn_name; /* if name, e.g. "en0" */ } ... strcpy(ifr.ifr_name.ptr, std.string.toStringz(if_name)); if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { return; } ``` this looks more clean and like the C style code. -------------- Thanks! Binghoo Dang
Apr 22 2019
prev sibling parent reply Arun Chandrasekaran <aruncxy gmail.com> writes:
On Monday, 22 April 2019 at 11:04:49 UTC, dangbinghoo wrote:
 hi all,

 as now we don't have the net/if.h binding, I need to do struct 
 ifreq binding myself, here's my code:

 [...]
Looks like we both were working on the same thing, few hours apart. https://forum.dlang.org/post/nkbnknlgmcwaivppmzhc forum.dlang.org
Apr 22 2019
parent dangbinghoo <dangbinghoo gmail.com> writes:
On Monday, 22 April 2019 at 15:45:52 UTC, Arun Chandrasekaran 
wrote:
 On Monday, 22 April 2019 at 11:04:49 UTC, dangbinghoo wrote:
 hi all,

 as now we don't have the net/if.h binding, I need to do struct 
 ifreq binding myself, here's my code:

 [...]
Looks like we both were working on the same thing, few hours apart. https://forum.dlang.org/post/nkbnknlgmcwaivppmzhc forum.dlang.org
yeah, I was doing that 4 hours ago! ^_^
Apr 22 2019