Interface / Implementation in ANSI C

I am working on a large C project and I want to organize it using interface files (.h) and implementations (.c) similar to many object-oriented languages ​​such as Objective-C or Java. I am familiar with creating static libraries in C, but I think this makes my project unnecessarily complicated. How can I implement an interface / implementation paradigm in ANSI C? I mainly use GCC for compilation, but I strive for strict adherence to ANSI C and compatibility with multiple compilers. Thanks!

+5
source share
3 answers

It sounds like you are already doing the right thing: good C code also organizes interfaces in .h files and implementations in .c files.

Example ah file:

void f(int a); 

Example ac file:

 #include "ah" static void helper(void) {...} void f(int a) {... use helper()...} 

Example main.c file:

 #include "ah" int main(void) { f(123); return 0; } 

You get modularity because helper functions are not declared in the headers, so other modules are not aware of them (you can declare them at the top of the .c file if you want). Having this modularity reduces the number of recompilations needed and reduces the number of recompilations. (Binding should be done every time, though). Note that if you do not declare helper functions in the header, you are already quite safe, however, static hidden in front of them and hides them from other modules during binding, so there is no conflict if several modules use the same helper -function-names .

If you work only with primitive types, then this is all you need to know, and you can stop reading here. However, if your module needs to work with the structure, it gets a little more complicated.

The title of the problematic example bh:

 typedef struct Obj { int data; }*Obj; Obj make(void); void work(Obj o); 

Your module wants to transfer objects in and out. The problem here is that the internal components have leaked into other modules that depend on this header. If the view is changed to float data , then everyone, using modules, should recompile. One way to fix this is to use only void* . This is how many programs do this. However, this is cumbersome because every function that takes the void* argument as an argument must distinguish it from Obj . Another way to do this:

Ch header:

 typedef struct Obj*Obj; Obj make(void); void work(Obj); 

Cc implementation:

 #include "ch" typedef struct Obj { int data; }*Obj; 

The reason for this is because Obj is a pointer (as opposed to a structure by value / copy). Other modules that depend on this module should only know that the pointer passes and exits, and not what it points to.

+5
source

You should read something about OOP with non OOL, for example http://www.cs.rit.edu/~ats/books/ooc.pdf . But by doing this, you will never have a strong OOP input.

+1
source

Please do yourself a favor and read C Interfaces and Implementations: Reusable Software Creation Techniques

Here is my archive , which contains some libraries written in C, using the interface pattern and implementation described in the book.

0
source

Source: https://habr.com/ru/post/1204056/


All Articles