Send composite type over TCP/UDP?

Thanks again, @yuyichao; I have it working. Dealing with pointers to immutables structs was very confusing to me as a new Julia user who’s familiar with C. For future readers, let me summarize what I got working. Perhaps others will know a cleaner way to do this!

Listener side:

sock = UDPSocket(); # Create the socket.
bind(sock, ip"127.0.0.1", 2000); # Listen on port 2000.
x = recv(sock); # Get an array of UInt8s from somewhere.

Sender side:

struct MySt; a::UInt32; b::Float64; end; # Create a super-simple immutable struct type.
m = MySt(1, 2.3); # Create an instance of the type.
sock = UDPSocket(); # Get ready to send some UDP.
x = reinterpret(UInt8, [m]); # Turn m into an array of UInt8, stored in x.
send(sock, ip"127.0.0.1", 2000, x); # Send it.

Note in the above that the call to reinterpret requires an array of the struct! I don’t really follow why. There are several long discussions about this around the internet; the longest actually currently ends with, “Wait, so why is it fine to convert an array of one immutable struct to bytes but not a scalar?” So, I don’t know, but we need to use an array as far as I can tell.

Back over to the listener, we now have x:

julia> x
16-element Array{UInt8,1}:
 0x01
 0x00
...
struct MySt; a::UInt32; b::Float64; end; # Define the same type on this end.
ma = [MySt(0, 0.)]; # Create an ARRAY to write to.
pma = reinterpret(Ptr{UInt8}, pointer(ma)); # Pretend that a pointer to ma is actually a pointer to UInt8.
unsafe_copy!(pma, pointer(x), 16); # Copy 16 units of whatever type (UInt8 in our case) to our pointer to the array from a pointer to the received data.
julia> m = ma[1] # Finally, pull out the data from our array.
MySt(0x00000001, 3.141592653589793)

It worked! Again, note that we can’t get a pointer to an instance of our struct; we have to get a pointer to the beginning of an array of our struct.

In C, the UDP part takes much more code, but the “just copy from this memory location to that one” part is far less confusing (recvfrom(sock, &m, 16, ...)). Does anyone see a good way to clean up my code above to make this more straightforward? I’d be happy to contribute something to the codebase, but my Julia-fu is clearly not where it needs to be yet.

[Despite that credit clearly goes to @yuyichao for the help, I’m marking this reply as the solution since it contains the working answer all in one post, and I’ll edit as necessary to reflect any new additions.]

1 Like