简体   繁体   English

将unsigned char * buffer转换为可以接受参数的可调用void指针

[英]casting unsigned char * buffer to a callable void pointer that can take an argument

The problem i have is that i don't know how to do the casting properly, my objective is to call the method that will be placed in the buf. 我遇到的问题是我不知道如何正确地进行投射,我的目标是调用将放置在buf中的方法。

This is my compiler error. 这是我的编译器错误。

error: 'buf' cannot be used as a function 错误:'buf'不能用作函数

This is my current code 这是我目前的代码

...

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;
}

And this is the actual method / buffer. 这是实际的方法/缓冲区。

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

A correct typecast would look like this: 正确的类型转换看起来像这样:

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

Why don't you use dlopen / dlsym for loading functions? 为什么不使用dlopen / dlsym来加载函数? Will be less error prone. 会少出错。 Also by default your memory into which you load your function will not be executable, so if you try to run ptrox it will get a SIGSEGV . 此外,默认情况下,加载函数的内存将不可执行,因此如果您尝试运行ptrox ,它将获得SIGSEGV

In order to use libdl you would need to compile your function foo for example in a shared library and load it like this: 为了使用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();
}

If you require to load a C++ function pointer to be loaded then you will need to use it's mangled function name. 如果需要加载要加载的C ++函数指针,则需要使用它的错位函数名。 Consult nm foo.so for it. 请咨询nm foo.so

How to mmap executable memory: 如何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;
}

For me the following construct works: ptrox = (void (*)(int &))buf; 对我来说,以下构造有效: ptrox = (void (*)(int &))buf; but don't know why the paranthesis around * is needed. 但不知道为什么需要围绕*的禁忌。

how i usually handle this: 我通常如何处理这个:

typedef void *pfunc(int &);

then i can use 然后我可以使用

ptrox = (pfunc)buf;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM