RAM
RAM

Reputation: 65

Print a Double from C in Python

I am sending a double value from C through TCP using lwIP. To accomplish that, I am using an union between a double and one string of 8 bytes (because the lwIP's function to send data is of type 'char *'). Here te code:

void process_echo_request(void *p) {
int sd = (int)p;
int RECV_BUF_SIZE = 2048;
char recv_buf[RECV_BUF_SIZE];
int n, nwrote;
union {
    double dval;
    char   sval[sizeof(double)];
    } data_to_send;

data_to_send.dval = 1e+23;

while (1) {
    /* read a max of RECV_BUF_SIZE bytes from socket */
    if ((n = read(sd, recv_buf, RECV_BUF_SIZE)) < 0) {
        xil_printf("%s: error reading from socket %d, closing socket\r\n", __FUNCTION__, sd);
        break;
    }

    /* break if the recved message = "quit" */
    if (!strncmp(recv_buf, "quit", 4))
        break;

    /* break if client closed connection */
    if (n <= 0)
        break;

    data_to_send.dval += 1e+23;
    /* handle request */
    if ((nwrote = write(sd, data_to_send.sval, 8)) < 0) {
        xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n",
                __FUNCTION__, n, nwrote);
        xil_printf("Closing socket %d\r\n", sd);
        break;
    }
}

/* close connection */
close(sd);
vTaskDelete(NULL);

I am trying to read from a Python script, but I fail on get the double value. The code:

#!/usr/bin/env python

import socket
from ctypes import *

TCP_IP = '192.168.0.10'
TCP_PORT = 1000
BUFFER_SIZE = 8

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(" ")
data = s.recv(BUFFER_SIZE)
s.close()

print float(data)

It fails with the message ValueError: could not convert string to float: �J��-�D I know, is because the string is not a literal representation of a real value. Any idea? I need the real (double) value.

For more information, the lwIP echo server is running in a Zynq 7000 FPGA+SoC. I am running the Python code from a Debian 8. The double value is a 64 bit temperature for a sensor.

-- EDIT -- The final working code is:

#!/usr/bin/env python

import socket
from struct import *

TCP_IP = '192.168.0.10'
TCP_PORT = 1000
BUFFER_SIZE = 8

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(" ")
data = s.recv(BUFFER_SIZE)
s.close()

print unpack("d",data)[0]

Upvotes: 1

Views: 528

Answers (1)

Jean-Fran&#231;ois Fabre
Jean-Fran&#231;ois Fabre

Reputation: 140256

you're recieving the binary representation of the double, not the string one.

You have to unpack it using struct module and the double specifier which is d. struct.unpack returns a tuple, so take first & only value to get your float

my_value = struct.unpack("d",data)[0]

note that you can even fix the endianness with < or >, not necessary if you're on the same machine or CPU type for both programs.

Upvotes: 2

Related Questions