I have a requirement in C similar to function overriding. I have 2 devices with different device IDs. I have a process which just calls device_create(device_id). The process doesn't know which device_create to call. It is upto driver of the device to execute device_create if the device_id matches to driver's device Id. Is there any way to do it in C?
-
put some code you tried with – Chandrayya G K Feb 26 '14 at 11:43
-
Take a look at the factory pattern. – Klas Lindbäck Feb 26 '14 at 11:46
-
read this http://lwn.net/Articles/444910/ - "Object-oriented design patterns in the kernel", there C techniques to create interfaces and implement them – Dabo Feb 26 '14 at 11:54
-
I do not get what you are asking. Where is your code? In the calling process, in the device? In what context is this call made? *"The process doesn't know which device_create to call."*. How is this call made? Where should the override be? – user13500 Feb 26 '14 at 12:57
-
I agree that this question needs a lot of clarification. Try to explain the **why** of what you are doing - it will help people give you useful suggestions. How does the device drivers' code get loaded into the process that calls `device_create()`? – Peter T.B. Brett Feb 26 '14 at 13:00
-
Let me try to explain little bit more detail: – user3354961 Feb 26 '14 at 14:26
-
There is a process X which is already running in the system. It reads the device ID from the hardware. Once the process reads the device ID, It has to call device_create(device_id) to create a software context structures specific to that device. Assume that there are 2 devices with device_id 100 and 200. The drivers are totally different. Now, device100 has device100_create function and device200 has device200_create function. – user3354961 Feb 26 '14 at 14:34
-
When device_create function is invoked by the process it has to appropriately invoke the either device100_create or device200_create without using switch/case statements. The reason for not using switch/case is because everytime a new device has to be added to the process, I have to update the switch/case statement in the process. – user3354961 Feb 26 '14 at 14:35
-
@user3354961: What about function pointers? – user13500 Feb 26 '14 at 15:43
-
I understand that function pointers can solve it. But the problem here is. Lets say device_create is a function pointer. But unless I know the device Id, I cannot initialize this function pointer. Atleast, during the initialization, I need to use a switch/case statement which I am trying to avoid. – user3354961 Feb 26 '14 at 15:57
-
What is the nature of the ID's? Range / type etc. Also updated the answer a bit. – user13500 Feb 26 '14 at 16:45
2 Answers
If you use different shared objects (or dlls) to implement the function you could handle this programatically on your own. You could create a plugin like structure and use something like the Command pattern.
Not exactly simple, but can help with your problem.
Cheers.

- 1,816
- 1
- 13
- 22
OK. Understand I'm still of the mark, but leave this post for now.
You do not know the ID when process starts. When HW is attached you read the ID and want to call correct function based on the ID but without using the ID directly?
The closest I can think of as a simple solution is by using an array of function pointers:
void (*funs[3])(void) = {
&device_create100,
&device_create200,
NULL
};
But then only if you can normalize the ID to match index of the array. Say all ID's are in the range 1000-1032 that would be an 32 long function pointer array where you can use ID - 1000
.
As this is rather unlikely you could resort to a sorted list, binary tree, hash table or the like on which you do a lookup.
struct node {
int (*fun)(void);
int id;
struct *node left;
struct *node right;
}
This is of course then assuming you have a rather big list of possible ID's and a switch
is out of the question.
Old post.
What about function pointers:
int (*device_create)(int);
int device_create_init(int id)
{
switch (id) {
case 0x0a:
device_create = &device_create_100;
break;
case 0x0b:
device_create = &device_create_200;
break;
}
/* After first call, the now set device_create_xxx function will be
invoked on device_create() */
return device_create(id);
}
int main(void)
{
device_create = &device_create_init;
/* Loop */
return 0;
}

- 3,817
- 2
- 26
- 33
-
Thanks for your reply. The linked list option seems to be solving my problem. If it doesn't solve, then I will reply with the problem I face. – user3354961 Feb 26 '14 at 16:59
-
-
@user3354961: As a tree then I assume ;). Even a sorted array would give a rather quick lookup using even the simplest routines. When it comes to linked list you could also consider Unrolled linked list: http://en.wikipedia.org/wiki/Unrolled_linked_list But if this is a static list consider the LL carefully. Also consider to cache at least last ID if it is likely the same device gets de-attached and re-attached frequently in succession. For static data consider subjects like this: http://stackoverflow.com/q/18335889/3278057 – user13500 Feb 26 '14 at 17:32
-
strcut device_t arr[] = { LIST_ENTRY(100, device_create100) LIST_ENTRY(200, device_create200) }; Is there a way that I use some macro like LIST_ENTRY in my driver for 100 and driver for 200 and both of them will be part of this global array? – user3354961 Feb 26 '14 at 17:32
-
@user3354961: I'm not quite getting you again. You want some macro like `{ LIST_ENTRY(100), LIST_ENTRY(200), LIST_ENTRY(300) }` that create something like `{ &device_create_100, &device_create_200, &device_create_300 }` ? – user13500 Feb 26 '14 at 17:44
-
ex: In driver file drv100.c, I will have macro declaration LIST_ENTRY(100, dev_create100 }. In driver file drv200.c, I will have macro declaration LIST_ENTRY(200, dev_create200). Though these 2 declarations are in 2 different files, they should be added to a global structure strcut device_t arr[] in main_process.c file. Is it possible someway? – user3354961 Feb 26 '14 at 17:56
-
@user3354961: If I'm reading you correctly, no way I'm aware of. Centralize and define the array in one file and declare the array and functions in a header file which you include. Both the header and C file can be auto-generated using scripts `for x in drv*; do printf ...` Though that is perhaps not what you want or the best way. – user13500 Feb 26 '14 at 18:12