Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用模块在C中编译应用程序?_C++_C - Fatal编程技术网

C++ 如何使用模块在C中编译应用程序?

C++ 如何使用模块在C中编译应用程序?,c++,c,C++,C,我想做一个应用程序,它可以用外部模块编译,比如php。在php中,您可以在运行时加载模块,也可以将php与模块一起编译,这样就可以在运行时不加载模块。但我不明白这是怎么做到的。若我在module.c中有一个模块,并且有一个函数叫做say_hello,若你们明白我的意思,我如何将它注册到主应用程序中 /* module.c */ #include <stdio.h> // here register say_hello function, but how, if i can't in

我想做一个应用程序,它可以用外部模块编译,比如php。在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!");
}
/*module.c*/
#包括
//这里注册say_hello函数,但是如果我不能在全局范围内
//调用另一个函数?
void说你好
{
printf(“你好!”);
}
若我将所有这些文件(主应用程序+模块)一起编译,那个么就并没有从主应用程序中调用say_hello函数的参考,因为只有当用户在其代码中调用它时,才会调用它。所以,我如何对我的应用程序说,嘿,有一个say_hello函数,如果有人想调用它,你知道它存在

EDIT1:我需要在运行时有类似于table的东西,在这里我可以看到是否存在用户调用的函数(使用C equivalent)。头文件对我没有帮助

编辑2:我的应用程序是为我的脚本语言翻译的


EDIT3:如果有人在php中调用函数,php必须知道该函数存在。我知道动态链接,如果加载了.so或.dll,则调用一些启动例程,您可以在该dll中简单地注册函数,以便php解释可以看到,如果某个模块注册了名为“say_hello”的示例函数。但是,如果我想使用例如gd支持编译php,那么gd函数是如何注册到某个php函数列表、哈希表或其他什么东西的呢?

C不是解释语言。所以您需要链接,您可能需要静态链接或动态链接

程序构建包括两个主要阶段:编译和链接。在编译过程中,所有的c文件都被翻译成机器代码,使得调用的函数无法解析(
obj
o
文件)。然后链接器将所有这些文件合并到一个可执行文件中,解决未解决的问题

这是静态链接。链接模块成为可执行文件不可分割的一部分


动态链接是特定于平台的。在windows下,这些是DLL。您应该发出一个系统调用来加载DLL,然后您就可以从中调用函数了。

如果我理解您的意思,我认为这是不可能的。因为它是编译语言。

我想您要找的是动态库(我们通常在C和操作系统中称运行时可加载模块为动态/共享库)。举个例子,它支持插件来扩展它的功能。它为插件制造商提供了一个特定的接口,比如注册、加载、卸载和使用的功能,插件必须遵循这些功能

当程序加载时,它会在它的
plugins
目录中寻找这样的动态库,如果存在,它会加载并使用它,否则它会跳过公开功能。之所以需要一个接口,是因为不同的模块可以具有不同的功能,而这些功能在正常运行时是未知的。必须有一个共同的、一致同意的方式来“谈论”它的插件/模块

每个C程序都可以链接到静态或动态库;静态将把代码从库复制到所述程序,不留下程序运行的依赖项,而链接到动态库则期望在程序启动时动态库出现。第三种方法不是链接到DLL,而是要求操作系统执行库的加载操作。如果成功,则使用动态模块,否则忽略。只有在加载调用成功时,动态库应该执行的功能才会向用户公开


注意,这是一个操作系统提供的特性,它与所用的语言无关(C或C++或Python在这里不重要);就C而言,编译器仍然链接到已知代码,即在编译时可用的代码。这就是不同操作系统的原因,需要编写不同的代码来加载动态模块。此外,syuch库的文件类型/格式因系统而异。在Linux中称为共享对象(.so),在Mac中称为动态库(.dylib),在Windows中称为动态链接库(.dll)。

您需要的是动态库。让我们首先看一下中提供的示例:

/*加载数学库,并打印2.0的余弦:*/
#包括
#包括
#包括
int main(int argc,字符**argv){
无效*手柄;
双(*余弦)(双);
字符*错误;
handle=dlopen(“libm.so”,RTLD_-LAZY);
如果(!句柄){
fprintf(stderr,“%s\n”,dlerror());
退出(退出失败);
}
dlerror();/*清除任何现有错误*/
/*书写:余弦=(双(*)(双))dlsym(手柄,“cos”);
看起来更自然,但C99标准的叶子
从“void*”强制转换为未定义的函数指针。
下面使用的作业是一种变通方法*/
*(void**)(&cosine)=dlsym(手柄,“cos”);
如果((error=dlerror())!=NULL){
fprintf(stderr,“%s\n”,错误);
退出(退出失败);
}
printf(“%f\n”,(*余弦)(2.0));
dlclose(手柄);
退出(退出成功);
}
还有一个


有关动态加载的更多一般信息,请从第一个开始。

1。选择:C或C++,而不是两者。2.拿你最喜欢的课本3。转到谈论库的页面。你需要阅读动态库。通常,对于C程序,你需要自己定义插件/模块API。例如,插件是一个具有某个预定名称的函数的DLL,您可以使用适合该平台的API加载该DLL。(在POSIX上应该是
dlopen()
)。然后,该函数将返回某种字典结构,将名称映射到函数指针或描述结构
/* 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);
}