C library naming conventions

前端 未结 8 1771
一向
一向 2021-01-31 05:50

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

相关标签:
8条回答
  • 2021-01-31 05:59

    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)

    0 讨论(0)
  • 2021-01-31 06:10

    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;
    }
    
    0 讨论(0)
  • 2021-01-31 06:16

    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;
    }
    
    0 讨论(0)
  • 2021-01-31 06:16

    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.

    0 讨论(0)
  • 2021-01-31 06:17

    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.

    0 讨论(0)
  • 2021-01-31 06:18

    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...

    0 讨论(0)
提交回复
热议问题