I'm attempting to convert a python program to D; the program is for sending Art-Net DMX packets.
Python:
import sys, socket, math, time
from ctypes import *
class ArtNetDMXOut(LittleEndianStructure):
PORT = 0x1936
_fields_ = [("id", c_char * 8),
("opcode", c_ushort),
("protverh", c_ubyte),
("protver", c_ubyte),
("sequence", c_ubyte),
("physical", c_ubyte),
("universe", c_ushort),
("lengthhi", c_ubyte),
("length", c_ubyte),
("payload", c_ubyte * 512)]
def __init__(self):
self.id = b"Art-Net"
self.opcode = 0x5000
self.protver = 14
self.universe = 0
self.lengthhi = 2
def main():
hostIP = "localhost"
S = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
packet = ArtNetDMXOut()
packet.payload[0] = 255
S.sendto(packet, (hostIP, ArtNetDMXOut.PORT))
if __name__ == "__main__":
main()
D:
import std.stdio;
import std.socket;
class ArtNetDMX{
char id[8];
ushort opCode;
ubyte verH;
ubyte ver;
ubyte sequence;
ubyte physical;
ushort universe;
ubyte lengthHi;
ubyte length;
ubyte data[511];
this(){
this.id = "ART-NET0";
this.opCode = 0x5000;
this.ver = 14;
this.universe = 0;
this.lengthHi = 2;
}
}
void main() {
auto s = new UdpSocket();
auto addr = new InternetAddress("localhost", 6454);
s.bind(addr);
ArtNetDMX packet = new ArtNetDMX();
packet.data[0] = 255;
s.send(packet);
};
My Python code works exactly as intended, but in D I get the error function std.socket.Socket.send (const(void)[] buf, SocketFlags flags) is not callable using argument types (ArtNetDMX)
at the s.send(packet);
line.
Am I approaching this correctly? What am I doing wrong?
For starters, you'll want ArtNetDMX
to be a struct
, not a class
- since classes in D are reference types and there are no guarantees about class field layout; and since you're sending it over the wire, specify the appropriate alignment (usually 1 if every field is to be packed together):
struct ArtNetDMX {
align(1):
....
}
In your main
, you can now allocate an instance of it on the stack:
ArtNetDMX packet; // no `new` required
packet.id = "ART-NET0"; // initialize fields
packet.opCode = 0x5000;
packet.ver = 14;
packet.universe = 0;
packet.lengthHi = 2;
Or if you perform the same initialization a lot, move it into a function:
ArtNetDMX createArtNetDMX()
{
ArtNetDMX packet;
packet.id = "ART-NET0";
packet.opCode = 0x5000;
packet.ver = 14;
packet.universe = 0;
packet.lengthHi = 2;
return packet;
}
Finally, Socket.send
requires its parameter to be a slice (an array or part of). If you end up sending multiple packets at a time, you'd put your packets into an array, then just send the array.
Since you're only sending one packet, you can replace
s.send(packet);
with
s.send((&packet)[0..1]);
which is just a safe way to convert an object to a 1-element slice.