C Language Development function library using opaque pointers to hide structure details

Source: Internet
Author: User
Tags mutex

1 modular design requires library interface to hide implementation details

As a function library, trying to reduce the coupling with its callers is the most basic design criterion. C language, as the classic "program = data structure + algorithm" practitioners, in the implementation of the function library, there must be a lot of structure definition, interface functions need to operate on these structures. At the same time, the modularization of the programming requires the Library interface to expose its implementation details as little as possible, and the interface parameters should use the basic data type as much as possible to avoid exposing the definition of the structure within the parameter.

2 Two ways to hide a struct

With the author's superficial understanding, there are two most commonly used methods, which can realize the hidden structure definition in the library: the interface function parameter uses the structure pointer, the interface function parameter uses the handle.

2.1 Referencing a struct with struct-body pointers

For the sake of convenience, first give a sample code written using VC + +.

Library of oral documents MySDK.h

 #pragma once   #ifdef mysdk_export   #define MYSDK_API __declspec (dllexport)   #else   #define MYSDK_API __declspec (dllimport)   #endif  typedef struct  _window window; /* pre-declaration */  #ifdef __cplusplus  extern  "C"  { #endif   Mysdk_api  window* CreateWindow ();  Mysdk_api  void  ShowWindow (window* Pwin);  #ifdef __cplusplus }  #endif   

Library implementation File Mysdk.c

#define Mysdk_export#include "MySDK.h"#include <stdlib.h>struct_window{intWidthintHeightintXintYunsigned Charcolor[3];intIsshow;}; Mysdk_api window* CreateWindow () {window* p =malloc(sizeof(Window));if(p) {p->width = -; P->height = -; P->x =0; P->y =0; p->color[0] =255; p->color[1] =255; p->color[2] =255; P->isshow =0; }returnP;} Mysdk_apivoidShowWindow (window* pwin) {pwin->isshow =1;}

Library Consumer Code

#include <stdio.h>#include "../myDll/MySDK.h"#pragma comment(lib, "../Debug/myDll.lib")int main(intchar** argv){    Window* pWin = CreateWindow();    ShowWindow(pWin);    return0;}

Where MySDK.h and MYSDK.C are the implementations of the library; main.cpp is the caller program implementation. Both sides used the same interface header file MySDK.h.

However, from the user's point of view, main.cpp only knows the type of struct that is known as window in the library, but does not know the implementation details (definition) of this body. Because the C + + compiler is a deferred-dependent compiler, as long as the source code does not involve the window structure in the body layout of the code, compile without the need to know the full definition of window, but still be able to check the correctness of the type name, such as if the client code as follows will be the compiler to check the problem:

    int* p = 0;    ShowWindow(p);

Although the compiler does not know the implementation details of the struct that the Pwin points to in ShowWindow (Pwin), it can still ensure that the argument type is window*, which makes it easier for callers to check for errors.

2.2 Referencing a struct using the handle (handle)

The first concept of touching the handle is in Win32API. You can conclude that the internal Windows system defines a large number of structures, such as thread objects, process objects, window objects 、....。 However, the definition of these structures is rarely provided in the programming interface Win32API, where the caller indirectly references the struct object to be used by a value called a handle.

Handle in Win32API
For example, the following Win32API

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,      00nullptrnullptrnullptr);  ShowWindow(hWnd, nCmdShow);  UpdateWindow(hWnd);

Window type must be a very complex structure in Windows, in order to hide its implementation details, Microsoft has taken a window handle concept to indirectly refer to the window structure body object. In order to achieve this correspondence, the corresponding relationship between the handle and the structure object must be maintained inside the library.

handles in the Linux API
The concept of handle is also widely used in the Linux platform API. Such as

int open(constcharint flags); ssize_t read(intvoid *buf, size_t count);

Inside Linux, a file must be represented by a complex struct, but a simple integer is used in the API to reference it, avoiding the details of exposing the file structure to the caller.

Handles in the OpenGL API
Handles are also applied to the OpenGL library. Such as

void WINAPI glGenTextures(   GLsizei n,   GLuint  *textures);void WINAPI glBindTexture(   GLenum target,   GLuint texture);

Textures are also a complex structure inside the OpenGL library, and the same concept of using handles hides the implementation details.

3 comparison of handles and pointers 3.1 The advantages and disadvantages of the handle

The handle looks really good, so how does the local map to the corresponding structure? One of the most easily thought-out answers is to direct the memory address of the struct object as a handle. In practice, however, most library implementations do not do so. The reason why the memory address is not directly used as a handle value, I personally think there are several reasons:

    • From the source protection point of view, the memory address is more easily hack. Knowing the memory address of the structure, it is able to read the contents of the memory, thus providing convenience for guessing the structure details.

    • From the point of view of program stability, for objects maintained inside the library, callers should only be accessed through an interface function, and if the caller gets the memory address of the object, it is possible to make a direct modification intentionally or unintentionally, thus affecting the stable operation of the library.

    • From a portability perspective, pointer types have different lengths in 32-bit and 64-bit systems, which can cause a variety of inconveniences by defining the interface functions that are duplicated for two names. In the case of OpenGL, for example, using the int type as the handle type, you can have an interface function spanning multiple platforms.

    • From the angle of simplifying the oral file, the use of pointers requires at least a prior declaration of the struct type, such as struct Window; Instead of using the base data type as a handle, you do not need to do so.

The disadvantages of the handle exist are:

    • The compiler does not recognize the specific struct type
      Because the data type of the handle is essentially a basic data type, the compiler can only perform regular checks and not recognize the specific struct type. Such as
   SECURITY_ATTRIBUTES sa;   HANDLE= CreateMutex(&TRUE, L"Mutex");   NULL000);

The code compiler above does not complain because both the mutex object and the file object are using the same handle type.

    • The efficiency may be slightly worse
      After all, there is a process that looks at the memory pointer based on the handle value-it may slightly affect the efficiency of the operation.
3.2 Advantages and disadvantages of pointers

In fact, the pointer and handle is relative, the lack of handle is the advantage of pointers, the advantages of the handle is also the lack of pointers.

4 How to choose

For the design of large cross-platform libraries, handle is adopted, and pointers are used for private small libraries.

In terms of my current project, is a small C library project, the target group of the library is relatively single, so in a simple enough principle, I chose to use pointers to the way to hide the implementation of the structure of the library in detail.

C Language Development function library using opaque pointers to hide structure details

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.