首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过命名管道将浮动转换为字符串并从C代码发送到Python

通过命名管道将浮动转换为字符串并从C代码发送到Python
EN

Stack Overflow用户
提问于 2019-03-31 14:32:18
回答 3查看 487关注 0票数 0

我希望使用命名管道将浮动值从C代码发送到Python代码中。我正在将接收到的值打印到Python端的终端中,但是除了值本身之外,还会显示一些乱七八糟的字符。

管口:

代码语言:javascript
复制
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,下面给出了代码

代码语言:javascript
复制
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);
}

然后,为了在端接收代码,我使用这个

代码语言:javascript
复制
#!/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

A备注:,如果我只发送"Hello!",它可以正常工作,没有任何问题。

我在这里错过了什么?提前谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-03-31 14:48:44

第一个危险标志在sprintf调用中;它不知道目标缓冲区str有多大,因此如果您不小心,可能会溢出。对于单个浮点数和64个字节,这个步骤应该很好。

但是,您没有存储返回值,因此此时您不知道格式化文本有多大。然后使用sizeof,它告诉您缓冲区有多大,而不是您刚刚将多少数据放入其中。您可以使用基于字符串的函数(因为sprintf编写了以nul结尾的字符串),例如strlen (用于测量字符串)或fputs (将字符串写入文件)。

一个简单得多的快捷方式可能是首先使用fprintf,而不需要分配单独的缓冲区(很可能使用内置在FILE中的缓冲区)来存储格式化的字符串。

可以(虽然不一定是可移植的或安全的)在文件描述符(如writeclose使用)和FILE (例如fprintf使用)之间使用fdopen等函数进行转换。

票数 2
EN

Stack Overflow用户

发布于 2019-03-31 14:59:11

这句话:

代码语言:javascript
复制
write(fd_fifo, str, sizeof(str));

正在导致未加密的内存被写入fifo。您不希望编写整个str缓冲区,只想写入要传递的字符串的大小。您可以通过使用snprintfstrlen(str)返回值来找出这个值。

代码语言:javascript
复制
int ret = sprintf(str, "%f", ...);
assert(ret > 0); // just to be safe
write(fd_fifo, str, ret);

使用sprintf对您来说是不安全的。使用snprintf防止堆栈溢出。

代码语言:javascript
复制
int ret = snprintf(str, sizeof(str), ....
// no changes

这样,sprintf就不会在缓冲区中写入比sizeof(str)字符更多的字符。

但是,最好的方法是没有静态分配的缓冲区。您可以使用fdopen

代码语言:javascript
复制
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:

代码语言:javascript
复制
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);
票数 1
EN

Stack Overflow用户

发布于 2019-03-31 17:29:54

我解决了问题,解决办法就是改变这条线。

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55441961

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档