Do you know you can use a function pointer in the structure?
I assume your answer is “YES” but however if your answer is “NO”, then it is my recommendation that you should read the article “How to use the structure of function pointer in C?”
In this blog post, I will explain the different uses of function pointers and structure together. Also, I will explain how to achieve polymorphism in C with the help of a function pointer and structure.
Primary prerequisites for this topic:
Now let’s see the different uses of function pointers in the C structure. But before explanation, I want to give a quick summary of how and why to create function pointers in structure.
How to declare a function pointer in C within a structure?
C is not an object-oriented language, so it does not contain the member functions like C++. In short, In C language we can’t create the function in structure. But using the function pointer we can provide this feature. These function pointers behave like the member function and we can also support polymorphism in C.
For example,
In the below example, a structure contains some function pointers.
struct SERVER_COM { int iLenData; void (*pfSend)(const char *pcData,const int ciLen); int (*pfRead)(char *pData); } GATEWAYCOM;
The prototype looks messy. You can make it easy and readable with the help of typedef keyword. Let’s use the typedef for the same declaration and make the prototype easy and readable, see the below code.
//Aliasing with typedef typedef void (*pfSend)(const char *pcData,const int ciLen); typedef int (*pfRead)(char *pData); //structure contains function pointers struct SERVER_COM { int iLenData; pfSend pSendToServer; pfRead pReadFromServer; } GATEWAYCOM
Now I believe you have a basic idea of how to create a function pointer in C structure. So let’s see the uses of function pointer in structure without wasting any time.
Uses of function pointers in the structure:
There are a lot of places where the function pointer is used in the structure. Below I am describing some places where function pointer is useful in structure.
Function pointers and structure together for polymorphism:
C is not an object-oriented language and it does not support the concept of oops. So when in C programming, you intend to do some form of polymorphism, then you need to use the function pointers.
To accomplish this task we need to create a function pointer within the structure and initialize the function pointer with the corresponding function. It will create an illusion of polymorphism and provide the run time-binding.
Let consider an example,
Suppose you want to communicate with a server with TCP/IP and the most important thing is that it is not an end. Maybe in the future, you select the other way (UDP) for server communication.
So here you can think to create a structure with some function pointers. This structure represents the generic containers and the function pointers behave like the C++ member functions.
typedef struct { int (*OpenSocket)(void); int (*CloseSocket)(int); int (*ReadFromServer)(int,char*,short); int (*WriteToServer) (int,char*,short); } sCommStructure;
We have created the above typedef structure for the general-purpose communication library. You only need to initialize the member of this structure as per the communication protocol types as per your requirement.
So if your project uses the TCP/IP protocol for server communication, you need to initialize the structure with the TCP/IP function. See the below configure function.
Initialize the structure variables for TCP/IP communication
sCommStructure *CreateTcpComm(void) { sCommStructure *psComTcpIp = malloc (sizeof (sCommStructure)); if (psComTcpIp != NULL) { psComTcpIp -> OpenSocket = &TcpSocketCreate; psComTcpIp -> CloseSocket = &TcpSocketClose; psComTcpIp -> ReadFromServer = &TcpSocketReceive; psComTcpIp -> WriteToServer = &TcpSocketSend; } return psComTcpIp; }
But if your project uses the UDP protocol for server communication, you need to initialize the structure with the UDP functions. Like the below expression,
Initialize the structure variables for UDP communication
sCommStructure *CreateUdpComm(void) { sCommStructure *psComUdp = malloc (sizeof (sCommStructure)); if (psComUdp!= NULL) { psComUdp -> OpenSocket = &UdpSocketCreate; psComUdp -> CloseSocket = &UdpSocketClose; psComUdp -> ReadFromServer = &UdpSocketReceive; psComUdp -> WriteToServer = &UdpSocketSend; } return psComUdp; }
Now functions OpenSocket, CloseSocket, ReadFromServer and WriteToServer are used for both TCP/IP and UDP. You only need to configure with specific protocol.
Suppose, now we need to communicate with the server using the TCP/IP, then just called the CreateTcpComm function in your application.
For Example,
int CommunicationWithTcp(char *Rqst, short lenRqst, char *Rsp,short RvcSize) { int hSocket = -1; short shortRetval = -1; //Call Create TcpComm function for tcp/Ip communication sCommStructure *psTcpcomm = CreateTcpComm (); //Create Socket hSocket = psTcpcomm->OpenSocket(); if(hSocket < 0) { printf("Socket Creation Failed: SOCKET_HANDLER = %d", hSocket); return SOCKET_FAILED; } else { printf("Socket Creation Success: SOCKET_HANDLER = %d", hSocket); } //Send data shortRetval = psTcpcomm->WriteToServer(hSocket, Rqst, lenRqst); if(shortRetval<0) { printf("Socket Request Send Failed: RET_VALUE = %d", shortRetval); return SEND_FAILED; } else { printf("Socket Request Send Success: RET_VALUE = %d", shortRetval); } shortRetval = psTcpcomm->ReadFromServer(hSocket, Rsp, RvcSize); if(shortRetval<0) { printf("Socket REsponse Receive Failed: RET_VALUE = %d", shortRetval); return RECV_FAILED; } else { printf("Socket Request Receive Success: RET_VALUE = %d", shortRetval); } psTcpcomm->CloseSocket(hSocket); return 0; }
In this way, a single type could be used for UDP, SNA, and RS232 with exactly the same interface.
Implementation of the callback function:
In device drivers and low-level programming, function pointer frequently uses in structure. A lot of call back functions are used in the case of windows driver. This callback function is registered using the structure of function pointer in the driver for the simplicity and bug-free coding.
For Example,
In the case of the PNP device, there is an AdDevice call-back function which is called by PnP manager. This call-back function is used to create a device object for the driver and registered all PNP call-back functions using structure-function pointers.
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = MyDeviceEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceD0Entry = MyDeviceEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = MyDeviceEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
Resolve issues by using function pointer as a member of C struct:
If you have worked on a C project where the string is frequently used, then you have faced an issue related to string length. If the length of your string changes frequently, you always need to call the strlen() function to calculate the length of the string it looks bad in terms of readability.
Using the structure and function pointer together makes it more readable. See the below code.
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Sstring { char *ch; int bufSize; int (*length)(struct Sstring *self); } Sstring; /* Calculate string length */ int calStringLen(Sstring *self) { return strlen(self->ch); } /* Initialization of all required resources */ Sstring *init(int n) { Sstring *str = malloc(sizeof(Sstring)); if(str) { str->ch = calloc(n, sizeof(char)); if(str->ch != NULL) { //buffer size str->bufSize = n; str->length = calStringLen; } else { free(str); str = NULL; } } return str; } /* Deinitialization of all required resources */ void deinit(Sstring *self) { if(self != NULL) { if(self->ch != NULL) { free(self->ch); } self->length = NULL; free(self); self = NULL; } } int main() { //Called Initializer Sstring *p = init(50); if(p!= NULL) { printf("Enter Sting = "); fgets(p->ch,p->bufSize,stdin); printf("\n%s",p->ch); printf("String length = %d\n\n", p->length(p)); } //called Deinitializer deinit(p); return 0; }
Output:
Your opinion matters
Although here I have tried to cover the uses of function pointer and structure I would like to know your opinion on the function pointer in structure. So please don’t forget to write a comment in the comment box.
Recommended Articles for you,
- How to pass an array as a parameter in C?
- How to access a two-dimensional array using pointers in C?
- Brief Introduction of switch case in C.
- A brief description of the pointer in C.
- Dangling, Void, Null and Wild Pointers
- How to use function pointer in C?
- Replace the nested switch case using an array and function pointer.
- Implement state machine in C.
- Function pointer in structure.
- Pointer Arithmetic in C.
- void pointer in C.
- 10 questions about dynamic memory allocation.
- Memory Layout in C.
- 100 C interview Questions
- File handling in C.
- C format specifiers.