从动态库中调用具有更改签名的函数?

问题描述 投票:0回答:1

说我有

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)

c memory dynamic-library
1个回答
1
投票

这是不可能的,因为通过无效指针调用函数会在代码中触发未定义的行为

您能做的最接近的事情就是保留一个集合签名并返回一个指向已知结构的指针,该结构包含“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");
© www.soinside.com 2019 - 2024. All rights reserved.