简体   繁体   English

C void *函数指针参数

[英]C void* function pointer argument

I'm trying to create a task queue in the ARM. 我正在尝试在ARM中创建任务队列。 The basic idea is the following. 基本思想如下。

typedef void (*funcpointer)(void *);     // the argument being passed will be a void pointer that I can hopefully typecast

struct sQueue{
   funcpointer       func_address;        // this stores the address of the function to be called
   void              *func_parameter;                   // this stores the address of the struct that is passed to the function
   uint32_t          TimeStamp;                  // the time at which the function should be called     
};

sQueue Func_List[10];

The plan is to be able to put the address of the function that should be called in Func_List[x].func_address. 计划是要把应该调用的函数的地址放在Func_List [x] .func_address中。

I would like to be able to put the address of functions that accept pointers to different struct types in func_address. 我希望能够将接受指向不同结构类型的指针的函数的地址放入func_address中。 Here's an example: 这是一个例子:

void Config_ADC(sADC_Settings *pSettings);

void Enable_RX(sRX_Top_Settings *pSettings);

Both functions accept effectively a 32-bit pointer to a struct, but in these cases the structs are of different types. 这两个函数都有效地接受指向结构的32位指针,但是在这些情况下,这些结构具有不同的类型。

When I try to assign Func_List[x].func_address = Config_ADC the compiler complains: 当我尝试分配Func_List [x] .func_address = Config_ADC时,编译器抱怨:

a value of type "void (*)(sADC_Settings *)" cannot be assigned to an entity of type "funcpointer" 类型“ void(*)(sADC_Settings *)”的值不能分配给“ funcpointer”类型的实体

Any ideas on how I can achieve this? 关于如何实现此目标的任何想法? I can of course change the function Config_ADC to accept a void* pointer and then typecast it inside the function, but I don't really want to do that. 我当然可以将函数Config_ADC更改为接受void *指针,然后在函数内部进行类型转换,但是我并不是真的想要这样做。

IIRC it is UB to call a function through a function pointer with a different signature. IIRC通过具有不同签名的函数指针来调用函数是UB。

You will need a proxy function for each non matching function type. 对于每种不匹配的函数类型,您将需要一个代理函数。

void Config_ADC(sADC_Settings *pSettings);
void Config_ADC_proxy(void *pSettings){
  Config_ADC((sADC_Settings*) pSettings);
}

A solution is to cast the void pointer inside the function: 一种解决方案是将void指针转换为函数内部:

void Config_ADC(void *p)
{
    sADC_Settings *pSettings = (sADC_Settings *)p;

(Actually I don't like this because it unnecesarilly takes up another variable, however, I think it is already better than proxy functions that involve stack management and call management overhead. The compiler shouldn't bother when void * is involved; then there would be no overhead at all.) (实际上,我不喜欢这样,因为它不必要地占用了另一个变量,但是,我认为它已经比涉及栈管理和调用管理开销的代理函数更好。当涉及到void *时,编译器不应理会;然后在那里完全没有开销。)

Your particular ABI specification (specific to the target processor, the operating system, and perhaps even the compiler) dictates how C functions are called and with which calling conventions . 您的特定ABI规范(特定于目标处理器,操作系统,甚至可能是编译器)规定了如何调用C函数以及使用哪种调用约定 Beware that some formal arguments may get passed thru some hardware registers. 注意,某些形式的参数可能会通过某些硬件寄存器传递。

I suggest to use typedef -s to define any signature of functions called thru pointers: 我建议使用typedef -s定义称为指针的函数的任何签名:

typedef void myroutofint_t(int);
typedef int  myintof2int_t (int, int);

If you are sure of the signature of the called function and if you can list all the signatures of functions called thru a pointer, you could use an unamed union (in C99 or C11): 如果确定被调用函数的签名并且可以通过指针列出被调用函数的所有签名,则可以使用未修饰的并集(在C99或C11中):

struct sQueue{
 enum functiontype_en funtype;
 union {
   void* funaddress;
   myroutofint_t *funroutofint;
   myintof2int_t *funintof2int;
 };
 // othe fields of SQueue
 };

The C standard does not even require that function pointers and data pointers live in the same address space and have same size. C标准甚至不需要功能指针和数据指针位于相同的地址空间中并且具有相同的大小。 But POSIX does, and we assume that. 但是POSIX会这样做,我们假设是这样。

BTW, you might need libffi . 顺便说一句,您可能需要libffi

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

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