<jupyter_start><jupyter_text>The Static and Shared Library with GCC   The Library Library files are a collection of **precompiled functions** that are written according to the principle of reusability.  Static  Library Static libraries are **directly linked into** the program at compile time. A program using a static library takes copies of the code that it uses from the static library and makes it part of the program.  Shared  Library For a shared library, the compiler/linker checks that the names you link with exist in the library when the application is built, **but doesn't move their code into the application**. At run time, the shared library must be available.Before the executable starts running, **the operating system loads the machine code needed for the external functions** - a process known as **dynamic linking.** ![library](./img/library.png)  The advantages and disadvantages in each methodThere are two powerful ideas for modular programming with C/C++ programs, * Modular organization of `sources`:  organize program sources into a source tree* Modular organization of `object files`:  combine object files into libraries**The advantages of using library**1. Modular development2. Reusability3. Maintainability**Shared libraries*** reduce the amount of code that is duplicated in each program that makes use of the library, keeping **binaries small**. * allows you to replace the shared object with one that is functionally equivalent, but may have added performance benefits **without needing to recompile** the program that makes use of it. Shared libraries will, however have a small additional cost for the execution of the functions as well as a run-time loading cost as all the symbols in the library need to be connected to the things they use**Static libraries*** increase the overall size of the binary, but it means that you don't need to carry along a copy of the library that is being used. As the code is connected at compile time there are not any additional run-time loading costs. The code is simply there.**GCC assumes that all libraries**   * `start` with **lib*** Static libraries: `end` with `.a`* Shared libraries: `end`  with `.dll`(windows) or `.so`(Linux)， Change the current working directory to `./demo`<jupyter_code>%pwd
%cd demo<jupyter_output>J:\SEU\SEECW\SE\SEES\notebook\demo<jupyter_text>1 The shared library 1.1 The source code of library The  shared library we will build consist of a single source file: * `statistics.c/h`<jupyter_code>%%file ./include/statistics.h
#ifndef STATISTICS_H
#define STATISTICS_H

double  mean(double data[], int size);

#endif

%%file ./src/statistics.c

#include "statistics.h"

double  mean(double data[], int size)
{
  /* Compute the arithmetic mean of a dataset using the recurrence relation 
     mean_(n) = mean(n-1) + (data[n] - mean(n-1))/(n+1)   */

  double mean = 0;
  for(int  i = 0; i < size; i++)
  {
      mean += (data[i] - mean) / (i + 1);
   }
  return mean;
}<jupyter_output>Overwriting ./src/statistics.c<jupyter_text>1.2 The shared library  Step 1: Compiling with Position Independent CodeWe compile the C file with `Position Independent Code( PIC )` * **`-fPIC`** : stands for `Position Independent Code`(位置无关代码)      the generated machine code is `not dependent` on being located at a `specific address` in order to `work`.      Position-independent code can be `executed` at `any memory address`<jupyter_code>!gcc -c -O3 -Wall -fPIC  -o  ./obj/statistics.o  ./src/statistics.c -I./include/<jupyter_output><empty_output><jupyter_text>* `-c`: compile into object file with default name : *.o.      By default, the object file has the same name as the source file with extension of ".o"     * `-O3`: Optimize yet more.      turns on all optimizations specified by -O2 and also turns on the -finline-functions, -fweb, -frename-registers and -funswitch-loops optionsturns  on  all  optimizations          * `-Wall`: prints "all"  compiler's warning message.       This option should always be used, in order to generate better code.  Step 2: Creating a shared library from an object file* -shared : creating a shared library<jupyter_code>!gcc -shared -o  ./bin/libstat.dll ./obj/statistics.o<jupyter_output><empty_output><jupyter_text>**Makefile of Building the shared library**<jupyter_code>%%file ./makestatso.mk

CC=gcc
CFLAGS=-O3 -Wall -fPIC 

SRC=./src/
OBJ=./obj/
BIN=./bin/
INC=./include/

# Windows
LIB=libstat.dll

all:  $(LIB)

$(LIB): statobj
	 $(CC) -shared -o $(BIN)$@ $(OBJ)statistics.o
    
statobj: $(SRC)statistics.c
	 $(CC) -c $(CFLAGS)  -o $(OBJ)statistics.o $(SRC)statistics.c -I$(INC)    

!make -f makestatso.mk
!dir .\bin\libstat*.*<jupyter_output><empty_output><jupyter_text>Step3: Using the shared library  Header Files and Libraries * `Header File`: When compiling the program, the **compiler** needs the **header** files to compile the source codes;* `libraries`: the **linker** needs the **libraries** to resolve external references from other object files or libraries. The `compiler` and `linker` will not find the `headers/libraries` unless you set **the appropriate options*** **1 Searching for Header Files**   **`-Idir`:** The include-paths are specified via **-Idir** option (`uppercase` 'I' followed by the directory path.       * **2 Searching for libraries Files**   **`-Ldir`**: The library-path is specified via **-Ldir** option (`uppercase` 'L' followed by the directory path）. * **3 Linking the library**   **`-lname`**: Link with the library name **without** the `lib` prefix and the extensions.  We use the **same** code ` ./src/statdemo.c` to demonstrates calling the shared library  **Makefile**<jupyter_code>%%file ./makestatsodemo.mk

SRC= ./src/
OBJ= ./obj/
BIN= ./bin/
INC=./include/

all: statdemoso

statdemoso: statobj  
	gcc -o $(BIN)$@ $(OBJ)statdemo.o -L$(BIN) -lstat

statobj: $(SRC)statdemo.c 
	gcc -c -o $(OBJ)statdemo.o $(SRC)statdemo.c -I$(INC)
    
run:
	./bin/statdemoso  
    
!make -f makestatsodemo.mk
!dir .\bin\statdemo*.*
!.\bin\statdemoso
!make -f makestatsodemo.mk run<jupyter_output><empty_output><jupyter_text>Step4 Automatic building all<jupyter_code>%%file ./makefile

all:
	make -f makestatso.mk
	make -f makestatsodemo.mk
	make -f makestatsodemo.mk run
!make -f makelibandclient.mk<jupyter_output><empty_output><jupyter_text>2 Building  a Shared Library with Multi-source 2.1  The multi-source filesThe shared library we will build consist of the multi-source files* statistics.c/h* number.c/h<jupyter_code>%%file ./include/number.h

#ifndef NUMBER_H
#define NUMBER_H

 
int factorial(int n);


#endif
%%file ./src/number.c

#include "number.h"

// The factorial of a positive integer n, denoted by n!, 
//    is the product of all positive integers less than or equal to n. 
//  For example,5!=5*4*3*2*1=120
//  The value of 0! is 1 
int factorial(int n)
{
    if (n == 0 ) {
        return 1;
    }
    else 
    {
        return n * factorial(n - 1);
    }
}<jupyter_output>Overwriting ./src/number.c<jupyter_text>2.2 Building  into One Shared Library**Makefile**```makeSRCS=$(SRC)statistics.c \    $(SRC)number.c ```<jupyter_code>%%file ./makelibmaths.mk

CC=gcc
CFLAGS=-O3 -Wall -fPIC

SRC= ./src/
OBJ= ./obj/
BIN= ./bin/
INC= ./include/

LIB=libmaths.dll

SRCS=$(SRC)statistics.c \
    $(SRC)number.c 

# non-path filename
filename=$(notdir $(SRCS))

# the obj target of a source code using the pattern rule
OBJS=$(patsubst %.c,$(OBJ)%.o,$(filename))

all:$(LIB)
    
$(LIB): $(OBJS)  
	$(CC) -shared -o $(BIN)$@ $^ 

# the pattern rule: one step rule for multiple source files
$(OBJS):$(SRCS)
	$(CC) $(CFLAGS) -o $@ -c $(SRC)$(patsubst  %.o,%.c,$(notdir $@))  -I$(INC)
!make -f makelibmaths.mk
!dir .\bin\libm*.dll<jupyter_output>驱动器 J 中的卷是 cmh
 卷的序列号是 9C25-3306

 J:\SEU\SEECW\SE\SEES\notebook\demo\bin 的目录

2022/05/17  19:25            48,164 libmaths.dll
               1 个文件         48,164 字节
               0 个目录 94,268,981,248 可用字节<jupyter_text>2.3 Building a client executable The code demonstrates calling the shared library's functions: 2.3.1 C<jupyter_code>%%file ./src/demomath.c

#include <stdio.h> 
#include "statistics.h"
#include "number.h"

int main() {
    
     double a[] = {8, 4, 5, 3, 2};
     int len= sizeof(a)/sizeof(*a);
     printf("mena is %f\n", mean(a,  len)); 
    
     int n =5;
     printf("the factorial of  %d is %d\n",n,factorial(n));  // 5!=120
     return 0;
}
!gcc -o  ./bin/demomath ./src/demomath.c  -L./bin/ -lmaths -I./include
!.\bin\demomath<jupyter_output>mena is 4.400000
the factorial of  5 is 120<jupyter_text>2.3.2 CPPC++ has a special keyword to declare a function with C bindings: **extern "C"**A function declared as **extern "C"** uses the function name as symbol name, just as a C function```cppifdef __cplusplusextern "C"{endif// all of your legacy C code here    ifdef __cplusplus}endif```<jupyter_code>%%file ./include/statistics.h
#ifndef STATISTICS_H
#define STATISTICS_H

#ifdef __cplusplus
extern "C"
{
#endif
    
double  mean(double data[], int size);

#ifdef __cplusplus

}
#endif

#endif

%%file ./include/number.h

#ifndef NUMBER_H
#define NUMBER_H


#ifdef __cplusplus
extern "C"
{
#endif
    
int factorial(int n);


#ifdef __cplusplus
}
#endif

#endif
%%file ./src/demomath.cpp

#include <iostream>

#include "statistics.h"
#include "number.h"

using namespace std;

int main() {
    
     double a[] = {8, 4, 5, 3, 2};
     int len= sizeof(a)/sizeof(*a);
     cout<<"mean is "<<mean(a,  len)<<endl; 
    
     int n =5;
     cout<<"the factorial of "s<<n<<" is "<<factorial(n)<<endl;  // 5!=120
     return 0;
}
!g++ -o  ./bin/demomath ./src/demomath.cpp  -L./bin/ -lmaths -I./include
!.\bin\demomath<jupyter_output>mean is 4.4
the factorial of 5 is 120<jupyter_text>3 The C/C++ Caller of CoolProp Library in Windows* [Official Doc: CoolProp Shared Library](http://www.coolprop.org/coolprop/wrappers/SharedLibrary/index.html)**Change working dir to `./notebook/coolpropdemo`**![CoolPropdemo](./img/vcr/coolpropdemo.jpg)> **Note:** the `coolpropdemo` have demo codes for Windows and **Linux**> >  the details about Using The CoolProp  shared library under Linux in [Unit8-2-Programming_On_Linux](./Unit8-2-Programming_On_Linux)<jupyter_code>%pwd
%cd ../coolpropdemo<jupyter_output>J:\SEU\SEECW\SE\SEES\notebook\coolpropdemo<jupyter_text>**The Windows Shared Library**1. The official Windows Shared Library builded Microsoft Visuall C++: `CoolProp_x64.dll`2. The Shared Library builded with TDM-GCC-64: `libCoolProp.dll`The example use a TDM-GCC-64's dll: **libCoolProp.dll**   C Caller* -DCOOLPROP_LIB<jupyter_code>%%file ./main.c

/* 
The example use the shared library of CoolProp in c

g++ -DCOOLPROP_LIB -o ./bin/main   main.c -I./include -L./bin -lCoolProp
./bin/main

*/

#include "CoolPropLib.h"
#include <stdio.h>

int main() {
     double value=PropsSI("P","T",273.15+0,"Q",0,"R134a");
     printf("%f\n", value); 
     return 0;
}<jupyter_output>Overwriting ./main.c<jupyter_text>Compiling<jupyter_code>!g++  -DCOOLPROP_LIB -o ./bin/main  main.c -I./include -L./bin -lCoolProp<jupyter_output><empty_output><jupyter_text>Run<jupyter_code>!.\bin\main<jupyter_output><empty_output><jupyter_text>C++ Caller<jupyter_code>%%file ./demo.cpp
/* 
The example use the shared library of CoolProp in c++

g++ -DCOOLPROP_LIB -o ./bin/demo  demo.cpp -I./include -L./bin -lCoolProp

./bin/demo

*/

#include "CoolPropLib.h"
#include <iostream>
#include <iomanip>

int main()
{
    double value=PropsSI("P","T",273.15+0,"Q",0,"R134a");
    std::cout << std::setiosflags(std::ios::fixed)  << value << std::endl;
    return 1;
}<jupyter_output>Overwriting ./demo.cpp<jupyter_text>Compiling<jupyter_code>!g++ -DCOOLPROP_LIB -o ./bin/demo  demo.cpp -I./include -L./bin -lCoolProp<jupyter_output><empty_output><jupyter_text>Run<jupyter_code>!.\bin\demo<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13411645398461927, 'fraction_numerical': 0.014282092453308543, 'mean_word_length': 4.027187765505523, 'pattern_counts': {'":': 0, '<': 92, '<?xml version=': 0, '>': 72, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '72898', 'license': 'MIT', 'n_tokens_mistral': 4280, 'n_tokens_neox': 4037, 'n_words': 1310, 'path': 'notebook/Unit5-2-GCC_Library.ipynb', 'repo_name': 'SEU03013050C/HOME-03013050-C-SEU', 'size': '11833'}