приведение беззнакового буфера char * к вызываемому указателю void, который может принимать аргумент

0

Проблема в том, что я не знаю, как правильно выполнять кастинг, моя цель - вызвать метод, который будет помещен в buf.

Это моя ошибка компилятора.

error: 'buf не может использоваться как функция

Это мой текущий код

...

unsigned char *getFileBuffer(const char filename[], long &fileSize)
{
    ...
}

void (*ptrox)(int &) = NULL;

int main()
{
    long filesize = -1;
    int x = 3;

    //buf will consist of a operation, that takes an referenced int as an argument.
    unsigned char *buf = getFileBuffer("foo", filesize);

    //This is obviously not correct and does not match the description.
    ptrox = (void *)&buf(int &);

    ptrox(x);

    cout << x;
}

И это фактический метод/буфер.

void i(int &x)
{
    x += 2;
}

__Z1iRi:
0000000100000cbb    55                  pushq   %rbp
0000000100000cbc    4889e5              movq    %rsp, %rbp
0000000100000cbf    48897df8            movq    %rdi, -0x8(%rbp)
0000000100000cc3    488b45f8            movq    -0x8(%rbp), %rax
0000000100000cc7    8b00                movl    (%rax), %eax
0000000100000cc9    8d5002              leal    0x2(%rax), %edx
0000000100000ccc    488b45f8            movq    -0x8(%rbp), %rax
0000000100000cd0    8910                movl    %edx, (%rax)
0000000100000cd2    5d                  popq    %rbp
0000000100000cd3    c3                  ret
  • 0
    Вам нужен ответ для C или C ++, потому что он будет другим.
  • 0
    C ++, пожалуйста, но если вы можете объяснить, чем они отличаются, это было бы здорово.
Теги:

2 ответа

2
Лучший ответ

Правильный тип будет выглядеть так:

ptrox = (void (*)(int &))buf;

Почему вы не используете dlopen/dlsym для загрузки функций? Будет меньше склонности к ошибкам. Также по умолчанию ваша память, в которую вы загружаете свою функцию, не будет выполняться, поэтому, если вы попытаетесь запустить ptrox она получит SIGSEGV.

Чтобы использовать libdl вам нужно будет скомпилировать вашу функцию foo например, в общей библиотеке и загрузить ее следующим образом:

void * libhandle = dlopen("foo.so", RTLD_NOW);
if (!libhandle) {
    perror("dlopen");
    abort();
}
ptrox = (void (*)(int &))dlsym(libhandle,
    "foo" // C function name (use extern "C" where appropriate)
    );
if (!ptrox) {
    perror("dlsym");
    abort();
}

Если вам нужно загрузить указатель функции C++ для загрузки, вам нужно будет использовать это измененное имя функции. Обратитесь к nm foo.so за ним.

Как выполнить mmap исполняемую память:

void * getFileBuffer(const char filename[], long fileSize) {
    int fd = open(filename, O_RDONLY);
    if (fd < 0) {
        perror("open");
        abort();
    }
    void * buf = mmap(
          NULL
        , fileSize
        , PROT_READ | PROT_EXEC
        , MAP_PRIVATE
        , fd
        , 0
    );
    if (buf == MAP_FAILED) {
        perror("map");
        abort();
    }

    return buf;
}
  • 0
    Файл 'foo' состоит только из двоичных инструкций, и я планирую ввести метод в мою программу, которая запускает и изменяет x.
  • 0
    За исключением того, что это приведение является недопустимым, по крайней мере, до C ++ 11 (и только условно поддерживается в C ++ 11). Правильный способ выполнения задания: *(void**)(&ptrox) = dlsym( libhandle, "foo" ); , Тот же самый метод может использоваться для первоначально запрошенного приведения, но в этом случае следует помнить, что он может работать некорректно на всех платформах (указатели функций и указатели данных могут иметь разные размеры). (Posix требует, чтобы это работало.)
Показать ещё 8 комментариев
0

Для меня работает следующая конструкция: ptrox = (void (*)(int &))buf; но не знаю, зачем нужна скобка вокруг *.

как я обычно справляюсь с этим:

typedef void *pfunc(int &);

то я могу использовать

ptrox = (pfunc)buf;
  • 0
    Круглые скобки используются, так что * не интерпретируется как часть возвращаемого типа ( void * ). На самом деле, вы, вероятно, должны использовать их также с typedef .
  • 0
    Это преобразование условно поддерживается (C ++ 11) или недопустимо (более ранние версии C ++). На практике это часто (незаконно) разрешалось, но, как правило, нет гарантии того, что указатели на функции имеют тот же размер, что и указатели на данные.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню