Конвертировать float в String и отправить из кода C в Python через Named Pipe - PullRequest
0 голосов
/ 31 марта 2019

Я хотел бы отправить значения с плавающей точкой из кода C в код Python, используя именованные каналы. Я печатаю полученные значения в терминал на стороне Python, однако наряду с самим значением также отображаются символы тарабарщины.

Отверстие трубы:

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);
}

Для преобразования числа с плавающей запятой в строку я использую sprintf, а код приведен ниже,

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);
}

Затем для получения кода на стороне Python я использую это

#!/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)

Вывод, который я получаю, выглядит примерно так

i-W? UOeiEU11.417070

Где должен быть правильный результат:

11,417070

Примечание: Если я попытаюсь отправить только «Привет!», Это будет работать без проблем.

Что мне здесь не хватает? Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 31 марта 2019

Первый красный флаг в вызове sprintf;он не знает, насколько велик ваш целевой буфер str, поэтому может переполниться, если вы не будете осторожны.С одним float и 64 байтами этот шаг должен быть в порядке.

Однако вы не сохранили возвращаемое значение, поэтому на данный момент вы не знаете, насколько велик форматированный текст.Затем вы использовали sizeof, который говорит вам, насколько большой буфер, а не то, сколько данных вы просто поместили в него.Вы можете использовать строковую функцию (поскольку sprintf записывает строку с нулевым символом в конце), например, strlen (для измерения строки) или fputs (для записи строки в файл).

Гораздо проще использовать fprintf, во-первых, без необходимости выделять отдельный буфер (он, вероятно, использует встроенный в FILE) для хранения отформатированной строки.

Возможно, хотя и не обязательно переносимым или безопасным, преобразовать файловые дескрипторы (например, write и close use) и FILE (например, fprintf using), используя такие функции, какfdopen.

1 голос
/ 31 марта 2019

Строка:

write(fd_fifo, str, sizeof(str));

вызывает запись неинициализированной памяти в fifo.Вы не хотите писать весь буфер str, а только размер строки, которую хотите передать.И вы можете узнать это по snprintf возвращаемому значению с помощью strlen(str).

int ret = sprintf(str, "%f", ...);
assert(ret > 0); // just to be safe
write(fd_fifo, str, ret);

Использование sprintf небезопасно для вас.Используйте snprintf для защиты от переполнения стека.

int ret = snprintf(str, sizeof(str), ....
// no changes

Таким образом sprintf никогда не будет записывать в буфер более sizeof(str) символов.

Однако лучший способ неиметь статически распределенный буфер.Вы можете использовать fdopen:

FILE *f = fdopen(fd_fifo, "w");
if (f == NULL) {
      // handle error
}
int ret = fprintf(f, "%f", ...);
if (ret < 0) {
      // handle error
}
fclose(f);

или заранее узнать размер буфера, снова вызвать malloc и snprintf:

int ret = sprintf(NULL, "%f", ...);
assert(ret > 0);
char *str = malloc(ret * sizeof(char));
if (str == NULL) { 
      // handler error
}
ret = snprintf(str, "%f", ...);
write(fd_fifo, str, ret);
free(str);
0 голосов
/ 31 марта 2019

Я решил проблему, решение меняло эту строку

write(fd_fifo, str, sizeof(str));

на

write(fd_fifo, str, strlen(str));

...