Проблема в том, что я не знаю, как правильно выполнять кастинг, моя цель - вызвать метод, который будет помещен в 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
Правильный тип будет выглядеть так:
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;
}
*(void**)(&ptrox) = dlsym( libhandle, "foo" );
, Тот же самый метод может использоваться для первоначально запрошенного приведения, но в этом случае следует помнить, что он может работать некорректно на всех платформах (указатели функций и указатели данных могут иметь разные размеры). (Posix требует, чтобы это работало.)
Для меня работает следующая конструкция: ptrox = (void (*)(int &))buf;
но не знаю, зачем нужна скобка вокруг *.
как я обычно справляюсь с этим:
typedef void *pfunc(int &);
то я могу использовать
ptrox = (pfunc)buf;
*
не интерпретируется как часть возвращаемого типа ( void *
). На самом деле, вы, вероятно, должны использовать их также с typedef
.