Purpose of simple wrapper function in C - c

In ex26 of 'Learn C the Hard Way' in the db.c file Zed defines two functions:
static FILE *DB_open(const char *path, const char *mode) {
return fopen(path, mode);
}
static void DB_close(FILE *db) {
fclose(db);
}
I have a hard time understanding the purpose/need for wrapping these very simple calls to fopen and fclose. What are, if any, the advantages of wrapping very simple functions, like the example given above?

In this particular case a wrapper is used to hide the detail that DB_open, DB_read or DB_close all map to file operations.
This approach implements an abstraction layer through which all database related functions are to be accessed. Also this provides modularity, which may later allow adding more methods to open/read/close databases.
As explained by Michael Kohne in the comments, this wrapper should be improved to totally hide e.g. the type of FILE *db, by substituting it with struct DB_context *context;.

Wrappers, (or stubs), are often used to guard the other areas of your code from changes in the functions being wrapped.
It's also a useful way of interacting with dynamic libraries and shared objects.

Basically a wrapper means , hiding all the related information of underlying routines by using our/a_developer's custom function.
You've mentioned that file name itself is db.c , so maybe the developer wants all the critical & important function which are used/declared must have starting of DB_

Related

how do we configure the parameter inside lib from app layer

I have very basic question on C language.
Situation
There is a library named "lib".
The library has a member of array named "tmp".
int tmp[ARRAY_SIZE];
currently ARRAY_SIZE is defined inside lib.
Even though it is treated as library, we compile the library and app at the same time.(we are in non-OS environment)
We can use static memory allocation only (no dynamic allocation)
because of embedded system environment (where using heap is likely to be avoided)
Since this is the library, we would like to be independent from application layer as much as possible
Goal
We would like to make ARRAY_SIZE configurable from app layer.
Question
In this situation, how do you modify this library to achieve the goal ?
Here is my ideas.
define "tmp" at application layer,
then pass it as a pointer to the library at initialization time.
define the MACRO at compile time, like -DARRAY_SIZE=10
create header file like lib_setting.h at app layer, the include it from lib.h
Any other ideas ?
If you were me, how do you implement ?
John
Any other ideas ?
No, these are exactly the solutions to such problems.
If you were me, how do you implement ?
It strongly depends on what the library is for and what exactly ARRAY_SIZE represent. For sure I would not call it ARRAY_SIZE, as the name ARRAY_SIZE() is used in linux kernel I'm familiar with, so I would definitely pick a LIB_unique LIB_name LIB_with LIB_prefix.
If it's a library meant for normal regular use, I would definitely go with option 1 whenever possible.
struct lib_s {
char *buf;
size_t bufsize;
};
static int lib_init(struct lib_s *t, char *buf, size_t bufsize) {
assert(t);
assert(buf);
assert(bufsize);
t->buf = buf;
t->bufsize = bufsize;
return 0;
}
int lib_dosomething(struct lib_s *t);
// client
int main() {
char mysuperbuffer[2046];
struct lib_s lib;
lib_init(&lib, mysuperbuffer, sizeof(mysuperbuffer));
}
Such design is easy to unit test. Is re-entrant. The lifetime is manageable. It's not spaghetti code. It's easy to understand and track variables. If user changes his mind, the user can choose if he wants to malloc or not. It's easy to refactor and extend later. Such design is found in many functions - fopenbuf() comes to my head from POSIX.
If it's a highly specialized library that profiling shows it's the bootleneck and the library needs super speed of execution and you don't want to waste sizeof(char*) + sizeof(size_t) bytes of memory and a lot more for indirection, I would go with option 3. Many projects use it - autotools generates a main config.h file, mbedtls.h has mbedtls/config.h file, etc.
If the configuration option is very constant and rarely changes, for example changes only when switching platforms, on windows it's something on linux it's something else, then maybe I would consider option 2, but I believe I would prefer to go option 3 anyway. Using a file is easier to track in control version systems and build systems will recompile only files that depend on a header that sees that definition. A macro passed on command line is harder to track which files use it (ie. spaghetti code) and usually when you change it's value, you have to recompile the whole project.

Is There a Standard Method for Making Abstract Data Types in ansi C?

I recently transferred into a different school & cs program. The language used is C as compared to java which was taught at my previous school. One of my main issues which may be the result of not writing enough C code is that I'm having trouble finding a standard for making Abstract Data Types.
From what I've seen, there are tons of ways these are implemented and the lack of a visible standard is making me worried I missed something while self learning C. I've seen implementations that hide the init variable from the user such as
#define createVector(vec) Vector vec; void init_vector(&vec)
and another version which is what I would be more used to in which a handle is used to hold the returned pointer to struct from the createVector() function. The issue is I can't find any detailed description on handles online or in my course 2 book. The course 2 book only shows the interface and methods but not how they are grouped together in a way that hides the implementation from the user. I wanted to know if there was a "correct" way/standard for ADTs? The book in question is Robert Sedgewick "Algorithms in C - Third Edition".
Abstract Data Types
Split your sources.
The header (.h files) contains the abstract declarations like the datatypes (structs, functions, enums, constants, etc)
The actual implementation is done in the .c files.
When using such a (lets call it) module you only include the header in your source.
The implementiation you use is decided at linking time. You may decide to use different .c files for implementation or a static library (or even a dynamic library).
If you want to hide the data you use opaque structures.
Why is this standard? Ever heard of the FILE type? This is the opaque type used for IO in c's standardlibrary. You only include the header stdio.h and leave the implementation to the compiler. The header on the other hand or at least the symbols that it defines are well documented (and part of the c standard).
Abstract Classes
Java has the concept of an abstract class. Well, it also has the concept of a class in general. C does not. This is more a personal opinion but don't waste time on emulating language features that the language does not offer.
For none abstract methods use functions which take a pointer to a (probably opaque) struct containing all the data needed as first parameter, like fprintf(FILE*,const char*,...).
For abstract methods you will need function pointers.
Use these function pointers (or maybe a struct of function pointers) like a strategy. You may define a method for registering such a strategyand delegate the normal functions to them. Take for example the atexit function, which globally (you may call it a singleton) adds a exiting-strategy.
The XY Problem
I'm having trouble finding a standard for making Abstract Data Types
Read about this and apply it to your question.
Instead of trying to force your solution to work rethink if the attempted solution is applicable to the problem. Try to get comfy with the techniques described above. This may need a bit of practice but then you can model your solution in a more c-styled way.
I just wanted to post this as I figured out the answer that would be more specific to my case however I understand that this probably doesn't apply to everyone. The thing I was looking for was the idea of "First Class ADTs" which use a handle to contain a pointer to the actual object that was created from a .c implementation file that would be hidden from the user.
For ADT using C, this approach is the standard as far as I know. You will have a header (.h) file and one or more implementation (.c) files. The header file might look something like:
typedef struct * Doodad;
Doodad * doodadInit(int);
void doodadDestroy(Doodad *);
int doodadGetData(Doodad *);
void doodadSetData(int);
For your implementation file(s) you might have:
typedef struct iDoodad {
int data;
} Doodad;
Doodad * doodadInit(int data) {
...
}
...

Exposing functions instead of constants for describing library features

I've noticed that in a lot of library, version informations, as well as informations on the availability of special features that may differ or be absent depending on the build, are made accessible to client applications not by a constant, but by a function call returning a constant, e.g.:
const char *libversion(void) {
return "0.2";
}
bool support_ssl(void) {
return LIB_SSL_ENABLED; /* whatever */
}
instead of simply:
const char *libversion = "0.2";
bool support_ssl = LIB_SSL_ENABLED;
Is there a practical reason for doing this, or is it only some kind of convention?
Is there a practical reason for doing this, or is it only some kind of convention?
I'd say both…
A practical reason I see for this, is that when you distribute your library, your users install a compiled version of it as a shared object, and access its data using the header. If the constant is accessible through a function, its prototype is declared in the header, but the value is defined in the compilation unit, linked in the shared object file. Edit: I'm not saying it's not possible, but a good reason for doing so is to keep the possibility to keep the API stable, while switching from a constant value to a calculated value for a given function, cf reason #3.
Another practical reason I can see is that you could access that API using some sort of "middleware", like corba, that enables you to access functions, but not constants (please be kind with me if I'm wrong about that particular point, I haven't done any CORBA in 10 years…).
And in the end, it's somehow good OOP convention, the header file being a pure functional interface, and all the members being encapsulated enabling a full decoupling of the inner workings of the library and the exposed behaviour.

Design for C program [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
Is it good/correct way to do like this for a robust C program
//File1 => Module1.h
static int Fun(int);
struct{
int (*pFn)(int)
}Interface;
//File2 => Module1.c
static int Fun(int){
//do something
}
Interface* Init(void)
{
Interface *pInterface = malloc(sizeof(Interface));
pInterface->pFn = Fun;
return pInterface;
}
//File 3 => Module2.c
#include"Module1.h"
main()
{
Interface *pInterface1 = Init();
pInterface1->pFn(5);
}
My intention is to make each module expose an interface...
Questions:
Is it good to write a C code like above to expose an interface... ??
What better ways are available for exposing interface??
Are there any references for design principles for C programming (not C++) ??
This is more idiomatic for a dynamically loaded module. (Or something along these lines.)
Usually an interface between two source files is defined using extern functions and objects which are accessed directly. You would need to make a case for doing anything more sophisticated.
If you use it for solving simple task, it may only increases code
base and complexity. But certain places it could be useful.
For example: If you want to implement STRATEGY-pattern in C, that is
one way to do it.
You may hide content of the Interface struct from users by using FIRST-CLASS ADT pattern. Or you can combine above patterns.
My short answer is no.
Ignoring the comments that point out that the static function should not be declared in the .h file (that is the part you want to hide -- it is static after all), here are some things to keep in mind.
It seems like you are trying to use the interface in order to de-couple the implementation from consumers of the module; a noble goal. This can allow increased flexibility as the implementation can change in the .c file without breaking calling code. However, think about the interface you have defined.
Any code using this module should be guaranteed to be able to get an Interface instance, via Init (although this needs to be included in your .h file). That Interface instance will point to the functions to use. One such function has the signature
int Fun(int);
So what have you hidden? Of course, you can change the function they are calling, but you still have to provide a function with that signature.
Alternatively, you could just define the .h as:
int Fun(int);
And then in the .c file, something like:
static int StaticFun(int i)
{
// something
}
int Fun(int i)
{
StaticFun(i);
}
You could make Fun call a different function based on some internal state it manages, or a config file, whatever you want. Why is this better? Besides being simpler, it is a static call; the compiler can inline the call to StaticFun, or even the function StaticFun completely, for example. Calls through function pointers usually incur a noticeable performance hit.
Now, there may be a case for an "Interface" object, such as you have defined. But I would be inclined to suggest that there isn't one in your case, not without modification.
Suppose your Init function changed to:
Interface* Init(some state info);
Now the Interface object you pass back can change depending on the state or configuration passed in, which allows your module to dynamically map functions. Basically, my opinion is that if you are actually calling a static function underneath, then you are working much harder than needed, and preventing compiler optimizations.
As a note, if you are going to go the Interface route (I'm working on a project with something similar right now) then may I suggest a modification? Something like...
.h file:
const Interface* Init(some state);
.c file:
static int FunTyp1(int);
static int FunTyp2(int);
static const Interface typ1 = { &FunTyp1 };
static const Interface typ2 = { &FunTyp2 };
const Interface* Init(some state)
{
if (some state == type1)
return &typ1;
else if (some state == type2)
return &typ2;
}
Advantages:
You probably don't want consuming code to modify the interface? At least, I can't think of a good reason.
Defining it statically avoids the unnecessary heap allocation and the memory leaks when consumers repeatedly request Interface objects and forget to free them (or don't know they should -- who owns this object?).
You can share a single (static) instance of the Interface object for all the consuming code in the process without worrying that someone changes it.
Note that by having several statically initialized instances, you can define a different "Interface" object for each function mapping you want to support.

Reentrancy or not with this netbsd code

I am studying on "reading code" by reading pieces of NetBSD source code.
(for whoever is interested, it's < Code Reading: The Open Source Perspective > I'm reading)
And I found this function:
/* convert IP address to a string, but not into a single buffer
*/
char *
naddr_ntoa(naddr a)
{
#define NUM_BUFS 4
static int bufno;
static struct {
char str[16]; /* xxx.xxx.xxx.xxx\0 */
} bufs[NUM_BUFS];
char *s;
struct in_addr addr;
addr.s_addr = a;
strlcpy(bufs[bufno].str, inet_ntoa(addr), sizeof(bufs[bufno].str));
s = bufs[bufno].str;
bufno = (bufno+1) % NUM_BUFS;
return s;
#undef NUM_BUFS
}
It introduces 4 different temporary buffers to wrap inet_ntoa function since inet_ntoa is not re-entrant.
But seems to me this naddr_ntoa function is also not re-entrant:
the static bufno variable can be manipulated by other so the temporary buffers do not seem work as expected here.
So is it a potential bug?
Yes, this is a potential bug. If you want a similar function that most likely reentrant you could use e.g. inet_ntop (which incidentally handles IPv6 as well).
That code comes from src/sbin/routed/trace.c and it is not a general library routine, but just a custom hack used only in the routed program. The addrname() function in the same file makes use of the same trick, for the same reason. It's not even NetBSD code per se, but rather it comes from SGI originally, and is maintained by Vernon Schryver (see The Routed Page).
It's just a quick hack to allow use of multiple calls within the same expression, such as where the results are being used in one printf() call: E.g.:
printf("addr1->%s, addr2->%s, addr3->%s, addr4->%s\n",
naddr_ntoa(addr1), naddr_ntoa(addr2), naddr_ntoa(addr3), naddr_ntoa(addr4));
There are several examples of similar uses in the routed source files (if.c, input.c, rdisc.c).
There is no bug in this code. The routed program is not multi-threaded. Reentrancy is not being addressed at all in this hack. This trick has been done by design for a very specific purpose that has nothing to do with reentrancy. The Code Reading author(s) is wrong to associate this trick with reentrancy.
It's simply a way to hide the saving of multiple results in an array of static variables instead of having to individually copy those results from one static variable into separate storage in the calling function when multiple results are required for a single expression.
Remember that static variables have all the properties of global variables except for the limited scope of their identifier. It is of course true that unprotected use of global (or static) variables inside a function make that function non-reentrant, but that's not the only problem global variables cause. Use of a fully-reentrant function would not be appropriate in routed because it would actually make the code more complex than necessary, whereas this hack keeps the calling code clean and simple. It would though have been better for the hack to be properly documented such that future maintainers would more easily spot when NUM_BUFS has to be adjusted.

Resources