Experiment: Object Oriented C? [duplicate] - c

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Can you write object oriented code in C?
Hi!
Just for the fun of it, I've been experimenting these last two days with creating a very simple, very straightforward object environment in pure C. I've been toying around with macros, dynamic linking, type-description structures and the like, and I've arrived at the following:
string_o str = new(String, "hello world");
list_o list = new(List);
List.pushf(list, str);
printf("In the list: \"%s\"\n",
String.text(List.popf(list)));
delete(list);
delete(str);
Looks and works kinda nice, but I can't figure a way to fake instance methods. I can't get past Class.function(instance), not without global macro replacements for function names, which defeats the purpose of encapsulation.
Again, this is an experiment, just for the challenge and the fun =). Can you guys help me figure out a way to do this? I don't want to use additional preprocessing, only plain C and GCC macros.
edit> forgot to say -- I don't want each instance to contain the function pointers in its structure. That would give me method syntax alright, but it would mean that a 4-byte data object would have a dozen function pointers copied over to each instance. That's kinda like cheating =P haha
Thanks in advance!

Object orientation in C is normally done with function pointers. That means a structure which contains not only the data for an instance but the functions to call as well.
It's the easiest way to do inheritance and polymorphism in C. By way of example, here's an object-orientd communications example.
It only has one method open but you can see how that differs for the TCP and HTML sub-classes. By having an initialisation routine which sets the a class-specific function, you get polymorphism.
#include <stdio.h>
// The top-level class.
typedef struct _tCommClass {
int (*open)(struct _tCommClass *self, char *fspec);
} tCommClass;
// Function for the TCP class.
static int tcpOpen (tCommClass *tcp, char *fspec) {
printf ("Opening TCP: %s\n", fspec);
return 0;
}
static int tcpInit (tCommClass *tcp) {
tcp->open = &tcpOpen;
return 0;
}
// Function for the HTML class.
static int htmlOpen (tCommClass *html, char *fspec) {
printf ("Opening HTML: %s\n", fspec);
return 0;
}
static int htmlInit (tCommClass *html) {
html->open = &htmlOpen;
return 0;
}
// Test program.
int main (void) {
int status;
tCommClass commTcp, commHtml;
// Same base class but initialized to different sub-classes.
tcpInit (&commTcp);
htmlInit (&commHtml);
// Called in exactly the same manner.
status = (commTcp.open)(&commTcp, "bigiron.box.com:5000");
status = (commHtml.open)(&commHtml, "http://www.microsoft.com");
return 0;
}
A more complete answer can be found here.
In response to your comment:
I don't want the functions contained in every single instance.
You're probably right. It's unnecessary to duplicate that information when it will be the same for every instance of a single class.
There's a simple way around that. Rather than having every instance carry its own set of function pointers, you create one structure holding them for the class, then each instance gets a pointer to that structure.
That will save quite a bit of space at the (minimal) cost of having to do two levels of indirection to call a function.

Related

Losing pointer reference to structure member ? (in c)

I am making a little project just for fun about OO in C.
The problem I am encountering is fairly odd to me. The program below is the entire thing.
When compiled and ran, all the 'methods' work properly... up until after it hits the first 'puts'. At this point, the 'methods' have lost the reference to 'self' at this point.
I'm not sure why it works up until then, but not after. It is worth noting that executing the 'constructor' again before the second 'puts' will make it work. The 'if' chains clearly show that the methods work because they properly set the new strings.
I do realize this would be fixed by simply passing the 'object's' address via parameters to the 'methods', but that's kind of the point of the post, I would like to find a neat way to do it without doing so.
#include <stdio.h>
//-----class_a--------------------------------------------------------------//
typedef struct{
char* string;
char* (*get_string)();
char* (*set_string)(char*);
} class_a;
void constructor_class_a(class_a *self, char* string){
self->string = string;
char* get_string(){
return self->string;
} self->get_string = get_string;
char* set_string(char* new_string){
return self->string = new_string;
} self->set_string = set_string;
}
//--------------------------------------------------------------------------//
int main(){
class_a object_a;
constructor_class_a(&object_a, "default string");
printf("string: %s\n", object_a.get_string());
if (object_a.get_string()=="default string"){
object_a.set_string("temporary string");
if (object_a.get_string()=="temporary string"){
object_a.set_string("final string");
if (object_a.get_string()=="final string"){
printf("string: %s\n", object_a.get_string());
}
}
}
printf("%s", object_a.get_string());
return 0;
}
I've tried doing this to no avail (including a int init member to the 'class'):
char* get_string(){
static class_a *self2 = {0};
if (!self2->inti){
*self2 = *self;
self2->init = 1;
}
return self2->string;
} self->get_string = get_string;
The problem is that you're trying to use nested functions, which are not part of the C language but a GCC extension, but using them incorrectly. Their lifetimes end at the end of the block they're nested in, and any use of a function pointer to them after their lifetime ends has undefined behavior.
Even if this did work, it would be an awful idea, since the ability to have pointers to nested functions necessarily depends on having an executable stack, which is deprecated because it makes most kinds of vulnerabilities trivial to exploit. This is among the many reasons that clang and other compilers refuse to copy this GCC feature and why it's essentially dead.

I don't understand how pointers work in this code?

I don't understand this part of the code below. I mean alloc_MY_CAR() returns some array and how does & work so that newTab->pFunFree = &free_MY_CAR sees this array which newTab->pDat returns?
I don't understand pointers well. I only know that & store address of variable and * is a pointer or a value of the variable.
Could anyone guide me on how to use it properly and how does it work? I'm a beginner, so don't be so hard on me.
Thanks in advance!
#pragma once
struct MY_CAR {
char *model;
int year;
};
void print_MY_CAR(void* pdata);
void free_MY_CAR(void *pdata);
MY_CAR* alloc_MY_CAR();
switch (typ) {
case 0:
newTab->pDat = alloc_MY_CAR();
newTab->pFunFree = &free_MY_CAR;
newTab->pFunPrint = &print_MY_CAR;
break;
}
MY_CAR* alloc_MY_CAR() {
MY_CAR* tab = (MY_CAR*)calloc(1, sizeof(MY_CAR));
if (!tab) {
exit(0);
}
else {
char model[125];
printf("Podaj model: ");
scanf("%s", model);
tab->model = (char*)calloc(strlen(model) + 1, sizeof(char));
strcpy(tab->model, model);
printf("Podaj rok: ");
scanf_s("%d", &tab->year);
}
return tab;
}
void free_MY_CAR(void *pdata) {
MY_CAR* car = (MY_CAR*)pdata;
if (!car || !car->model) return ;
free(car->model);
free(car);
}
Notice that the function free_MY_CAR has an argument of type void*,
a pointer to a "void" type
(which is a C idiom for a pointer to something without telling the type of the thing pointed to),
and the first thing it does is to reinterpret that pointer as a pointer to a MY_CAR.
So the function is probably intended to be called like this:
newTab->pFunFree(newTab->pDat);
That is, the way the functions "know" what pointer was returned by
alloc_MY_CAR() and stored in newTab->pDat
is that the programmer explicitly tells the functions what pointer
is stored in newTab->pDat.
The advantage of doing such things is that it allows some code to do some operation on a data structure without necessarily having to know what kind of data structure it will actually operate on when the program actually runs.
In the call to pFunFree above, newTab could have been initialized by the case 0 code shown in the question, but there could be another case
that initializes it with alloc_MY_JOB(), &free_MY_JOB, and &print_MY_JOB,
where the MY_JOB functions allocate/free/print a data structure that is quite different from the data structure used by
alloc_MY_CAR(), &free_MY_CAR, and &print_MY_CAR.
Then if you call
newTab->pFunPrint(newTab->pDat);
we might not be able to predict when we write the code whether it will print the contents of a data structure created by
alloc_MY_CAR() or by alloc_MY_JOB();
but we can predict that it will print the detailed information it has
about your car, or your job, or whatever was read from the data file and stored in newTab.
The property that we can make a function call that uses a data structure in a way appropriate to that data structure, without having to know when we write the code what the type of data structure will be, is called
polymorphism.
This is a cumbersome idiom and there are lots of ways to get it wrong.
One of the selling points of C++ is to enable people to write polymorphic objects more easily than this.

Is it possible to store function arguments in a pointer to function?

Just out of curiosity, I'm trying to understand how pointers to functions work in C.
In order to associate a function to a typedef, I've declared a pointer in it, and then I've stored the address of the desired function in there.
This is what I was able to achieve:
typedef struct
{
void (*get)(char*, int);
char string[10];
} password;
int main()
{
password userPassword;
userPassword.get = &hiddenStringInput;
userPassword.get(userPassword.string, 10);
return EXIT_SUCCESS;
}
While this does actually work perfectly, I'd like for "userPassword.get" to be a shortcut that when used calls the hiddenStringInput function and fills in the requested arguments (in this case, an array of characters and a integer).
Basically, since I'm always going to use userPassword.get in association with the arguments "userPassword.string" and "10", I'm trying to figure out a way to somehow store those parameters in the pointer that points to the hiddenString function. Is it even possible?
The way I see this usually done is by providing a "dispatch" function:
void get(password * pw) {
pw->get(pw->string, 10);
}
Then, after setting userPassword.get to your function, you call just:
get(userPassword);
Obviously this adds some boilerplate code when done for multiple functions. Allows to implement further funny "class like" things, though.
You can do this in Clang using the "Blocks" language extension. As commented, there have been attempts to standardize this (and it's not been received with hostility or anything), but they're moving slowly.
Translated to use Blocks, your example could look like this:
#include <stdlib.h>
#include <Block.h>
typedef void (^GetPw)(int); // notice how Block pointer types are used
typedef void (*GetPw_Impl)(char*, int); // the same way as function pointer types
typedef struct
{
GetPw get;
char string[10];
} password;
extern void hiddenStringInput(char*, int);
extern void setPw(char dst [static 10], char * src);
GetPw bindPw (GetPw_Impl get_impl, char * pw)
{
return Block_copy (^ (int key) {
get_impl (pw, key);
});
}
int main()
{
password userPassword;
setPw(userPassword.string, "secret");
userPassword.get = bindPw(hiddenStringInput, userPassword.string);
userPassword.get(10);
return EXIT_SUCCESS;
}
There are some subtleties to the way arrays are captured that might confuse this case; the example captures the password by normal pointer and assumes userPassword is responsible for ownership of it, separately from the block.
Since a block captures values, it needs to provide and release dynamic storage for the copies of the captured values that will be created when the block itself is copied out of the scope where it was created; this is done with the Block_copy and Block_release functions.
Block types (syntactically function pointers, but using ^ instead of *) are just pointers - there's no way to access the underlying block entity, just like basic C functions.
This is the Clang API - standardization would change this slightly, and will probably reduce the requirement for dynamic memory allocation to copy a block around (but the Clang API reflects how these are currently most commonly used).
So, I've just realized that I can write functions directly inside of structs
typedef struct
{
char string[10];
void get(void)
{
hiddenStringInput(string, 10);
return;
}
void set(const char* newPassword)
{
strcpy(string, newPassword);
return;
}
void show(void)
{
printf("%s", string);
return;
}
} password;
Now I can just call userPassword.get(), userPassword.show() and userPassword.set("something"), and what happens is exactly what the label says. Are there any reasons I shouldn't do this? This looks like it could come pretty handy.
EDIT: So this is only possible in C++. I didn't realize I'm using a C++ compiler and by attempting to do random stuff I came up with this solution. So this isn't really what I was looking for.

Long arguments list, how to process them nicely, now I have many if/else statements ... pure C

I have an application where the arguments list cant be reeeealy long. I can run my app like this:
./app -operations a b c d e f g h i j ...
And so on. My a,b,c ... are algorithms which I would like to run (functions defined in my code). To be able to execute them, I have something like this:
if(a)
funA();
if(b)
funB();
if(c)
funC();
...
It does not look nice, does it? I must say, there's much more calls than just 26, since my application grows and grows, my arguments list grows too. I'm looking for a fancy way to make it simpler/prettier. Is it possible, anyone with an idea?
I dont want to use C++ nor external libraries for making it simpler. Can it be done in pure C?
Here is a very simplified possible option:
#include <stdio.h>
// create a common structure to hold all your
// function parameters;
typedef struct Parameters
{
int p1;
int p2;
} Param_Type;
// sample function 1
void func1( Param_Type *params ) {
printf("hi from func1: %d\n", params->p1 );
}
// sample function 2
void func2( Param_Type *params ) {
printf("hi from func2: %d\n", params->p2 );
}
int main() {
Parameters p;
// parse the command line and populate the parameters struct;
p.p1 = 1;
p.p2 = 1;
//create a lookup table with pointers to each function.
void (*F_A[2])(Param_Type *) = {func1, func2};
//You will still need some function, that given a set of arguments, can
// derive and return an index into the array that maps to the correct
/ function.
int func_idx = your_mapping_function(...) // todo
// dispatch the correct function call.
(*F_A[func_idx])(&p);
return 0;
}
You can use use getopt() to read the command line parameters.
And I don't see any optimization in the way you are deciding what action to take depending upon the arguments. I'd say it's just a bad design of doing things. You could try changing your approach.
You could use enums and function pointers to define handlers for every different set of arguments.
Something in the lines of:
typedef enum {
ARG_A,
ARG_B,
ARG_C,
// etcetera
MAX_ARGS
} CmdArgId;
bool cmdArgStates[MAX_ARGS];
typedef void (*CmdHandler_f)();
CmdHandler_f cmdHandlers[MAX_ARGS] = {
// TODO: set function pointers
};
int main()
{
// set cmdArgStates[] indexes to true or false,
// according to the program command line.
ParserCmdArgs();
for (int i = 0; i < MAX_ARGS; ++i)
{
if (cmdArgStates[i] == true)
{
cmdHandlers[i]();
}
}
}
If you need the handler functions to have different numbers of arguments, you can define a common function with a fixed number of args and just ignore them when they are not needed. I.e.: typedef void (*CmdHandler_f)(); could also de something like typedef void (*CmdHandler_f)(int, int, int);
One idea would be to create a structure that can be used to abstract each command line option. Here is a possible method you could use to implement that idea :
Create a structure that can represent each function you need to
support, and have it hold a pointer to the function and a string for the search key.
Create an array of this structure and initialize the members accordingly
Use an algorithm, such as a binary search, to find the key in the structure array when looping through the command line arguments.
Once you have the structure from the key, you can then call the function which will handle the behavior desired in the option.
It's possible this won't apply to your situation, but this really is an implementation specific problem. If you want a more specific solution, you should probably post more details about your functions and the implementation behind them.

C Instructions explanation

can any one explain the following instructions:
int *c[10];
char *(**n)(void);
float *(**r(void))[6];
short *(**v(void))(int);
long *(*(*(*z)(void))[7])(void);
http://www.cdecl.org/ will explain all these statements. C Right-Left rule explains how to read C declerations pretty well. There are plenty of other resources available, notably in this question.
Since this is your homework you won't learn this by me telling you everything ;) But, one hint. You can create and pass pointers to functions in C, not just variables.
Function arguments of all but the first example are prototypes for function pointers.
Say we have a library for testing colours, we might want to allow the users of our library to provide custom ways of getting the name of the colour. We might define a struct for users to pass in containing callbacks we can call.
struct colour_tester {
char *(*colour_callback)(void);
}
// test the user's function if given
void run_test(struct colour_tester *foo ){
// use the callback function if set
if ( foo->colour_callback != NULL ){
char * colour = (*foo->colour_callback)();
printf( "colour callback returned %s\n", colour );
}
}
Users of the library would then be free to define implementations of these callback functions and pass them to us as a function pointer.
#include <colour_tester.h>
char * get_shape_colour(){
return "red";
}
int main ( int argc, char** argv ) {
// create a colour tester and tell it how to get the colour
struct colour_tester foo;
foo.colour_callback = &get_shape_colour;
run_test( &foo );
}
I've leave you to work out what is going on with the ones with extra numbers of *s.

Resources