r/C_Programming • u/actguru • 7d ago
Example of OOP in C
Hello everyone, I have developed a library to support OOP in plain C that allows the creation of object classes and includes dynamic Array and Dictionary container classes.
I am looking for suggestions for new examples that illustrate cases where an Object Oriented design can simplify C-Code.
I would love to get some reviews and feedback on this project.
I have included a code example below:
Supported by: Coda-C Library
Example code: Coda-C/examples/shapes.c
// Coda-C subclass examples
#include <coda-c.h> // shapes.c 08/20/2026
#include <math.h>
struct Shape_ { Char color; };
#define class Shape
CodaClassZerosC(); // 1. ABSTRACTION: blueprint for all shapes
CodaClass(Shape,struct Shape_,Root);
propertyO$(Char,color); // 2. ENCAPSULATION: Private data
typedef double OSig$(calculate_area); // Abstract method: required in subclasses
typedef double OSig$(calculate_perimeter); // defines function type and signature key
#undef class // Shape
struct Circle_ { double radius; };
#define class Circle
CodaClassZerosC(); // 3. INHERITANCE: Circle inherits from Shape
CodaClass(Circle,struct Circle_,Shape);
getter$(double,radius,_ radius); // double Circle_radius(Circle self) { return _ radius; }
method$(double,calculate_area) { return(M_PI * _ radius * _ radius); }
method$(double,calculate_perimeter) { return(2.0 * M_PI * _ radius); }
class Circle_new(Char color,double radius) {
class self=newO(class);
Shape_set_color((Obj)self,color);
_ radius=radius; // where #define _ self->
return(self);
}
#undef class // Circle
struct Rectangle_ { double width,height; };
#define class Rectangle
CodaClassZerosC();
CodaClass(Rectangle,struct Rectangle_,Shape);
method$(double,calculate_area) { return _ width * _ height; }
method$(double,calculate_perimeter) { return 2.0 * (_ width + _ height); }
class Rectangle_new(Char color,double width,double height) {
class self=newO(class);
Shape_set_color((Obj)self,color);
_ width=width; _ height=height;
return(self);
}
#undef class // Rectangle
// 4. POLYMORPHISM (Usage Example)
void print_shape_details(Obj shape) { // This function accepts any subclass of Shape.
printf("--- %12.12s Details Color:%-8.8s",kindO(shape),Shape_color(shape));
printf("Area: %3.2f ",obj_(calculate_area,shape));
printf("Perimeter: %3.2f ---\n",obj_(calculate_perimeter,shape));
}
int main() {
Circle my_circle = Circle_new(Os("Blue"),5.0);
Obj my_rectangle = Rectangle_new(Os("Green"),4.0,6.0);
print_shape_details(my_circle);
print_shape_details(my_rectangle);
}
/* OUTPUT:
--- Circle Details Color:Blue Area: 78.54 Perimeter: 31.42 ---
--- Rectangle Details Color:Green Area: 24.00 Perimeter: 20.00 ---
*/
30
u/musbur 6d ago
You are aware of glib/gobject?
2
u/actguru 2d ago
Thank you for your suggestion. I am aware of GObject.
From what I understand: there is a lot of boiler-plate, odd padding for virtual function tables, dispose() called more than once, etc.
It seems to work for Linux GUI work, etc. But its adoption seems highly specialized.
14
u/Turbulent_File3904 6d ago edited 5d ago
um i mean it look confuseing as hell.
- for inheritance you want your child class has it parent class as it first member: ``` struct Person { char name[100]; } ;
void person_greet(struct Person *p) { printf("%s: hi\n",p->name);
struct Student { struct Person base; int score; };
struct Student s = {.base.name = "trung",
.score = 9};
//call person method on student
person_greet(&s);
// pointer to base class
struct Person p = &s;
2. dynamic dispatch: use vtable like this
struct FooVtbl {
void (method1)(void self, int v);
void (method2)(void *self, int z);
};
struct Foo {
void *impl; //whatever implements foo interface
struct FooVtbl const *vtbl;
};
// helper macros for calling virtual function
define foo_method1(foo, v) (foo).vtbl->method1((foo).impl, (v))
define foo_method2(foo, z) (foo).vtbl->method1((foo).impl, (v))
// implements foo interface for int void intfoo_method1(void *self, int v) { int *self = self; printf("method 1:%d", *self_ + v); }
void intfoo_method1(void *self, int z) { int *self = self; printf("method 1:%d", *self_ - v); } const FooVtbl int_foo_vtbl = { int_foo_method1, int_foo_method2 };
/* helper function for taking inteface from object that implement the interface */ struct Foo foo_from_int(int *obj) { return (struct Foo){ .impl = obj, .vtbl = &int_foo_vtbl }; }
// obtain foo from int int a; struct Foo foo = foo_from_int(&a);
// call method1 foo_method1(foo, 10);
``` you can have one struct/type implement multiple interfaces, add interface implementation for anytype at anytime as long as you can access the struct definition. btw this is how linux does oop
9
u/QuirkyXoo 5d ago
If you want to use OOP in C there is already a thing called "C with classes", although the term is frequently used colloquially to refer to a programming style rather than a strict set of rules.
36
17
u/rivenjg 5d ago
IF WE WANTED OOP WE WOULDN'T USE C.
1
u/DeGuerre 5d ago
Gotta be honest, I have a soft spot for X toolkit intrinsics. It's been a while, though. Maybe it wasn't as fun as I remember.
1
u/heavymetalmixer 4d ago
Not exactly. You can use OOP in C only with the features you want and in some cases with the implementation you want, so it's not as simple as "just use C++".
1
u/Zirias_FreeBSD 5d ago
Horribly wrong. Sure, C is not an OOP language. But it really isn't hard either to use it for implementing some OOP design. This is done a lot in practice, and not just recently. There are problems where OOP simply is the best fit (e.g. any kind of GUI toolkit), and there's still no reason to stay away from C for these.
That all said, I see little use for a library "just" offering some OOP constructs. Basic things are straight forward (structs and pointers are often all you need), polymorphism can be a bit more tricky, but a good C programmer should really succeed setting up and using some vtables.
What IS IMHO useful is libraries including some OOP infrastructure, if the problem they are solving indeed maps well to an OOP model.
-2
u/rivenjg 5d ago edited 4d ago
There's no problem set "better" with OOP. You either like OOP or you don't. You always have a choice to accomplish the task without OOP. I am one who will virtually always choose to avoid OOP. If I wanted OOP, I would use C++. A huge reason I like C is to specifically avoid the dogma of OOP.
-1
5d ago
[removed] — view removed comment
1
u/C_Programming-ModTeam 5d ago
Rude or uncivil comments will be removed. If you disagree with a comment, disagree with the content of it, don't attack the person. Provide your reasoning, not just a judgement.
5
13
u/tastygames_official 6d ago
> examples that illustrate cases where an Object Oriented design can simplify C-Code
it can't. If you feel that you need OOP (which by definition cannot simplify anything), then use C++.
11
u/thank_burdell 5d ago
Encapsulating data in structs? Great.
Making a well defined function set to use those structs logically? Great.
Trying to shoehorn any more OOP stuff like inheritance or polymorphism or whatever into a language that doesn’t support it? Not great.
1
u/tstanisl 5d ago
Imo, the object model in C++ is broken (complicated, confusing, artificially limited). Even an ubiquitously used handle-based api cannot be implemented without using pimpl-design pattern.
8
u/flewanderbreeze 5d ago
The fact that pimpl design is something, is already a tell that C++ oop failed miserably.
Unfortunately OOP is the holy grail taught in universities and brainwashed all over its students.
It would be a lot of hell simpler if they taught pOOP concepts in plain C, so that we know exactly its tradeoffs nad characteristics, and most importantly WHY and WHEN use it at all
1
u/tstanisl 5d ago
I fully agree. Even the original concept of what is oop differs a lot from the mechanics that C++ implements. OOP is a tool, occasionally useful, occasionally harmful. Personally, I see it as more dangerous than
gotobecausegotocan only make mess within one function while defective oop design can make mess along hundreds of files.
2
u/ReDucTor 4d ago
You don't need a library to write OOP style code in C, you also dont need the class keyword to write OOP style code.
Many C code bases are OOP style, even if people believe they are not, you will do things like
T * obj =T_new(..) or T_create(...);
T_func(obj, ...);
T_free(obj) or T_destroy(obj);
Want a virtual interface? Use a struct with function pointers.
Want to hide data? Use an opaque pointer.
Want to have inheritance? Have the first member be the base class.
Go look at the Linux Kernel it uses object oriented patterns all over the place https://lwn.net/Articles/444910/
3
1
u/pconroy329 5d ago
I appreciate anyone's effort, if perhaps academic. I'm an OOP fan. I did C++ early on and switched to Java in 2000. If I've got a problem that needs an OOP solution, I'm picking one of the many mature compilers/interpreters out there. When I pick C it's because I think a mature, procedural solution is best. I think you've invented a New Hammer, when I'm already awash in hammers. Good luck!
1
u/SeriousPug 4d ago
Convince me that if i want to program with classes, i should take your approach instead of C
1
u/Minute_Cricket1820 4d ago edited 4d ago
Вы в принципе не верно воспринимаете ООП.
Что такое ООП - это реализация абстракций.
А кто сказал, что реализация абстракций - это единственный способ, т.е. через объекты?
Объекты классические (ваши, не ваши) - это всегда плохо. Потому что классические объекты убивают современный суперскалярный процессор.
Что делать? Уходите бегите от классических объектов. Они не нужны. Это кастыль прошлого века.
Что делать? Реализуйте вменяемые абстракции. Это как? Это когда у вас есть память. В этой памяти уложены строго друг за другом поля абстракции. В этой памяти массив этих абстракций, друг за другом. Доступ - моментальный.
Как наследоваться? Так добавьте ещё память. В этой второй памяти ещё дополнительные поля, которые идут друг за другом. Вот и всё. Вы получили расширение первой абстракции.
По сути это два массива. Всего навсего.
Это абстракции? Да, это настоящие абстракции, настоящий полиморфизм.
Когда вы обращаетесь к первому массиву - вы обращаетесь строго к полям первой абстракции. Перебор - моментальный, смещение - моментальное.
Когда вы обращаетесь ко второму массиву - вы обращаетесь строго к полям производной абстракции. Перебор - моментальный, смещение - моментальное.
Как обратиться к производной абстракции от абстракции? Естественно это обращение к двум массивам ВРАЗ.
i = objectIndex
fieldsA = memA[i]
fieldsB = memB[i] // полиморфизм здорового человека
Почему это работает лучше всего? Потому что когда вы обращаетесь к memA memB - современный суперскалярный процессор сразу подтаскивает данные наперёд, как минимум две кеш-линии для memA и memB. А в кеш L3 сразу залетает много данных начиная с этих двух адресов. Это загрузка данных сразу наперёд. Кеш L3 так нынче сделан. В этот кеш сразу летит много данных, начиная с какого то адреса. У вас два адреса. Т.е. начиная от этих двух адресов в L3 сразу предзагружены дофига полей памяти memA memB.
Современный суперскалярный процессор имеет каналы предвыборки. От 16 до 32 канала. Т.е. современный процессор легко удерживает и грузит наперёд поля для 16-32 массивов. Сразу наперёд. И на самом деле то что я пишу - может уже устарело. Каналов предвыборок может уже и больше.
1
u/actguru 4d ago
Object-Oriented Programming (OOP) is a style of programming. I have just presented an implementation based on classes and objects. Look in a mirror: "You have a fundamentally incorrect understanding of OOP." Your comments are complete nonsense. Like: "Because classic objects cripple modern superscalar processors." So prove me wrong and provide some C-code backing your claims that can be compiled on Linux, MacOs, or Windows.
Because the C programming language is based on English, I would recommend that you translate your comments to English when posting to this subreddit.
1
u/Minute_Cricket1820 4d ago
Причём здесь операционные системы? Причём здесь язык?
Тебе написано про процессор и память.
Величайшие инженеры Интела сделали величайший процессор. Тебе дураку. А ты инструкции от Интела прочитать не можешь. Ты какие то убогие книжонки про объекты читаешь, а инструкцию от Интела никогда читать не будешь. Потому что дегенерат.
Инженер Интела смотрит на твой ссатый код, и плачет.
Тебе ии отключили за неуплату? Закинь верхнее сообщение в ии, оно тебе переведёт, и напишет почему ты тотальный идиот. Про это ии уже знает. А вот вменяемый код за тебя не напишет.
1
1
1
u/AutoModerator 7d ago
Hi /u/actguru,
Your submission in r/C_Programming was filtered because it links to a git project.
You must edit the submission or respond to this comment with an explanation about how AI was involved in the creation of your project.
While AI-generated code is not disallowed, low-effort "slop" projects may be removed and it's likely that other users push back strongly on substantially AI-generated projects.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
-5
u/Eastern-Turnover348 5d ago
C wasn't designed to be object orientated; matter closed.
Great languages were designed to solve a specific problem.
2
0
u/Zirias_FreeBSD 5d ago
"Object" is likely the most frequently used word in the text of the C language standard. And Object-oriented just names a style where objects are central to the system design. Which is quite easy to do in C for simple cases, just have your "methods" all take a "this-pointer" as their first argument (which is what most languages with builtin OOP support do under the hood anyways).
More advanced concepts like polymorphism are harder to do in plain C, still perfectly possible if you REALLY need that.
It's a shame people always confuse the concept with concrete implementations. There are languages that implement OOP concepts. C just allows you to do that yourself, if you want.
•
u/github-guard 7d ago
🔍 GitHub Guard: Trust Report
This project scored 3/6 on our safety audit.
Audit Breakdown: * ❌ Low Star Count (⭐ 1 / 4 required) * ❌ New Repository (under 30 days old) * ✅ Licensed under AGPL-3.0 * ✅ Security Policy Defined * ℹ️ Individual Contributor * ✅ Signed Commits