模块化编译时数组扩展

2024-04-16

假设我处于这种情况:

main.c :

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

 #include "header.h"

 int iCanProcess (char* gimmeSmthToProcess);

 int processingFunctionsCount = 0;
 int (*(*processingFunctions)) (char*) = NULL;

 int addProcessingFunction(int (*fct)(char*)) {
     processingFunctionsCount++;
     processingFunctions = realloc(processingFunctions, 
               sizeof(int (*)(char*))*ProcessingFunctionsCount);
   processingFunctions[processingFunctionsCount-1] = fct;
 }

 int main(int argc, char *argv[]) {
     char* dataToProcess = "I am some veeeery lenghty data";
     addProcessingFunction(iCanProcess);

     [ ... ] 

     for(unsigned int i = 0; i < processingFunctionsCount; i++) {
         processingFunctions[i](dataToProcess);
     }

     free(processingFunctions);
   return 0;
 }

 int iCanProcess (char* gimmeSmthToProcess) { ... }

一些文件.c:

 #include "header.h"

 int aFunction(char* someDataToProcess) { ... }  

标头.h:

  #ifndef HEADER_DEF
  #define HEADER_DEF

  extern int processingFunctionsCount;
  extern int (*(*processingFunctions)) (char*);

  int addProcessingFunction(int (*fct)(char*));

  #endif

有什么方法,使用宏或任何其他技巧,我可以添加aFunction指向函数指针的数组processingFunctions不改变main.c or header.h每次我需要添加一个?

这里的问题不是改变数组,因为它可以很容易地重新分配,而是不改变main()函数:必须有一种方法可以让我知道文件在这里并被编译,并在保持外部的情况下获取函数原型main()

我考虑过使用像这样的预处理器技巧this one https://stackoverflow.com/questions/4904255/how-can-i-generate-a-list-via-the-c-preprocessor-cpp但似乎没有找到合适的方法......

(旁注:这是一个更大项目的精简版本,实际上是支持具有相同输出但不同输入的解析器的基本代码。一些解析器支持某些类型的文件,所以我有一个函数指针数组(每个解析器一个,检查它们是否兼容),我根据文件内容调用每个解析器。然后,我要求用户选择要使用的解析器。每个解析器有一个文件,包含一个“检查”函数,看看解析器是否可以处理这个文件,以及一个“解析”函数来实际完成所有艰苦的工作。我不能每次添加解析器时都更改标头或 main.c 文件。)

(旁注 2:这个标题太糟糕了……如果您有更好的想法,请随意编辑它并删除此注释。谢谢)


您可以将每个函数作为一个模块(Windows 的共享对象或 dll)带有已知名称的单个符号,然后在运行时只需扫描目录以查找.sos or .dll加载每个并创建一个指向该符号的指针,假设您有N模块,其中i第一个模块源代码是

模块.i.c

int function(char *parameter)
{
     // Do whatever you want here
     return THE_RETURN_VALUE;
}

然后你编译每个.c文件到共享对象中,我将使用 Linux 进行说明,在 Windows 上您可以做类似的事情,并且 Linux 解决方案适用于 POSIX 系统,因此它涵盖了很多内容

首先生成模块.i.c包含此脚本的文件

#!/bin/bash

for i in {0..100};
do
    cat > module.$i.c <<EOT
#include <stdlib.h>

int
function(char *parameter)
{
    // Deal with parameter
    return $i;
}
EOT
done

现在创建一个Makefile像这个

CC = gcc
LDFLAGS =
CFLAGS = -Wall -Werror -g3 -O0
FUNCTIONS = $(patsubst %.c,%.so, $(wildcard *.*.c))

all: $(FUNCTIONS)
    $(CC) $(CFLAGS) $(LDFLAGS) main.c -o main -ldl

%.so: %.c
    $(CC) -shared $(CFLAGS) $(LDFLAGS) $< -o $@

clean:
    @rm -fv *.so *.o main

以及将加载模块的程序(我们假设它们与可执行文件位于同一目录中)

#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <dlfcn.h>

int
main(void)
{
    DIR *dir;
    struct dirent *entry;
    dir = opendir(".");
    if (dir == NULL)
        return -1;
    while ((entry = readdir(dir)) != NULL)
    {
        void *handle;
        char path[PATH_MAX];
        int (*function)(char *);
        if (strstr(entry->d_name, ".so") == NULL)
            continue;
        if (snprintf(path, sizeof(path), "./%s", entry->d_name) >= sizeof(path))
            continue;
        handle = dlopen(path, RTLD_LAZY);
        if (handle == NULL)
            continue; // Better: report the error with `dlerror()'
        function = (int (*)(char *)) dlsym(handle, "function");
        if (function != NULL)
            fprintf(stdout, "function: %d\n", function("example"));
        else
            fprintf(stderr, "symbol-not-found: %s\n", entry->d_name);
        dlclose(handle);
    }
    closedir(dir);
    return 0;
}

在 Windows 上,想法是相同的,尽管您无法像上面的代码那样遍历目录,并且需要使用LoadLibrary() https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175%28v=vs.85%29.aspx代替dlopen(),并替换dlsym()具有适当的功能。

但同样的想法也可行。

有关如何保护您加载的模块及其文件夹的更多信息,请参阅这个问题 https://stackoverflow.com/questions/34722352/how-can-i-secure-the-plugins-i-load

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

模块化编译时数组扩展 的相关文章

  • 查询父实体时导航属性为空

    下面是我的域实体的基类 public interface IBaseEntity public int Id get set public DateTime CreatedDate get set public DateTime Updat
  • 将 viewbag 转换为 javascript 数组

    我想将数据从 ViewBag mytags 获取到 Javascript 数组 但我无法执行此操作 function var sampleTags new Array var array Html Raw Json Encode ViewB
  • 如何转换温度传感器得到的值?

    我在ST工作Temperature sensor hts221 我用I2C与传感器的命令通信 我从文档中看到类似以下文字 enter code here Temperature data are expressed as TEMP OUT
  • 如何解决警告“没有明确的所有权”

    我有一种方法 它采用间接指针作为参数 然后 如果出现错误 将其设置为错误对象 我正在尝试打开尽可能多的警告 但其中之一 Implicit ownership types on out parameters 在此方法中生成警告 id doWi
  • 在 C# 中快速加载/读取 TIFF 文件

    我正在编写一个处理 TIFF 图像的 C 应用程序 主要是显示文件 重新排序页面 删除页面 分割多页图像 将单个图像合并为一个多页图像等 我们处理的大多数图像都较小 无论是文件大小还是页码 但也有一些较大的图像 显示图像时 我们需要将多页
  • 修改文件流

    我现在正在开发一个允许编辑非常大的文本文件 4Gb 的类 嗯 这可能听起来有点愚蠢 但我不明白如何修改流中的文本 这是我的代码 public long Replace String text1 String text2 long repla
  • C++ 多重继承关闭同名运算符

    是否可以从两个不同的抽象类继承仅返回类型不同的同名运算符 如果是这样 他们 实现运算符的语法是什么 使用 解析运算符的语法是什么 与任何其他虚函数相同 一般情况下的开销是多少 如果您可以向我提供参考或示例代码 将会有所帮助 thanks 1
  • 为什么宇宙飞船与盒子对撞机相撞后不再回头?

    我希望当发生碰撞时将宇宙飞船转回来 但他们继续前进 开箱即用的对撞机和地形 使克隆船在碰撞时我想返回的脚本 using System using UnityEngine using Random UnityEngine Random usi
  • C# 中的私有“集合” - 无法理解它

    我见过很多使用类似的东西编写的示例代码 请原谅这是多么可怕的罐头 public class Test public object Thingy get private set 不幸的是 这些例子从未真正解释为什么 set 被设置为私有 所以
  • 为什么在用 size 声明的向量上使用 Push_back 会导致向量为零?

    我制作了一个恒定大小的向量来存储负值 然后打印我得到的所有值都是零 我只是想知道为什么它不存储负值 include
  • 在哪里可以找到 C 语言的位移指南? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我看过什么是按位移位 bit shift 运算符以及它们如何工作 https stackoverflow com questions
  • 使用 List.Sort(Comparison Comparison 在 C# 中对列表进行排序

    我创建了一个类 如下所示 public class StringMatch public int line num public int num of words 我创建了一个列表 List
  • valgrind 错误“大小 4 的读取无效”[重复]

    这个问题已经存在了 这是我的程序 int fun1 void int n 9 int pf n cout lt lt pf lt
  • C# 计算 int 数组中值的平均值

    当我尝试打印 int 数组中的值的平均值时 它会打印出与我有值一样多的完全不同的东西 这是什么问题 int numbers numbers new int 5 Console WriteLine give five integer numb
  • 避免调用成员变量的构造函数

    我有以下 C 类 Header File class A public A private B m B C m C cpp File A A m B 1 m B doSomething m B doMore m C C m B getSom
  • 使用 cmake 和 opencv 对符号“gzclose”的未定义引用[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我尝试构建该项目 doppia https bitbucket org rodrigob doppia 但发生链接错误 我想这是一
  • 使用实体框架而不使用 using 语句的缺点?

    有很多这样的代码块 public class SomeController Controller DbEntities entity new DbEntities public ActionResult Add entity someOpe
  • 展平数组中的对象

    大家好 我从响应中获取了一系列对象 我需要将所有学生对象展平为简单的学生姓名 但不确定如何进行 任何帮助将不胜感激 数组示例 students id 123456 name Student Name active true students
  • C#中同步接口和实现注释的方法

    是否有自动方法在接口及其实现之间同步注释 我目前正在记录它们 并且不想手动使它们保持同步 UPDATE 考虑这段代码 interface IFoo
  • C 中的 NULL 是否需要/定义为零?

    在我的 GCC 测试程序中 NULL 似乎为零 但维基百科说NULL只需要指向不可寻址的内存 有编译器做吗NULL非零 我很好奇是否if ptr NULL 是比更好的练习if ptr NULL is guaranteed to be zer

随机推荐

  • DSP 库 - RFFT - 奇怪的结果

    最近我一直在尝试在我的STM32F4 Discovery评估板上进行FFT计算 然后将其发送到PC 我已经调查了我的问题 我认为我对制造商提供的 FFT 函数做错了 我正在使用 CMSIS DSP 库 现在我一直在用代码生成样本 如果工作正
  • Expo RN:分离与弹出

    我目前有一个使用 Expo create react native app 在 React Native 中构建的应用程序 需要一些本机代码 据我了解 有两种选择可以下降到纯反应本机 弹出和分离 鉴于到目前为止我已经使用了相当多的 Expo
  • AltBeacon 应用程序在几分钟后重新启动

    我的应用程序遇到一些问题 我在禁用 RegionBootstrap 并通过 System exit 0 关闭应用程序后 我的应用程序在几分钟后 通常是 3 4 分钟 会自行重新启动 这是我每次重新启动应用程序时发现的 Logcat 行 20
  • 寻找硬币组合以产生给定找零的递归方法不正确

    我最近正在做一个项目欧拉问题 即 31 它基本上是找出使用集合 1 2 5 10 20 50 100 200 的元素可以求和到 200 的有多少种方法 我使用的想法是这样的 求和到 N 的方法的数量等于 对 N k 求和的方式数量 对 k
  • 如何提高派生类中属性的变化?

    我该如何提高PropertyChanged for SomeProperty在班上B 此示例无法编译 因为PropertyChanged无法通过这种方式访问 public class A INotifyPropertyChanged pub
  • 单元测试 Laravel FormRequest

    我正在尝试对各种自定义进行单元测试FormRequest输入 我找到的解决方案是 建议使用 this gt call 方法并断言response与预期值 答案链接 https stackoverflow com questions 2979
  • 需要帮助使用 Google Apps 脚本查找 Google 表格中的列中的最大值

    我有一张有几千行和两列的工作表 我需要编写一个脚本 该脚本将增加行并将其中一列中的值与同一列中的前 50 个值进行比较 并查看它是否大于前 50 个条目的最大值 我一直在尝试使用 Math max 但找不到正确的语法来使其在动态范围内工作
  • 如何获取文件目录的绝对路径?

    如何获取包含指定文件的目录的绝对路径 current dir is home me dev File file new File target test txt assert absolute file equals home me dev
  • 对三元运算符语句中的“意外 T_ECHO”进行故障排除

    DAO gt get num rows 1 echo is echo are 这似乎没有按预期为我工作 我收到错误 Unexpected T ECHO 我希望它能回应 是 或 是 我已经尝试过 条件周围没有括号 我是否无法以这种方式使用三元
  • 如何更改Vuforia AR相机对焦模式?

    我在用Vuforia 6 2 AR SDK对于在Unity中 但是当我在 Android 手机中测试该应用程序时 相机看起来像blurry 我在 Vuforia 的开发者网站中搜索并找到了一些相机对焦模式 但我无法实现 因为该指南适用于较旧
  • 何时使用 Hibernate 投影?

    我对 Hibernate 有点困惑预测 and criteria 何时使用预测以及何时使用标准 它们并不相互排斥 您可以同时使用两者 预测通常在某些标准的背景下使用 简而言之 Hibernate Projections 用于仅查询您使用 C
  • 无法在 Python 中分配 1.6 GB

    这段代码产生一个MemoryError from pylab import complex128 import numpy x numpy empty 100000000 dtype complex128 100 millions comp
  • 在 os.startfile() 中运行时隐藏控制台?

    我有一个 bat带有参数的文件 我使用运行它os startfile test bat 有没有办法隐藏其控制台 我尝试使用subprocess 效果很好 但是当我关闭父程序时subprocess这是使用编译的py2exe控制台模式也关闭 i
  • TinyMCE有效元素:只允许特定的CSS规则

    小MCE的valid elements属性允许您定义有效 HTML 元素及其属性的白名单 您可以仅允许段落和链接 tinyMCE init valid elements p a href 但是 那style属性有点问题 它对于某些事情 例如
  • SSRS堆叠条形图标签位置

    我正在使用 SQL Server 2012 SSRS 我有一个堆积的条形图 其中包括利息和股息 我想将这些值的总和添加到堆积条形图上方的区域 我尝试过调整标签的各种属性 但我无法将标签位置设置在堆叠条形图中间以外的任何位置 有什么想法如何让
  • 使用 PowerShell 将 Azure 活动日志连接到 Log Analytics 实例

    有没有办法使用 PowerShell 将 Azure 活动日志配置为转发到 Log Analytics 实例 本质上与使用本页概述的门户执行的操作相同 https learn microsoft com en us azure azure
  • 当使用 mkstemp() 创建的文件被删除时?

    我有一个程序调用 mkstemp 用返回的 fd 写入一些内容 然后关闭 fd 我希望保留该文件 直到我自己删除它 使用 rm 命令或其他命令 我的问题是 Linux会在close fd 后删除这个文件吗 Linux在close fd 后会
  • 返回对象的 ECMAScript 6 箭头函数

    当从箭头函数返回一个对象时 似乎有必要使用一组额外的 and a return关键字 因为语法中存在歧义 这意味着我不能写p gt foo bar 但必须写p gt return foo bar 如果箭头函数返回对象以外的任何内容 and
  • jquery 1.9 手风琴高度问题

    我正在使用一个手风琴 其父级高度为 400px 我希望手风琴的高度永远不会大于 400px 但我也希望手风琴的各个元素能够根据其内容的大小进行调整 通过将 heightStyle 设置为 fill 我可以使整个手风琴的高度为 400px 在
  • 模块化编译时数组扩展

    假设我处于这种情况 main c include