如何从 C 函数创建 shell 命令

2024-05-09

想知道如何获取一组 C 函数并将它们转换为 shell/bash 命令。

假设我有一组简单的 C 函数

int
fn1() {
  // some C code for function 1.
}

int
fn2() {
  // some C code for function 2.
}

int
fn3() {
  // some C code for function 3.
}

然后我想以某种方式创建 CLI 命令,以便我可以从终端使用它们。

$ fn1 <param> <param> ...
$ fn2 ...
$ fn3 ...

不确定这样做的过程是什么。如果我需要以某种方式重写 shell 脚本中的所有函数接口,然后以某种方式调用 C 函数,有点像这样(bash 脚本):

fn1() {
  callc mylib/fn1 $1 $2
}

fn2() {
  ...
}

...

或者,如果我可以通过将每个 C 函数分成单独的文件来自动将它们转换为 shell 脚本fn1.c, fn2.c等等,并以某种方式将它们加载到外壳中source ~/.bash_profile类型的事物。

任何帮助将不胜感激,谢谢。


或者也许采用老式方法:编写 C 代码来检查它是如何被调用的(原始命令行参数中的第 0 个参数)并根据该名称调用正确的 C 函数。需要将此类 C 程序编译为单个可执行文件,然后创建指向基本应用程序的符号链接,其中符号链接是感兴趣的函数的名称。除了将此处的工件(可执行文件和符号链接)安装到 $PATH 中的目录中之外,不需要 shell 代码。

例子。如果以下代码的名称为 toybox.c,并且 ~/bin 存在且位于用户的 $PATH 中,请使用类似以下内容的代码:

$ cc -o ~/bin/toybox toybox.c
$ ln -s toybox ~/bin/fn1
$ ln -s toybox ~/bin/fn2
$ ln -s toybox ~/bin/fn3

简单的测试 - 仅表明脚手架已就位。

$ fn1
fn1 invoked - no arguments.
$ fn3 1 2 'a b c'
fn3 invoked - arguments:
  1 - '1'
  2 - '2'
  3 - 'a b c'

toybox.c 的源代码可能如下所示:

#include <string.h>
#include <libgen.h>
#include <stdio.h>

struct name2func {
    const char *name;
    int (*func)(int ac, char *const av[]);
};

void
fn_debug(const char *fn, int ac, char *const av[])
{
    int n;

    printf("%s invoked - ", fn);

    if (ac <= 0) {
        printf("no arguments.\n");
    } else {
        printf("arguments:\n");
        for (n = 0; n < ac; n++) {
            printf("  %d - '%s'\n", n + 1, av[n]);
        }
    }
}

int
fn1(int ac, char *const av[])
{
    fn_debug("fn1", ac, av);
    /* some C code for function 1. */
    return 0;
}

int
fn2(int ac, char *const av[])
{
    fn_debug("fn2", ac, av);
    /* some C code for function 2. */
    return 0;
}

int
fn3(int ac, char *const av[])
{
    fn_debug("fn3", ac, av);
    /* some C code for function 3. */
    return 0;
}

/*
 * Establish a crude symbol table after function definitions: size of
 * the name2func array (i.e., its number of elements) is available via the
 * sizeof builtin.
 */

struct name2func n2f[] = {
  { "fn1", fn1 },
  { "fn2", fn2 },
  { "fn3", fn3 }
};

int
dispatch(const char *func_name, int ac, char *const av[])
{
    size_t n;

    /* linear search ok for small # of funcs */

    for (n = 0; n < sizeof n2f / sizeof n2f[0]; n++) {
        if (strcmp(func_name, n2f[n].name) == 0) {
            return (*n2f[n].func)(ac, av);
        }
    }

    fprintf(stderr, "%s: unsupported\n", func_name);
    return 1;
}

int
main(int argc, char *const argv[])
{
    /*
     * using POSIX basename(3) to create, say, "fn1" from
     * a full-path invocation like "/my/odd/dir/fn1".
     */
    char *fnbase = basename(argv[0]);

    if (fnbase == 0) {
        perror("basename");
        return 1;
    }

    return dispatch(fnbase, argc - 1, argv + 1);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 C 函数创建 shell 命令 的相关文章

  • 多个源的 makefile

    在学习 make 文件时 我试图为多个源目录编写一个 make 文件 似乎我在某个地方错了 这是我的代码结构 directory common fun2 c inc fun h src fun1 c main c 这是我的生成文件 CC c
  • 将 new 与 decltype 一起使用

    T t T is an implementation detail t new T want to avoid naming T to allow for flexibility t new decltype t error cannot
  • 为什么 F# 的默认集合是排序的,而 C# 的不是?

    当从 C 世界迁移到 F 最惯用的可能 思维方式时 我发现了这个有趣的差异 在 C 的 OOP mutable 世界中 默认的集合集合似乎是HashSet https learn microsoft com en us dotnet api
  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate
  • linq 中使用字符串数组 c# 的 'orderby'

    假设我有一个这样的方法定义 public CustomerOrderData GetCustomerOrderData string CustomerIDs var query from a in db Customer join b in
  • 在 C# 中调用 C++ 库 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有很多用 C 编写的库 我想从 C 调用这些库 但是 我遇到了很多问题 我想知道是否有书籍或指南告诉我如何做到这一点 Dll导入 htt
  • 从模板切换传递的类型

    在 C 中是否可以检查传递给模板函数的类型 例如 template
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 获取 boost Spirit 语法中的当前行

    我正在尝试使用 boostspirit 获取正在解析的文件的当前行 我创建了一个语法类和结构来解析我的命令 我还想跟踪在哪一行找到命令并将其解析到我的结构中 我将 istream 文件迭代器包装在 multi pass 迭代器中 然后将其包
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • MFC:如何设置CEdit框的焦点?

    我正在开发我的第一个简单的 MFC 项目 但我正在努力解决一个问题 想要设置所有的焦点CEdit其中一个对话框中的框 我的想法是 当打开对话框时 焦点位于第一个编辑框上 然后使用 选项卡 在它们之间交换 我看到了方法SetFocus 但我无
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 析构函数中的异步操作

    尝试在类析构函数中运行异步操作失败 这是代码 public class Executor public static void Main var c1 new Class1 c1 DoSomething public class Class
  • Project Euler #8,我不明白我哪里出了问题[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我正在做项目欧拉第八题 https projecteuler net problem 8 其中我得到了这个大得离谱的数字 7316
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • 如何调试 .NET 运行时中的内部错误?

    我正在尝试调试一些处理大文件的工作 代码本身works 但 NET 运行时本身会报告零星错误 对于上下文 这里的处理是一个 1 5GB 文件 仅加载到内存中一次 在循环中处理和释放 故意尝试重现此否则不可预测的错误 我的测试片段基本上是 t
  • 需要提取字符串中点后的最后一个数字,如“7.8.9.1.5.1.100”

    我需要提取 C 字符串中最后一个点后面的最后一个数字 例如 7 8 9 1 5 1 100 并将其存储在整数中 Added 该字符串也可以是 7 8 9 1 5 1 1 或 7 8 9 1 5 1 0 我还想验证它在最后一个点之前恰好是 7
  • 通过 Tab 键浏览 XML 文档字段

    In VB NET you can move through the fields in the XML member documentation with the Tab key 这在 C 中不起作用 还有其他方法吗 除了用鼠标将光标放在
  • 为什么以下 C 程序会出现总线错误?

    我认为这是第一个失败的 strtok 调用 好久没写C了 有点不知所措 非常感谢 include
  • INotifyPropertyChanged 和 propertyName

    我一直不确定它的含义propertyName实施时INotifyPropertyChanged 所以一般来说你实现INotifyPropertyChanged as public class Data INotifyPropertyChan

随机推荐