说我有
hello1.c
char *greeting = "Hello, Version 1";
char *greet(void) {
return greeting;
}
和
hello2.c
int greeting = 42;
int greet(void) {
return greeting;
}
我的
host.c
看起来像这样:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <unistd.h>
#define LIBHELLO_SO "libhello.so"
void load_and_call_greet() {
// Open the shared library
void *dynamic_lib = dlopen(LIBHELLO_SO, RTLD_LAZY);
if (!dynamic_lib) {
fprintf(stderr, "%s\n", dlerror());
return;
}
// Define a function pointer for the function we want to call
char *(*greet)(void);
// Get the function from the shared library
greet = (char *(*)(void)) dlsym(dynamic_lib, "greet");
// Check for errors
char *error;
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
dlclose(dynamic_lib); // Close the library before exiting
return;
}
// Call the function and print the result
printf("%s\n", greet());
// Close the shared library
dlclose(dynamic_lib);
}
int main() {
while (1) {
load_and_call_greet();
sleep(5); // Wait for 5 seconds before reloading the library
}
return 0;
}
然后,我编译并运行主机文件,并且在不终止主机文件的情况下,我想将动态库交换为新签名(从
hello1.c
到hello2.c
):
/ ./host
/ prints "Hello, Version 1" every 5 seconds
/ in another terminal re-compile libhello.so but use `hello2.c` as source file rather than `hello1.c`
/ expected result: ./host prints 42
/ actual result: './host terminated by signal SIGSEGV (Address boundary error)
是否可以更改
host.c
代码以从动态库中加载具有更改签名的函数?
我尝试了几种使用 ChatGPT 的方法,但它给出了
SIGSEGV (Address boundary error)
。
这是不可能的,因为通过无效指针调用函数会在代码中触发未定义的行为。
您能做的最接近的事情就是保留一个集合签名并返回一个指向已知结构的指针,该结构包含“void *”以及有关它所指向内容的信息。
例如:
你好.h:
#define TYPE_INT 1
#define TYPE_CHARP 2
struct hello {
int type;
void *value;
};
你好1.c:
#include <stdlib.h>
#include <string.h>
#include "hello.h"
char *greeting = "Hello, Version 1";
struct hello *greet(void) {
struct hello *p = malloc(sizeof *p);
p->type = TYPE_CHARP;
p->value = strdup(greeting);
return greeting;
}
hello2.c:
#include <stdlib.h>
#include "hello.h"
int greeting = 42;
struct hello *greet(void) {
struct hello *p = malloc(sizeof *p);
p->type = TYPE_INT;
p->value = malloc(sizeof(int));
*p->value = greeting;
return greeting;
}
然后调用它:
#define TYPE_INT 1
#define TYPE_CHARP 2
struct hello {
int type;
void *value;
};
// Open the shared library
void *dynamic_lib = dlopen(LIBHELLO_SO, RTLD_LAZY);
if (!dynamic_lib) {
fprintf(stderr, "%s\n", dlerror());
return;
}
// Define a function pointer for the function we want to call
struct hello *(*greet)(void);
// Get the function from the shared library
greet = (struct hello *(*)(void)) dlsym(dynamic_lib, "greet");
// Check for errors
char *error;
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
dlclose(dynamic_lib); // Close the library before exiting
return;
}
// Call the function and print the result
struct hello *result = greet();
if (result->type == TYPE_INT) {
print("%d\n", *((int *)result->value));
} else if (result->type == TYPE_CHARP) {
printf("%s\n", *((char *)result->value));
}
free(result->value);
free(result);
// Close the shared library
dlclose(dynamic_lib);
char *(*greet)(void);
// Get the function from the shared library
greet = (char *(*)(void)) dlsym(dynamic_lib, "greet");