digitalmars.D.learn - How to do alias to a C struct member?
- dangbinghoo (81/81) Apr 22 2019 hi all,
- Adam D. Ruppe (13/15) Apr 22 2019 D doesn't support this kind of alias. There's two options:
- dangbinghoo (3/19) Apr 22 2019 OK, I'd prefer with option 2.
- dangbinghoo (64/78) Apr 22 2019 hi all,
- Arun Chandrasekaran (4/8) Apr 22 2019 Looks like we both were working on the same thing, few hours
- dangbinghoo (3/13) Apr 22 2019 yeah, I was doing that 4 hours ago! ^_^
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
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
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:OK, I'd prefer with option 2. thank you in advance!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
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: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 DangOn Monday, 22 April 2019 at 11:04:49 UTC, dangbinghoo wrote:OK, I'd prefer with option 2. thank you in advance!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.
Apr 22 2019
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
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:yeah, I was doing that 4 hours ago! ^_^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