Ich versuche, eine Methode zu finden, um von einem Programm aus das Vorhandensein einer oder mehrerer ".c" -Dateien zu überprüfen und eine oder mehrere Funktionen davon zu laden.
Grundsätzlich hätte ich ein "Haupt" -Programm, das prüft, ob die Datei "script.c" existiert, und (falls vorhanden) die main () -Funktion dieses Programms startet.
Hier ist der Inhalt meines "Haupt" -Programms vor der Kompilierung:
int main(int argc, char *argv[]){
...
if(argc == 1){
FILE *file;
if((file = fopen("script.c", "r"))){
printf("file script.c loaded.");
// to compile the script.c file and modify on it the "main()" function to "_main()" (in order to be able to recompile it with the main library) before restarting the program
int ret = system("gcc -c script.c && objcopy --redefine-sym main=_main script.o && gcc main script.o -o main &&./main -l script.o");
printf("ret(0)=%d\n", ret);
}
else{
int ret = system("./main -l");
printf("ret(1)=%d\n", ret);
}
}
else{
if(argc == 3 && strcmp(argv[2], "script.o") == 0){
_main(argc, argv);
}
else{
printf("no file found.\n");
}
}
...
}
Er ist der Inhalt meiner "script.c"-Datei:
int main(int argc, char *argv[]){
...
printf("main() function in script.c loaded.\n");
...
}
Wenn die script.c-Datei vorhanden ist, sollte das Ausführen von main folgendes ergeben:
file script.c loaded.
ret(0)=0
main() function in script.c loaded.
Wenn die script.c-Datei nicht existiert, sollte main Folgendes geben:
file script.c loaded.
ret(1)=0
no file found.
Offensichtlich funktioniert dies aus mehreren Gründen nicht.
Haben Sie eine Idee, wie ich mein Ziel erreichen kann? Also von einem einzelnen ausführbaren Programm (hier "main") aus, um das Vorhandensein einer externen Datei (hier "script.c") zu überprüfen und eine oder mehrere Funktionen daraus zu starten... PS: Habe es schon bei anderen gesehen Projekte, ich weiß, dass es möglich ist, aber ich kann die Lösung nicht finden. PS2: Es muss nur die ausführbare Datei (main) und evtl. die script.c-Datei vorhanden sein (also keine main.c...was daher vielleicht darauf hindeutet, dass eine "main"-Datei mit der zugehörigen "main.o" zusammengeführt werden sollte würde entpackt und ausgeführt)
Lösung des Problems
Also von einem einzigen ausführbaren Programm (hier "main") aus, um das Vorhandensein einer externen Datei (hier "script.c") zu überprüfen und eine oder mehrere Funktionen daraus zu starten...
Ich gehe davon aus, dass die von main
Ihnen erwähnte Funktion nicht die wichtigste ist, und zeige, wie Sie innerhalb Ihres Programms Sammlungen von Funktionen in gemeinsam genutzte Bibliotheken kompilieren können, die Sie laden und dann Funktionen (außer main
) darin ausführen.
Ein einfacher Treiber könnte so aussehen:
// driver.c
#include <dlfcn.h> // to be able to dynamically load shared libraries
#include <stdio.h>
#include <stdlib.h>
// the signature of the `start` function you decide to have in all the files:
typedef void(*start_func_t)(void);
int main(int argc, char *argv[]){
char sys[1024];
for(int i = 1; i < argc; ++i) { // loop through all the arguments
// try to compile the argument into an object file
// (use a safer version than sprintf in real code)
sprintf(sys, "gcc -fPIC -c -o %s.o %s", argv[i], argv[i]);
if(system(sys)) {
printf("%d failed\n", sys);
exit(1);
}
// try to create a shared library from the object file
sprintf(sys, "gcc -shared -o libcurrent.so %s.o", argv[i]);
if(system(sys)) {
printf("%d failed\n", sys);
exit(1);
}
// load the shared library you just created
(void)dlerror();
void *handle = dlopen("./libcurrent.so", RTLD_NOW | RTLD_LOCAL);
if(!handle) {
puts(dlerror());
exit(1);
}
// lookup the "start" symbol in the shared library:
start_func_t start = dlsym(handle, "start");
if(!start) {
puts(dlerror());
exit(1);
}
// call the loaded function:
start();
dlclose(handle); // close the library
}
}
Sie müssen das obige Programm mit der dl
Bibliothek verknüpfen, also sollte so etwas funktionieren:
gcc -o driver driver.c -ldl
Wenn Sie nun einige Beispieldateien erstellen:
// t1.c
#include <stdio.h>
void start(void) { puts("Hello world"); }
// t2.c
#include <stdio.h>
void start(void) { puts("another file"); }
und dann ausführen:
./driver t1.c t2.c
Es sollte diese Ausgabe erzeugen, wenn alles funktioniert:
Hello world
another file
Ich habe auch einen Test gemacht, um zu sehen, wie das funktioniert, wenn ich main
die Bibliothek einsetze. Das heißt, ändern Sie die start_func_t
Signatur in:
typedef int(*start_func_t)(int argc, char *argv[]);
main
und stattdessen laden und aufrufen:
start_func_t start = dlsym(handle, "main");
if(!start) {
puts(dlerror());
exit(1);
}
// call the loaded function with some example arguments:
char *cargv[] = {
"foo", "hello", "world", NULL
};
start(3, cargv);
und ändern Sie die Testprogramme geringfügig:
// t1.c
#include <stdio.h>
int main(int argc, char *argv[]) {
for(int i = 0; i < argc; ++i) {
printf("t1: %s\n", argv[i]);
}
}
// t2.c
#include <stdio.h>
int main(int argc, char *argv[]) {
for(int i = 0; i < argc; ++i) {
printf("t2: %s\n", argv[i]);
}
}
und das hat auch gut funktioniert. Allerdings main
ist es ein bisschen speziell und ich bin mir nicht sicher, ob dies gegen irgendwelche Regeln verstößt.
Keine Kommentare:
Kommentar veröffentlichen