如何动态分配功能代码? [英] How to dynamically allocate function code?

查看:85
本文介绍了如何动态分配功能代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C语言中,将函数指针用作来自某些库的回调的常用方法是在用户上下文中包含void*指针:

In the C language, the usual route for function pointers as callbacks from some library is to include a void* pointer for the context of the user:

void (*fp)(void* ctx);

这允许库使用上下文ctx调用回调.

The allows the library to call the callback with context ctx.

比方说,我使用的库在回调中不包含上下文指针.我将需要为每个上下文一个回调.在C中动态分配函数指针以提供回调的最便捷方法是什么?如何malloc()可以从库中调用的功能代码?

Let's say I'm using a library that does not include a context pointer in the callbacks. I will need to have one callback for each context. What is the most portable way to dynamically allocate function pointers in C for providing callbacks? How can I malloc() a function code that can be called from the library?

例如:

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

推荐答案

假定您希望分配实际的功能代码,而不是功能指针.编写引导加载程序和类似内容时的完成方式:

Assuming you wish to allocate the actual function code, rather than the function pointer. The way this is done when writing bootloaders and similar:

  • 对编译器和ABI使用的基础调用约定不确定.您需要确切地知道在堆栈框架中哪些寄存器和/或位置在函数调用和返回时一切正常.
  • 通过在C编译器中编写函数并仔细复制/粘贴程序集,或通过在汇编程序中手动编写函数来生成汇编程序代码.
  • 将汇编程序转换为操作码.
  • 确保有一块内存可以存储数据和执行代码.这也取决于ABI和MMU的设置.
  • 了解如何在此自定义段中分配内存.通常涉及一些链接描述文件摆弄和各种非标准关键字. #pragma __declspec __attribute__ blabla,上面放糖.高度特定于编译器.
  • 将内存作为原始uint8_t func [n]数组分配给该区域,以十六进制形式包含原始OP代码.
  • 关闭严格的别名和其他此类邪恶的指针转换之类的东西.从对象指针到函数指针时,请确保您的编译器具有一些定义良好的非标准扩展.
  • 通过((func_ptr)func) ()调用代码.
  • Be dead certain about the underlying calling convention used by the compiler and ABI. You'll need to know exactly which registers and/or places in the stack frame where everything goes upon function call and return.
  • Generate the assembler code either by writing a function in the C compiler and carefully copy/paste the assembly, or by manually writing the function in assembler.
  • Translate assembler to op codes.
  • Ensure there's a chunk of memory where you can both store data and execute code. This is also up to the ABI and the MMU setup.
  • Find out how to allocate memory in this custom segment. Typically involves some linker script fiddling and various non-standard keywords. #pragma __declspec __attribute__ blabla with sugar on top. Highly compiler-specific.
  • Allocate memory to this area as a raw uint8_t func [n] array, containing the raw OP codes in hex.
  • Shut off strict aliasing and other such evil pointer conversion things. Ensure that your compiler has some well-defined, non-standard extension when going from object pointers to function pointers.
  • Call the code through ((func_ptr)func) ().

如您所愿,这可能是一项艰巨的任务,具体取决于系统.对于使用嵌入式系统编译器的小型微控制器,这在某种程度上很容易实现.对于诸如x86或PowerPC之类的更复杂的系统,使用诸如gcc之类的编译器,要少得多.您将依靠各种错误指定的行为,并且代码将完全是特定于系统的.

As you hopefully can tell, this can be quite a task, depending on system. For small microcontrollers using embedded systems compilers, it is somewhat easily achievable. For more intricate systems like x86 or PowerPC, using compilers like gcc, far less so. You'll be relying on various poorly-specified behavior and the code will be completely system-specific.

这篇关于如何动态分配功能代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆