我想做应用程序,可以用外部模块编译,例如在php中。在php中,您可以在运行时加载模块,或者将模块与模块一起编译,因此模块可以在运行时加载而无需加载。但我不明白如何做到这一点。如果我在module.c中有模块,并且有一个名为say_hello的函数,如果你理解我的意思,我如何将它注册到主应用程序?
/* module.c */
#include <stdio.h>
// here register say_hello function, but how, if i can't in global scope
// call another function?
void say_hello()
{
printf("hello!");
}
如果我将所有文件(主应用程序+模块)编译在一起,则不会从主应用程序引用say_hello函数,因为仅当用户在其代码中调用它时才会调用它。那么我怎么能对我的应用说,嘿,有say_hello功能,如果有人想叫它,你知道它存在。
EDIT1:我需要在运行时使用像table这样的东西,在那里我可以看到用户是否存在函数(具有C equivavent)。头文件对我没有帮助。
EDIT2:我的应用程序是我的脚本langugage的解释。
EDIT3:如果有人在php中调用函数,php解释必须知道该函数存在。我知道动态链接,如果加载了.so或.dll,那么调用一些启动例程,你可以在该dll中简单地注册函数,所以php解释可以看到,如果某些模块注册了例如名为“say_hello”的函数。但是如果我想用例如gd支持编译php,那么如何将gd函数注册到某些php函数列表,哈希表等等?
答案 0 :(得分:2)
我想你正在寻找的是动态库(我们将运行时可加载模块称为C和OS世界中的动态/共享库)。举例来说,Pidgin支持插件以扩展其功能。它为它的插件制作者提供了一个特定的接口,比如注册,加载,卸载和使用的功能,插件必须遵循这些接口。
当程序加载时,它会在它的plugins
目录中查找这样的动态库,如果存在,它将加载并使用它,否则它将跳过暴露功能。需要接口的原因在于,由于不同的模块可以具有不同的功能,这些功能在运行时是一个未知的应用程序。必须有一个共同的,商定的方式“谈论”它的插件/模块。
每个C程序都可以链接到静态或动态库; static会将代码从库复制到所述程序,在那里不会让程序运行依赖,而链接到动态库则需要在程序启动时存在动态库。第三种方法,不是链接到DLL,而只是要求操作系统执行库的加载操作。如果成功,则使用动态模块,否则忽略。只有在加载调用成功时,动态库应该执行的功能才会向用户公开。
需要注意的是,这是一个操作系统提供的功能,它与所使用的语言无关(C或C ++或Python在这里无关紧要);就C而言,编译器仍链接到已知代码,即编译时可用的代码。这就是不同操作系统的原因,需要编写不同的代码来加载动态模块。更重要的是,syuch库的文件类型/格式因系统而异。在Linux中,它被称为共享对象(.so),在Mac中称为动态库(.dylib),在Windows中称为动态链接库(.dll)。
答案 1 :(得分:1)
C不是解释语言。所以你需要链接,你可能需要静态链接或动态链接。
计划构建包括两个主要阶段:编译和链接。在编译期间,所有c文件都被转换为机器代码,使被调用的函数无法解析(obj
或o
文件)。然后链接器将所有这些文件合并为一个可执行文件,解决未解决的问题。
这是静态链接。链接模块成为可执行文件的组成部分。
动态链接是特定于平台的。在Windows下,这些是DLL。您应该发出一个系统调用来加载DLL,之后您就可以从中调用函数。
答案 2 :(得分:1)
您需要的是动态库。我们先来看看the Linux manpage of dlopen(3)中提供的示例:
/* Load the math library, and print the cosine of 2.0: */
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen("libm.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
/* Writing: cosine = (double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is a workaround. */
*(void **) (&cosine) = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
printf("%f\n", (*cosine)(2.0));
dlclose(handle);
exit(EXIT_SUCCESS);
}
有关动态加载的更多常规信息,请先从the wikipedia page开始。
答案 3 :(得分:-5)
如果我明白你的意思,我认为这是不可能的。因为它是编译语言。