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

C++ 将unsigned char*buffer强制转换为可以接受参数的可调用void指针,c++,c,C++,C,我的问题是,我不知道如何正确地进行铸造,我的目标是调用将放置在buf中的方法 这是我的编译器错误 错误:“buf”不能用作函数 这是我当前的代码 ... unsigned char *getFileBuffer(const char filename[], long &fileSize) { ... } void (*ptrox)(int &) = NULL; int main() { long filesize = -1; int x = 3;

我的问题是,我不知道如何正确地进行铸造,我的目标是调用将放置在buf中的方法

这是我的编译器错误

错误:“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;
}

正确的类型转换如下所示:

ptrox = (void (*)(int &))buf;
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();
}
为什么不使用
dlopen
/
dlsym
加载函数?将不那么容易出错。此外,默认情况下,加载函数的内存将不可执行,因此如果尝试运行
ptrox
,它将得到
SIGSEGV

为了使用
libdl
,您需要在共享库中编译函数
foo
,并按如下方式加载:

ptrox = (void (*)(int &))buf;
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;
}
void*getFileBuffer(常量字符文件名[],长文件大小){
int fd=打开(仅文件名);
如果(fd<0){
佩罗(“公开”);
中止();
}
void*buf=mmap(
无效的
,文件大小
,PROT_READ | PROT_EXEC
,MAP_PRIVATE
,fd
, 0
);
if(buf==MAP_失败){
佩罗(“地图”);
中止();
}
返回buf;
}

对我来说,以下构造工作:
ptrox=(void(*)(int&)buf但不知道为什么需要围绕*的偏执

我通常如何处理这个问题:

typedef void *pfunc(int &);
那我可以用

ptrox = (pfunc)buf;

你需要C还是C++的答案,因为它会不同。请C++,但是如果你能提供一个解释,它们之间的差别会很大。括号是用的,所以<代码> */COD>不会被误解为返回类型的一部分(<代码>空白* <代码>)。实际上,您可能也应该将它们与
typedef
一起使用。这种转换是有条件支持的(C++11),或者是非法的(早期版本的C++)。在实践中,这通常是(非法)允许的,但通常不能保证指向函数的指针与指向数据的指针大小相同。该死,在typedef上忘记了它们,但对我来说,在typedef上更有意义,它说pfunc是指向函数的指针,(包含标识符和*)。文件“foo”只包含二进制指令,我的计划是尝试将一个方法注入到运行和修改x的程序中。除了此强制转换是非法的之外,至少在C++11之前的版本中是非法的(并且仅在C++11中有条件支持)。正确的赋值方法是
*(void**)(&ptrox)=dlsym(libhandle,“foo”)。同样的技术可以用于最初请求的强制转换,但在这种情况下,请注意,它可能无法在所有平台上正常工作(函数指针和数据指针的大小可能不同)。(Posix要求它工作。)@Ogelami在这种情况下,请确保包含加载的二进制指令的内存是可执行的。请注意,在大多数现代系统中,内存不能同时可写和可执行。我仍然建议使用动态加载程序以提高可移植性。哦,我真的不知道它不能同时是可写/可执行的。@Ogelami它可以是可读的和可执行的,但通常操作系统会拒绝同时使内存可写和可执行,以避免某些类型的攻击。