By reading What does -D_XOPEN_SOURCE do/mean? , I understand that how to use feature test macros.
But I still don't understand why do we need it, I mean, can we just enable all features available? Then the doc writes like this: this function only available in Mac/BSD, that function only available in Linux, if you use it, then your program can only be running on that system.
So why do we need a feature test macro in the first place?
why do we need it, I mean, can we just enable all features available?
Imagine some company has written perfectly fine super portable code roughly like the following:
#include <stdlib.h>
struct someone_s { char name[20]; };
/// #brief grants Plant To someone
int grantpt(int plant_no, struct someone_s someone) {
// some super plant granting algorithm here
return 0;
}
int main() {
// some program here
struct someone_s kamil = { "Kamil" };
return grantpt(20, kamil);
}
That program is completely fine and all is working fine, and that program is very C compatible, thus should be portable to anywhere. Now imagine for a moment that _XOPEN_SOURCE does not exist! A customer receives sources of that program and tries to compile and run it on his bleeding edge Unix computer with certified C compiler on a certified POSIX system, and he receives an error that that company has to fix, and in turn has to pay for:
/tmp/1.c:7:9: error: conflicting types for ‘grantpt’; have ‘int(struct someone_s, int)’
7 | int grantpt(struct someone_s someone, int plant_no) {
| ^~~~~~~
In file included from /tmp/1.c:2:
/usr/include/stdlib.h:977:12: note: previous declaration of ‘grantpt’ with type ‘int(int)’
977 | extern int grantpt (int __fd) __THROW;
| ^~~~~~~
Looks like a completely random name picked for a function is already taken in POSIX - grantpt().
When introducing new symbols that are not in reserved space, standards like POSIX can't just "add them" and expect the world not to protest - conflicting definitions can and will and do break valid programs. To battle the issue feature_test_macros were introduced. When a program does #define _XOPEN_SOURCE 500 it means that it is prepared for the POSIX standard and there are no conflicts between the code and symbols introduced by POSIX in that version.
Feature test macros are not just "my program wants to use these functions", it is most importantly "my program has no conflicts with these functions", which is way more important, so that existing programs continue to run.
The theoretical reason why we have feature selection macros in C, is to get the C library out of your way. Suppose, hypothetically, you want to use the name getline for a function in your program. The C standard says you can do that. But some operating systems provide a C library function called getline, as an extension. Its declaration will probably clash with your definition. With feature selection macros, you can, in principle, tell those OSes' stdio.hes not to declare their getline so you can use yours.
In practice these macros are too coarse grained to be useful, and the only ones that get used are the ones that mean "give me everything you got", and people do exactly what you speculate they could do, in the documentation.
Newer programming languages (Ada, C++, Modula-2, etc.) have a concept of "modules" (sometimes also called "namespaces") which allow the programmer to give an exact list of what they want from the runtime library; this works much better.
Why do we need feature test macros?
You use feature test macros to determine if the implementation supports certain features or if you need to select an alternative way to implement whatever it is you're implementing.
One example is the set of *_s functions, like strcpy_s:
errno_t strcpy_s(char *restrict dest, rsize_t destsz, const char *restrict src);
// put this first to signal that you actually want the LIB_EXT1 functions
#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
Then in your code:
#ifdef __STDC_LIB_EXT1__
errno_t err = strcpy_s(...); // The implementation supports it so you can use it
#else
// Not supported, use an alternative, like your own implementation
// or let it fail to compile.
#fi
can we just enable all features available?
When it comes to why you need to tell the implementation that you actually want a certain set of features (instead of it just including them all automatically) I have no better answer than that it could possibly make the programs slower to compile and could possibly also make it produce bigger executables than necessary.
Similarly, the implementation does not link with every library it has available, but only the most basic ones. You have to tell it what you need.
In theory, you could create header file which defines all the possible macros that you've found that will enable a certain set of features.
#define _XOPEN_SOURCE 700
#define __STDC_LIB_EXT1__ 1
...
But as you see with _XOPEN_SOURCE, there are different releases, and you can't enable them all at the same time, you need to select one.
Related
I am new to coding using MISRA C guidelines.
The following are two rules in MISRA C 2004:
Rule 16.1 (required): Functions shall not be defined with a variable number of arguments.
Rule 20.9 (required): The input/output library <stdio.h> shall not be used in production code.
This clearly means that I can't use printf in production code for it to be MISRA C compliant, because printf is a part of <stdio.h> and allows a variable number of arguments. So I set out on a quest to find out how I can write my own printf statement. So far I am unable to find any solution for this predicament. Any help from fellow developers would be appreciated.
so far I am unable to find any solution for this predicament
You have to use functions that print one (countable) things at a time. An example interface you might want to implement might look like the following:
print_string("Hello");
print_int(5);
print_char('\n');
so I set out on a quest to find out how I can write my own printf statement
Most MISRA-C systems are embedded systems where printf is just some bloated wrapper around an UART library. The usual solution is to develop your own logging/messaging tool instead. Not necessarily UART-based, might as well some other serial bus, or just 8 parallel data or some LCD/7-seg... all depending on what you need to display and if you intend for this to be part of the production code or not.
So how to do this is highly project-specific and it's typically more of a system design and electronics problem than a programming one.
EDIT
Since you seem to be making some sort of general-purpose library, one solution is to simply provide an API that returns strings to the caller, then let the caller worry about how to present them. That makes your lib MISRA-C compliant, while allowing the caller to print strings in whatever application-specific way they have available. For example:
void lib_getmsg (char* msg, size_t bufsize);
Where "lib" is some prefix for your library. Leave string allocation to the caller. Alternatively, the old-fashioned way:
lib_result_t lib_dosomething (void);
// Returns LIB_OK if went OK, returns LIB_ERR in case of errors.
// To get more information, call lib_get_lastmsg.
const char* lib_get_lastmsg (void);
This returns a pointer to an internal static string allocated by your library. The downside of this is that it won't work well in multi-process environments.
You need to understand the rationale for the MISRA C guidelines, understand the context they are used in, and the circumstances of your own code.
You also need to understand that the MISRA Guidelines are not to be blindly followed with a tick-box mentality... you then need to appreciate that those nice folk at MISRA provide several chapters of useful material before the actual guidelines. Part of that is the Deviation procedure.
If you can justify why you feel you need to violate a guidelines, then use the deviation procedure that is specified. This requires you understand the nature of the violation, and what you are going to do to ensure the integrity of your application.
If you genuinely need to use printf() and you can justify that, use it with a deviation
On Linux, running on a modern x86_64 processor:
int main()
{
char *s = "Hello, World!\n";
long l = 14;
long fd = 1;
long syscall = 1;
long ret = 0;
__asm__("syscall"
: "=a"(ret)
: "a"(syscall),
"D"(fd),
"S"(s),
"d"(l));
return 0;
}
Output:
Hello, World!
NOTE: This is NOT a duplicate of the question linked by Paul T, because I am asking if it is possible to determine if a type is of a certain broader incomplete type/kind at compile time, not if a symbol has been registered at compile time. This seems like a fundamental misunderstanding of the question.
I am writing a library in C that deals with pseudo-generic functions which take a type as an argument through a macro wrapper.
To spare the details (because they are rather complicated) there are two possible features that could help, I think:
Being able to detect if a type is a pointer at compile time. (No, the "use _Generic to test if you get ptrdiff_t from subtraction" trick won't work, because structures are a possibility, and you can't subtract structures.)
Being able to detect if a type is a struct at compile time. (If this was possible, then the aforementioned _Generic trick could be used if the type was detected as not being a struct.)
I've tried everything I could think of on Godbolt (even trying to compare types to incomplete anonymous structs and toying with __builtin_types_compatible_p) and wasn't able to find any solutions.
If anyone has any solutions I'd love to see them, otherwise I may just end up having to complicate the design a bit-- so not the end of the world if it's impossible, but it would be ideal if it can be done.
To give a basic idea of what one of these macros might look like or their expected output:
int *a;
assert(!IS_STRUCT(a));
assert(IS_POINTER(a));
struct {} b;
assert(IS_STRUCT(b));
assert(!IS_POINTER(b));
shouldn't throw any errors.
Complete Answer (if EDG Front End used):
If your IDE / compiler is using the EDG C++ Front End (which a lot are), and you are using C, not C++ (which your tag suggests), and you say you ARE using typeof, then you can detect a structs as follows (see the latest manual, page 75):
/* Test if EDG Front End is used*/
#if defined(__EDG__) && defined(__EDG_VERSION__)
#define IS_STRUCT(expression_or_type_name) __is_class(typeof (expression_or_type_name)))
#endif
since in C __is_class() will only be true for a struct (http://www.cplusplus.com/reference/type_traits/is_class/).
Further, pointers can similarly be detected as follows:
/* Test if EDG Front End is used*/
#if defined(__EDG__) && defined(__EDG_VERSION__)
#define IS_POINTER(expression_or_type_name) (__is_convertible_to(typeof (expression_or_type_name), void*) || __is_convertible_to(typeof (expression_or_type_name), void const*) || __is_convertible_to(typeof (expression_or_type_name), void volatile*) || __is_convertible_to(typeof (expression_or_type_name), void const volatile*))
#endif
(http://www.cplusplus.com/reference/type_traits/is_convertible/)
It’s not possible in standard C. Whatever solutions there may be must be implementation-defined.
It seems that C is not a suitable language for your problem domain. Short of esoteric platforms that come without C++ support, there seems to be little reason to have to solve this in C. On most any platform where C is available, so is C++. Since you claim that you use gcc, then C++ is surely available and you can process some of the input using a C++ compiler. You could do the input processing as a generator step: run the code through a C++ compiler to generate source code that defines constants that capture type properties sought.
I have worked on several projects in college on C, but never used it in professional capacity.
Recently I started reading through cpython's source code and the following syntax confused me: github
What does PyAPI_FUNC(int) PyToken_OneChar(int); the part before the function name mean? Is it a wrapper function that dynamically constructs the return type?
I am not even sure what to Google search for, in this case!
PyAPI_FUNC() is a macro defined in pyport.h. The particular definition depends on the platform you're building on, but here's an example:
#define PyAPI_FUNC(RTYPE) __declspec(dllimport) RTYPE
So the line in your question, PyAPI_FUNC(int) PyToken_OneChar(int); expands to:
__declspec(dllimport) int PyToken_OneChar(int);
Basically, it just declares the name PyToken_OneChar as a function that takes an int as its parameter and returns an int, but it does it in a way that lets the compiler embed storage information with those types. See What is __declspec and when do I need to use it? for more information about the __declspec directive if you're interested. Another of the definitions for PyAPI_FUNC is:
#define PyAPI_FUNC(RTYPE) RTYPE
which skips all that and just expands the line above to:
int PyToken_OneChar(int);
So the main thing to take away from this is that source code that's meant to compile on multiple platforms often uses macros that make it easier to write code once and use it on each of those platforms. In this case, it lets the programmers write declarations for PyToken_OneChar() and many other functions once instead of having to write (and maintain!) different versions for each platform. This is fairly advanced stuff -- not something you should worry about if you're getting started.
It's a C Macro they wrote which allows them to do different things on different OS platforms, for instance, on windows, this will export the function as part of the public interface for a DLL.
I am a first year computer science student and my professor said #define is banned in the industry standards along with #if, #ifdef, #else, and a few other preprocessor directives. He used the word "banned" because of unexpected behaviour.
Is this accurate? If so why?
Are there, in fact, any standards which prohibit the use of these directives?
First I've heard of it.
No; #define and so on are widely used. Sometimes too widely used, but definitely used. There are places where the C standard mandates the use of macros — you can't avoid those easily. For example, §7.5 Errors <errno.h> says:
The macros are
EDOM
EILSEQ
ERANGE
which expand to integer constant expressions with type int, distinct positive values, and which are suitable for use in #if preprocessing directives; …
Given this, it is clear that not all industry standards prohibit the use of the C preprocessor macro directives. However, there are 'best practices' or 'coding guidelines' standards from various organizations that prescribe limits on the use of the C preprocessor, though none ban its use completely — it is an innate part of C and cannot be wholly avoided. Often, these standards are for people working in safety-critical areas.
One standard you could check the MISRA C (2012) standard; that tends to proscribe things, but even that recognizes that #define et al are sometimes needed (section 8.20, rules 20.1 through 20.14 cover the C preprocessor).
The NASA GSFC (Goddard Space Flight Center) C Coding Standards simply say:
Macros should be used only when necessary. Overuse of macros can make code harder to read and maintain because the code no longer reads or behaves like standard C.
The discussion after that introductory statement illustrates the acceptable use of function macros.
The CERT C Coding Standard has a number of guidelines about the use of the preprocessor, and implies that you should minimize the use of the preprocessor, but does not ban its use.
Stroustrup would like to make the preprocessor irrelevant in C++, but that hasn't happened yet. As Peter notes, some C++ standards, such as the JSF AV C++ Coding Standards (Joint Strike Fighter, Air Vehicle) from circa 2005, dictate minimal use of the C preprocessor. Essentially, the JSF AV C++ rules restrict it to #include and the #ifndef XYZ_H / #define XYZ_H / … / #endif dance that prevents multiple inclusions of a single header. C++ has some options that are not available in C — notably, better support for typed constants that can then be used in places where C does not allow them to be used. See also static const vs #define vs enum for a discussion of the issues there.
It is a good idea to minimize the use of the preprocessor — it is often abused at least as much as it is used (see the Boost preprocessor 'library' for illustrations of how far you can go with the C preprocessor).
Summary
The preprocessor is an integral part of C and #define and #if etc cannot be wholly avoided. The statement by the professor in the question is not generally valid: #define is banned in the industry standards along with #if, #ifdef, #else, and a few other macros is an over-statement at best, but might be supportable with explicit reference to specific industry standards (but the standards in question do not include ISO/IEC 9899:2011 — the C standard).
Note that David Hammen has provided information about one specific C coding standard — the JPL C Coding Standard — that prohibits a lot of things that many people use in C, including limiting the use of of the C preprocessor (and limiting the use of dynamic memory allocation, and prohibiting recursion — read it to see why, and decide whether those reasons are relevant to you).
No, use of macros is not banned.
In fact, use of #include guards in header files is one common technique that is often mandatory and encouraged by accepted coding guidelines. Some folks claim that #pragma once is an alternative to that, but the problem is that #pragma once - by definition, since pragmas are a hook provided by the standard for compiler-specific extensions - is non-standard, even if it is supported by a number of compilers.
That said, there are a number of industry guidelines and encouraged practices that actively discourage all usage of macros other than #include guards because of the problems macros introduce (not respecting scope, etc). In C++ development, use of macros is frowned upon even more strongly than in C development.
Discouraging use of something is not the same as banning it, since it is still possible to legitimately use it - for example, by documenting a justification.
Some coding standards may discourage or even forbid the use of #define to create function-like macros that take arguments, like
#define SQR(x) ((x)*(x))
because a) such macros are not type-safe, and b) somebody will inevitably write SQR(x++), which is bad juju.
Some standards may discourage or ban the use of #ifdefs for conditional compilation. For example, the following code uses conditional compilation to properly print out a size_t value. For C99 and later, you use the %zu conversion specifier; for C89 and earlier, you use %lu and cast the value to unsigned long:
#if __STDC_VERSION__ >= 199901L
# define SIZE_T_CAST
# define SIZE_T_FMT "%zu"
#else
# define SIZE_T_CAST (unsigned long)
# define SIZE_T_FMT "%lu"
#endif
...
printf( "sizeof foo = " SIZE_T_FMT "\n", SIZE_T_CAST sizeof foo );
Some standards may mandate that instead of doing this, you implement the module twice, once for C89 and earlier, once for C99 and later:
/* C89 version */
printf( "sizeof foo = %lu\n", (unsigned long) sizeof foo );
/* C99 version */
printf( "sizeof foo = %zu\n", sizeof foo );
and then let Make (or Ant, or whatever build tool you're using) deal with compiling and linking the correct version. For this example that would be ridiculous overkill, but I've seen code that was an untraceable rat's nest of #ifdefs that should have had that conditional code factored out into separate files.
However, I am not aware of any company or industry group that has banned the use of preprocessor statements outright.
Macros can not be "banned". The statement is nonsense. Literally.
For example, section 7.5 Errors <errno.h> of the C Standard requires the use of macros:
1 The header <errno.h> defines several macros, all relating to the reporting of error conditions.
2 The macros are
EDOM
EILSEQ
ERANGE
which expand to integer constant expressions with type int, distinct
positive values, and which are suitable for use in #if preprocessing
directives; and
errno
which expands to a modifiable lvalue that has type int and thread
local storage duration, the value of which is set to a positive error
number by several library functions. If a macro definition is
suppressed in order to access an actual object, or a program defines
an identifier with the name errno, the behavior is undefined.
So, not only are macros a required part of C, in some cases not using them results in undefined behavior.
No, #define is not banned. Misuse of #define, however, may be frowned upon.
For instance, you may use
#define DEBUG
in your code so that later on, you can designate parts of your code for conditional compilation using #ifdef DEBUG, for debug purposes only. I don't think anyone in his right mind would want to ban something like this. Macros defined using #define are also used extensively in portable programs, to enable/disable compilation of platform-specific code.
However, if you are using something like
#define PI 3.141592653589793
your teacher may rightfully point out that it is much better to declare PI as a constant with the appropriate type, e.g.,
const double PI = 3.141592653589793;
as it allows the compiler to do type checking when PI is used.
Similarly (as mentioned by John Bode above), the use of function-like macros may be disapproved of, especially in C++ where templates can be used. So instead of
#define SQ(X) ((X)*(X))
consider using
double SQ(double X) { return X * X; }
or, in C++, better yet,
template <typename T>T SQ(T X) { return X * X; }
Once again, the idea is that by using the facilities of the language instead of the preprocessor, you allow the compiler to type check and also (possibly) generate better code.
Once you have enough coding experience, you'll know exactly when it is appropriate to use #define. Until then, I think it is a good idea for your teacher to impose certain rules and coding standards, but preferably they themselves should know, and be able to explain, the reasons. A blanket ban on #define is nonsensical.
That's completely false, macros are heavily used in C. Beginners often use them badly but that's not a reason to ban them from industry. A classic bad usage is #define succesor(n) n + 1. If you expect 2 * successor(9) to give 20, then you're wrong because that expression will be translated as 2 * 9 + 1 i.e. 19 not 20. Use parenthesis to get the expected result.
No. It is not banned. And truth to be told, it is impossible to do non-trivial multi-platform code without it.
No your professor is wrong or you misheard something.
#define is a preprocessor macro, and preprocessor macros are needed for conditional compilation and some conventions, which aren't simply built in the C language. For example, in a recent C standard, namely C99, support for booleans had been added. But it's not supported "native" by the language, but by preprocessor #defines. See this reference to stdbool.h
Macros are used pretty heavily in GNU land C, and without conditional preprocessor commands there's be no way to properly handle multiple inclusions of the same source files, so that makes them seem like essential language features to me.
Maybe your class is actually on C++, which despite many people's failure to do so, should be distinguished from C as it is a different language, and I can't speak for macros there. Or maybe the professor meant he's banning them in his class. Anyhow I'm sure the SO community would be interested in hearing which standard he's talking about, since I'm pretty sure all C standards support the use of macros.
Contrary to all of the answers to date, the use of preprocessor directives is oftentimes banned in high-reliability computing. There are two exceptions to this, the use of which are mandated in such organizations. These are the #include directive, and the use of an include guard in a header file. These kinds of bans are more likely in C++ rather than in C.
Here's but one example: 16.1.1 Use the preprocessor only for implementing include guards, and including header files with include guards.
Another example, this time for C rather than C++: JPL Institutional Coding Standard for the C Programming Language . This C coding standard doesn't go quite so far as banning the use of the preprocessor completely, but it comes close. Specifically, it says
Rule 20 (preprocessor use)
Use of the C preprocessor shall be limited to file inclusion and simple macros. [Power of Ten Rule 8].
I'm neither condoning nor decrying those standards. But to say they don't exist is ludicrous.
If you want your C code to interoperate with C++ code, you will want to declare your externally visible symbols, such as function declarations, in the extern "C" namespace. This is often done using conditional compilation:
#ifdef __cplusplus
extern "C" {
#endif
/* C header file body */
#ifdef __cplusplus
}
#endif
Look at any header file and you will see something like this:
#ifndef _FILE_NAME_H
#define _FILE_NAME_H
//Exported functions, strucs, define, ect. go here
#endif /*_FILE_NAME_H */
These define are not only allowed, but critical in nature as each time the header file is referenced in files it will be included separately. This means without the define you are redefining everything in between the guard multiple times which best case fails to compile and worse case leaves you scratching your head later why your code doesn't work the way you want it to.
The compiler will also use define as seen here with gcc that let you test for things like the version of the compiler which is very useful. I'm currently working on a project that needs to compile with avr-gcc, but we have a testing environment that we also run our code though. To prevent the avr specific files and registers from keeping our test code from running we do something like this:
#ifdef __AVR__
//avr specific code here
#endif
Using this in the production code, the complementary test code can compile without using the avr-gcc and the code above is only compiled using avr-gcc.
If you had just mentioned #define, I would have thought maybe he was alluding to its use for enumerations, which are better off using enum to avoid stupid errors such as assigning the same numerical value twice.
Note that even for this situation, it is sometimes better to use #defines than enums, for instance if you rely on numerical values exchanged with other systems and the actual values must stay the same even if you add/delete constants (for compatibility).
However, adding that #if, #ifdef, etc. should not be used either is just weird. Of course, they should probably not be abused, but in real life there are dozens of reasons to use them.
What he may have meant could be that (where appropriate), you should not hardcode behaviour in the source (which would require re-compilation to get a different behaviour), but rather use some form of run-time configuration instead.
That's the only interpretation I could think of that would make sense.
Introduction
Hello folks, I recently learned to program in C! (This was a huge step for me, since C++ was the first language, I had contact with and scared me off for nearly 10 years.) Coming from a mostly OO background (Java + C#), this was a very nice paradigm shift.
I love C. It's such a beautiful language. What surprised me the most, is the high grade of modularity and code reusability C supports - of course it's not as high as in a OO-language, but still far beyond my expectations for an imperative language.
Question
How do I prevent naming conflicts between the client code and my C library code? In Java there are packages, in C# there are namespaces. Imagine I write a C library, which offers the operation "add". It is very likely, that the client already uses an operation called like that - what do I do?
I'm especially looking for a client friendly solution. For example, I wouldn't like to prefix all my api operations like "myuniquelibname_add" at all. What are the common solutions to this in the C world? Do you put all api operations in a struct, so the client can choose its own prefix?
I'm very looking forward to the insights I get through your answers!
EDIT (modified question)
Dear Answerers, thank You for Your answers! I now see, that prefixes are the only way to safely avoid naming conflicts. So, I would like to modifiy my question: What possibilities do I have, to let the client choose his own prefix?
The answer Unwind posted, is one way. It doesn't use prefixes in the normal sense, but one has to prefix every api call by "api->". What further solutions are there (like using a #define for example)?
EDIT 2 (status update)
It all boils down to one of two approaches:
Using a struct
Using #define (note: There are many ways, how one can use #define to achieve, what I desire)
I will not accept any answer, because I think that there is no correct answer. The solution one chooses rather depends on the particular case and one's own preferences. I, by myself, will try out all the approaches You mentioned to find out which suits me best in which situation. Feel free to post arguments for or against certain appraoches in the comments of the corresponding answers.
Finally, I would like to especially thank:
Unwind - for his sophisticated answer including a full implementation of the "struct-method"
Christoph - for his good answer and pointing me to Namespaces in C
All others - for Your great input
If someone finds it appropriate to close this question (as no further insights to expect), he/she should feel free to do so - I can not decide this, as I'm no C guru.
I'm no C guru, but from the libraries I have used, it is quite common to use a prefix to separate functions.
For example, SDL will use SDL, OpenGL will use gl, etc...
The struct way that Ken mentions would look something like this:
struct MyCoolApi
{
int (*add)(int x, int y);
};
MyCoolApi * my_cool_api_initialize(void);
Then clients would do:
#include <stdio.h>
#include <stdlib.h>
#include "mycoolapi.h"
int main(void)
{
struct MyCoolApi *api;
if((api = my_cool_api_initialize()) != NULL)
{
int sum = api->add(3, 39);
printf("The cool API considers 3 + 39 to be %d\n", sum);
}
return EXIT_SUCCESS;
}
This still has "namespace-issues"; the struct name (called the "struct tag") needs to be unique, and you can't declare nested structs that are useful by themselves. It works well for collecting functions though, and is a technique you see quite often in C.
UPDATE: Here's how the implementation side could look, this was requested in a comment:
#include "mycoolapi.h"
/* Note: This does **not** pollute the global namespace,
* since the function is static.
*/
static int add(int x, int y)
{
return x + y;
}
struct MyCoolApi * my_cool_api_initialize(void)
{
/* Since we don't need to do anything at initialize,
* just keep a const struct ready and return it.
*/
static const struct MyCoolApi the_api = {
add
};
return &the_api;
}
It's a shame you got scared off by C++, as it has namespaces to deal with precisely this problem. In C, you are pretty much limited to using prefixes - you certainly can't "put api operations in a struct".
Edit: In response to your second question regarding allowing users to specify their own prefix, I would avoid it like the plague. 99.9% of users will be happy with whatever prefix you provide (assuming it isn't too silly) and will be very UNHAPPY at the hoops (macros, structs, whatever) they will have to jump through to satisfy the remaining 0.1%.
As a library user, you can easily define your own shortened namespaces via the preprocessor; the result will look a bit strange, but it works:
#define ns(NAME) my_cool_namespace_ ## NAME
makes it possible to write
ns(foo)(42)
instead of
my_cool_namespace_foo(42)
As a library author, you can provide shortened names as desribed here.
If you follow unwinds's advice and create an API structure, you should make the function pointers compile-time constants to make inlinig possible, ie in your .h file, use the follwoing code:
// canonical name
extern int my_cool_api_add(int x, int y);
// API structure
struct my_cool_api
{
int (*add)(int x, int y);
};
typedef const struct my_cool_api *MyCoolApi;
// define in header to make inlining possible
static MyCoolApi my_cool_api_initialize(void)
{
static const struct my_cool_api the_api = { my_cool_api_add };
return &the_api;
}
Unfortunately, there's no sure way to avoid name clashes in C. Since it lacks namespaces, you're left with prefixing the names of global functions and variables. Most libraries pick some short and "unique" prefix (unique is in quotes for obvious reasons), and hope that no clashes occur.
One thing to note is that most of the code of a library can be statically declared - meaning that it won't clash with similarly named functions in other files. But exported functions indeed have to be carefully prefixed.
Since you are exposing functions with the same name client cannot include your library header files along with other header files which have name collision. In this case you add the following in the header file before the function prototype and this wouldn't effect client usage as well.
#define add myuniquelibname_add
Please note this is a quick fix solution and should be the last option.
For a really huge example of the struct method, take a look at the Linux kernel; 30-odd million lines of C in that style.
Prefixes are only choice on C level.
On some platforms (that support separate namespaces for linkers, like Windows, OS X and some commercial unices, but not Linux and FreeBSD) you can workaround conflicts by stuffing code in a library, and only export the symbols from the library you really need. (and e.g. aliasing in the importlib in case there are conflicts in exported symbols)