在 C 语言中,函数指针作为来自某些库的回调的通常路径是为用户的上下文包含一个 void*
指针:
void (*fp)(void* ctx);
允许库使用上下文 ctx
调用回调。
假设我使用的库在回调中不包含上下文指针。我将需要为每个上下文设置一个回调。在 C 中动态分配函数指针以提供回调的最便携方法是什么?我如何malloc()
一个可以从库中调用的函数代码?
例如:
typedef void (*my_fp_t)(char);
my_fp_t fp = (my_fp_t) malloc(sizeof(...));
init_function_ptr(fp, "Hello, there");
my_library_callback(fp);
...
void my_library_callback(my_fp_t fp) {
fp('a'); // prints "Hello, there"
}
最佳答案
假设您希望分配实际的函数代码,而不是函数指针。在编写引导加载程序和类似程序时这样做的方式:
- 非常确定编译器和 ABI 使用的底层调用约定。您需要确切地知道函数调用和返回时堆栈帧中的哪些寄存器和/或位置。
- 通过在 C 编译器中编写函数并仔细复制/粘贴程序集,或者通过在汇编器中手动编写函数来生成汇编代码。
- 将汇编程序翻译成操作码。
- 确保有一 block 内存可以存储数据和执行代码。这也取决于 ABI 和 MMU 设置。
- 了解如何在此自定义段中分配内存。通常涉及一些链接器脚本摆弄和各种非标准关键字。
#pragma __declspec __attribute__
blabla 上面有糖。高度特定于编译器。 - 将内存作为原始
uint8_t func [n]
数组分配给此区域,其中包含十六进制的原始 OP 代码。 - 关闭严格的别名和其他类似的邪恶指针转换。从对象指针到函数指针时,请确保您的编译器具有一些定义明确的非标准扩展。
- 通过
((func_ptr)func) ()
调用代码。
正如您所希望的那样,这可能是一项艰巨的任务,具体取决于系统。对于使用嵌入式系统编译器的小型微 Controller 来说,这在某种程度上是很容易实现的。对于像 x86 或 PowerPC 这样更复杂的系统,使用像 gcc 这样的编译器就没那么简单了。您将依赖于各种未明确指定的行为,并且代码将完全是系统特定的。
关于c - 如何动态分配函数代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54182269/