获取struct调用函数的指针

时间:2011-04-28 07:47:45

标签: c function pointers callback struct

对于当前项目,我不能使用C ++(不幸的是),只能使用纯C,而且我有以下问题:

我有3个独特的结构,需要调用相同的函数名称,我感觉它更优雅的方式在下面,而不是为不同的类型创建3个不同的功能,就像我觉得它更容易维护。如何获取调用该函数的指针?基本上我正在尝试重现的内容基本上与C ++中的“this”或者自我(在Obj-C中)类似,无论如何我可以在普通的C中做到这一点吗?

[test.h]

enum
{  
    TYPE_A = 0,  
    TYPE_B = 1,  
    TYPE_C = 2  
};

typedef struct  
{  
    char type;    
    void ( *GetType )( void );  
    // Some other data different than the other struct  
}A;  


typedef struct  
{  
    char type;  
    void ( *GetType )( void );  
    /* Some other data different than the other struct */  
}B;  


typedef struct  
{  
    char type;  
    void ( *GetType )( void );  
    // Some other data different than the other struct  
} C;

A *create_a( void );

B *create_b( void );

C *create_c( void );

void GetType( void );

[test.c]

A *create_a( void )  
{  
    A *a = ( A * ) calloc( 1, sizeof( A ) );  
    a->type = TYPE_A;  
    a->GetType = GetType;  
    return a;  
}

B *create_b( void )  
{  
    B *b = ( B * ) calloc( 1, sizeof( B ) );  
    b->type = TYPE_B;  
    b->GetType = GetType;  
    return b;  
}


C *create_c( void )
{  
    C *c = ( C * ) calloc( 1, sizeof( C ) );  
    c->type = TYPE_C;  
    c->GetType = GetType;  
    return c;  
}


void GetType( void )  
{  
    printf("How to get the pointer that call this function to retrieve the type?");  
}  

[main.c]

int main (int argc, const char * argv[])  
{  
    A *a = create_a();  
    B *b = create_b();  
    C *c = create_c();  

    a->GetType();  
    b->GetType();  
    c->GetType();  

    return 0;  
}

4 个答案:

答案 0 :(得分:0)

执行此类操作的传统方法(例如在UNIX内核中)是使用#define语法糖:

#define GET_TYPE(X) ((X)->GetType((X)))

当然,如果有更多的论据,它也会传递这些论点。函数指针通常收集在一个静态“ops”结构中,该结构在创建时分配(而不是每个单独的函数指针)。每个ops向量都有一个相应的#defines集合。

答案 1 :(得分:0)

“this”应作为GetType()的参数给出。这就是对象方法实际上是如何实现的。此外,由于GetType应该能够与所有类型的结构进行交互 - 结构应该具有类似的“基类”。例如:

#include "stdio.h"

typedef enum
{  
TYPE_A = 0,  
TYPE_B = 1,  
TYPE_C = 2  
} my_class_type;

typedef struct  
{  
char type;    
my_class_type ( *GetType )( void* );  
}my_base;  

my_class_type my_base_GetType( void* my_base_ptr)  
{  
    return ((my_base*)my_base_ptr)->type;
}  

typedef struct  
{
    my_base base;
    // Some other data different than the other struct  
}A;  


typedef struct  
{  
    my_base base;
/* Some other data different than the other struct */  
}B;  


typedef struct  
{  
    my_base base;
// Some other data different than the other struct  
}C;

A *create_a( void )  
{  
A *a = ( A * ) calloc( 1, sizeof( A ) );  
a->base.type = TYPE_A;  
a->base.GetType = my_base_GetType;  
return a;  
}

B *create_b( void )  
{  
B *b = ( B * ) calloc( 1, sizeof( B ) );  
b->base.type = TYPE_B;  
b->base.GetType = my_base_GetType;  
return b;  
}


C *create_c( void )
{  
C *c = ( C * ) calloc( 1, sizeof( C ) );  
c->base.type = TYPE_C;  
c->base.GetType = my_base_GetType;  
return c;  
}




int main(int argc, char* argv[])
{
    A *a = create_a();  
    B *b = create_b();  
    C *c = create_c();  

    printf("%d\n",a->base.GetType(a));  
    printf("%d\n",b->base.GetType(b));  
    printf("%d\n",c->base.GetType(c));  
    return 0;
}

此示例实现继承和多态。所有结构共享相同的基本核心,如果要覆盖GetType(),只需更改base中的指针即可。您可以保存指向my_base的指针并动态解析类型。

答案 2 :(得分:0)

将此作为正常参数传递(首先是常规参数):

void GetType(void *this);
...
GetType(a); // instead of C++-style a->GetType

最好有一些“基类”(包括“int type”字段),在这种情况下,指针将是“struct Base * this”,而不是“void * this”。

我个人总是这样走。您可以为某些“类”的函数添加前缀(例如,Cl1_GetType)。这是C语言中的OO编程方式。也可以使用通过函数指针的“真实虚函数”,但这不是常见的情况。

答案 3 :(得分:0)

从我对你的问题的理解是:“你只想获取GetType函数中结构中的类型字段的值”。这是正确的吗?如果是,你可以这样做:

enum
{  
    TYPE_A = 0,  
    TYPE_B = 1,  
    TYPE_C = 2  
};

typedef struct  
{  
    char type;    
    // Some other data different than the other struct  
}A;  


typedef struct  
{  
    char type;    
    /* Some other data different than the other struct */  
}B;  


typedef struct  
{  
    char type;  
    // Some other data different than the other struct  
} C;


A *create_a( void );

B *create_b( void );

C *create_c( void );

void GetType( void * );

[test.c的]

  A *create_a( void )  
    {  
        A *a = ( A * ) calloc( 1, sizeof( A ) );  
        a->type = TYPE_A;  
        return a;  
    }

    B *create_b( void )  
    {  
        B *b = ( B * ) calloc( 1, sizeof( B ) );  
        b->type = TYPE_B;  
        return b;  
    }

    C *create_c( void )
    {  
        C *c = ( C * ) calloc( 1, sizeof( C ) );  
        c->type = TYPE_C;  
        return c;  
    }
#define GetType(x) (x->type)

[main.c中]

int main (int argc, const char * argv[])  
{  
    A *a = create_a();  
    B *b = create_b();  
    C *c = create_c();  

    GetType(a);  
    GetType(b);  
    GetType(c);  

    return 0;  
}

希望这能回答你的问题。