【问题标题】:Handling array returned by c program in nodeJs server处理nodeJs服务器中c程序返回的数组
【发布时间】:2021-08-23 03:04:21
【问题描述】:

我编译了一个C 程序(array.out 编译自 array.c in linux),它返回一个指向双精度数组的指针。

array.c

#include <stdio.h>
#include <stdlib.h>

double* main(int argc, char *argv[]){
    double *arr;
    arr = (double *)calloc((3), (unsigned)(sizeof(double)));
    arr[0] = 10;
    arr[1] = 20;
    arr[3] = 30;
    return arr;
}

我还有一个正在运行的 express nodejs 服务器:

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
})

有没有办法调用 c 程序(array.out)并在 express nodeJs 服务器中处理其响应(arr)?

【问题讨论】:

  • 是的,通过 http 服务器 .. 尽管下面提到了一般错误
  • C 中的main 不能返回双精度数组。它必须返回一个int,该int作为结果代码传回shell。
  • 你可以发C++ addon
  • 您可以编写 C 程序以将 double 数组输出到 stdout,然后 node.js 执行该程序并获取输出。见How to execute an external program from within node.js
  • sizeof(...) 已经返回了一个无符号类型(size_t),完全不需要转换为unsigned int。在最坏的情况下,您甚至可能会截断大小信息(想象一下 16 位 unsigned int 和超过 65k 字节的 huge 结构)。承认,这只是理论上的性质,但实际上演员阵容仍然不正确。

标签: javascript node.js arrays c express


【解决方案1】:

savageGoat 已经给出了solution 的完整答案,但是关于编写更好的 C 代码的一些额外提示:

double *arr;
arr = (double *)calloc((3), (unsigned)(sizeof(double)));

请跳过所有不必要的括号,它们只会使代码更难阅读。赋值可以直接与声明一起发生,但这只是个人喜好问题:

double *arr = (double *)calloc(3, (unsigned)sizeof(double));

强制转换为unsigned int 是不必要的,sizeof 已经计算为无符号类型 (size_t)。实际上,强制转换甚至在技术上是错误的,因为您可能会以这种方式切断大小信息:想象一下 16 位无符号整数和一个超过 65k 字节的 huge 结构 - 承认,这是理论上的性质,但是演员阵容仍然不正确。

此外,无论如何您都在分配值,因此calloc 所做的零初始化只是不必要的镇流器,因此在 这种 情况下更喜欢malloc

double *arr = (double *)malloc(3 * sizeof(double));

现在仍然存在内存泄漏!当然,操作系统会为您清理它,因为进程无论如何都会终止,但是从一开始就开始使用,以考虑在这样做的时候(甚至之前......)释放任何动态分配的内存。否则,您在运行时间较长的进程中遇到内存泄漏。

更好的是:在堆栈上分配数组,如果不是太大的话;在这种情况下,您甚至可以立即对其进行初始化:

double arr[] = { 10.0, 20.0, 30.0 }; // size is calculated by compiler

最后,在这种情况下,您根本不需要数组:

printf("%f %f %f

实际上,你甚至根本不需要动态分配的数组:

printf("%f %f %f", 10.0, 20.0, 30.0);

只要确保使用 正确 字面量(10, 20, 30 将提供三个 int 值,编译器也会接受,但会引发未定义的行为,因为它与所需的类型不匹配用于格式说明符)。

【讨论】:

    【解决方案2】:

    您正在寻找的是带有exec 方法的child_process 模块

    const { exec } = require('child_process');
    const res = exec("./array", (error, stdout, stderr) => {
        // console.log({ error, stdout, stderr });
        const myResult = stdout.split(' ').map(e => parseFloat(e));
        console.log(myResult);
    });
    

    另一方面,您需要输出值让节点处理它

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]){
        double *arr;
        arr = (double *)calloc((3), (unsigned)(sizeof(double)));
        arr[0] = 10;
        arr[1] = 20;
        arr[2] = 30;
        printf("%f %f %f", arr[0], arr[1], arr[2]);
        return 0;
    }
    

    【讨论】:

    • 这还不够:必须捕获标准输出。
    • 我只是在这里提出这个问题Is there a way to call that c program (array.out),NodeJS 方面的答案是child_process,如果您的问题是can I trigger a function on my C program with NodeJS?,答案是肯定的,通过处理参数并将该参数传递给execSync 命令
    • 在我看来,用户想要从父进程中的子进程检索信息非常明显:'返回一个指向双精度数组的指针'。因此,完整的答案也需要涵盖该部分。
    • @kapil-sarwat 我看到的唯一方法是运行将结果转储到文件中的程序,然后读取该新文件。除此之外,我不知道还能怎么做,但我很乐意接受任何建议,因为我认为这是一个很好的问题,如果有其他方法我真的很感兴趣
    • @kapilsarwat 有,但它们并不那么简单:管道、套接字、共享内存……——数据甚至可以作为二进制传递,但这只有在 C 和 python 都使用时才有效双精度的相同表示(C 使用主机的表示,通常是 IEEE 754,假设 python 相同,但不确定!)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    相关资源
    最近更新 更多