How to compile an application in C with a module?

I want to make an application that can be compiled with the help of plug-ins, such as, for example, in php. In php you can load modules at runtime or compile php with the module, so modules are available with no download at runtime. But I do not understand how this can be done. If I have a module module.c, and there is one feature called say_hello, how do I register it in the main application, if you know what I mean?

/* 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!"); } 

If I compile all of these files (main + application modules) with a reference to the function say_hello from the main application is not available, because it is only called when the user calls it in your code. So how can I say in my application, hey, there is a function say_hello, if someone wants to call it, you know that it exists.

EDIT1: I need to have something like a table at runtime, where I can see if the called user function exists (ie C is equivalent to). Header files do not help me.

EDIT2: My application is interpreted for my script langugage.

EDIT3: If someone calls a function in php, the php interpretation should know that the function exists. I know about dynamic linking and if .so or .dll is loaded, some kind of start procedure is called, and you can have a simple registration function in this DLL, so php interpretation can see if some module registered, for example, a function called say_hello. But if I want to compile php with gd support, such as gd-functions are registered in any php functions list, hash table or something else?

+4
source share
4 answers

I assume that you are looking for dynamic libraries (we call runtime loadable modules as dynamic / shared libraries in C and in the OS world as a whole). Take, for example, the Pidgin , which supports plug-ins to extend its functionality. It gives a specific interface for plugin developers to perform, for example, recording function, loading, unloading and use, to be followed by plug-ins.

When the program is loaded, it searches in it such dynamic libraries plugins , if any, it will download and use it, otherwise it will skip the opening functionality. The reason why the interface is required, is that because the different modules may have different features that are unknown to the execution application. It must have a common, consistent way to "talk" with him plugins / modules.

Each C program can be associated with static or dynamic library; static will copy the code from the library to the specified program, leaving no dependencies to run the program, and upon binding to the dynamic library is expected that the shared library will be present at the start of the program. The third way to do this - not to associate with DLL, and simply ask the OS to execute the load operation of the library. If it succeeds, then you have a dynamic module, otherwise ignored. Functionality, which should perform a dynamic library, given to the user only if the download is successful challenge.

It should be noted that this feature is provided by the operating system, and it has nothing to do with the used language (C or C ++ or Python does not matter here); as far as C reports, the compiler still refers to known code, that is, code available at compile time. This is the reason for the different operating systems, you need to write different code to load the dynamic module. Moreover, the type of file / libraries syuch format varies from system to system. In Linux, it was called shared objects (.so), on the Mac it is called dynamic link libraries (.dylib), and In Windows - dynamic library link (.dll).

+2
source

C is not interpreted. Therefore, you need a reference, you may need a static binding or dynamic linking.

Creating a program consists of two main stages: collection and layout. At compile time, all c files are converted into machine code, leaving unresolved callable functions ( obj or o files). Then, the linker combines these files into a single executable file, deciding that it not be allowed.

This static binding. Related module becomes an integral part of the executable file.

Dynamic binding is specific to the platform. Under the windows of this DLL. You must issue a system call for the DLL load, after which you will be able to call the function from it.

+1
source

You need a dynamic library . First, consider the example in Linux dlopen manual page (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); } print the cosine of 2.0: * / /* 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); } ; /* 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); } RTLD_LAZY); /* 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); } n", dlerror ()); /* 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); } (*) (double)) dlsym (handle, "cos"); /* 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); } standard leaves /* 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); } function pointer undefined. /* 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); } )! = NULL) { /* 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); } , (* cosine) (2.0)); /* 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); } 

There's also a C dlopen mini HOWTO ++ .

For more general information about the dynamic loading of the first wikipedia page .

+1
source

I think that this is impossible, if I understand what you mean. Because it is a compiled language.

-5
source

All Articles