Search code examples
pythonclinuxnamed-pipes

Convert float into String and send from C code to Python through Named Pipe


I would like to send float values from C code into Python code using named pipes. I am printing the received values into terminal in the Python side, however along with the value itself, gibberish characters are also displayed.

Pipe opening:

void Init_FIFO(void)
{
    // FIFO file path
    char * bldc_fifo = "/tmp/bldc_fifo";

    // Creating the named FIFO -- mkfifo(<pathname>, <permission>)
    mkfifo(bldc_fifo, 0666);

    // Open FIFO to write/read data
    fd_fifo = open(bldc_fifo, O_RDWR | O_NONBLOCK);
    //fd_fifo = open(bldc_fifo, O_WRONLY | O_RDONLY | O_NONBLOCK);
}

For the conversion of float to string I use sprintf and the code is given below,

void SendDataOverFifo(float angle)
{
    char str[64];
    unsigned char writeBuffer[] = "Hello!";

    Init_FIFO();

    sprintf(str, "%f\n", angle);
    write(fd_fifo, str, sizeof(str));
    //write(fd_fifo, writeBuffer, sizeof(writeBuffer));
    close(fd_fifo);
}

Then for receiving the code in the Python side, I use this

#!/usr/bin/python

import os
import errno
import time

FIFO = '/tmp/bldc_fifo'

try:
    os.mkfifo(FIFO)
except OSError as oe: 
    if oe.errno != errno.EEXIST:
        raise

print("Opening FIFO...")
with open(FIFO, encoding='utf-8', errors='ignore') as fifo:
    print("FIFO opened")
    while True:
        time.sleep(0.1)
        data = fifo.read()
        print(data)

The output I am getting is something like this

i-W ?UOeiEU11.417070

Where the correct result should be:

11.417070

A note: If I try to send only "Hello!", it works without any problems.

What am I missing here? Thanks in advance.


Solution

  • The first red flag is in the sprintf call; it doesn't know how large your target buffer str is, so could overflow if you're not careful. With a single float and 64 bytes, that step should be fine.

    However, you didn't store the return value, so at this point you don't know how large the formatted text is. Then you used sizeof, which tells you how large the buffer is, not how much data you just put into it. You could use a string-based function (since sprintf wrote a nul-terminated string), such as strlen (to measure the string) or fputs (to write the string to file).

    A much easier shortcut might be to use fprintf in the first place, and not need to allocate a separate buffer (it likely uses one built into FILE) to store the formatted string.

    It is possible, albeit not necessarily portable or safe, to convert between file descriptors (such as write and close use) and FILE (such as fprintf uses) using functions such as fdopen.