Wednesday, March 19, 2025

Working with Files in the C Programming Language, Practical Examples and Tips for Efficient Programming

Working with files in the C programming language represents a key functionality that enables programmers to write, read, and manipulate data that is permanently stored on disk. This capability is essential for developing applications that require data storage between program executions, such as databases, configuration files, or logs. In the C programming language, file operations are achieved using the standard <stdio.h> library, which provides functions for opening, reading, writing, and closing files. In the C programming language, files are treated as data streams. There are two basic types of files:

  • Text files – data is stored as a sequence of characters, often human-readable, such as .txt files.
  • Binary files – data is stored in binary format, which is more efficient for machine processing, such as images, executable files, etc.

The FILE data type, defined in <stdio.h>, is used for working with files. This type is actually a pointer to a structure that contains information about the file, such as its location, current pointer position, and operating mode.

Working with files is straightforward in C programming

Working with files is straightforward in C programming

The C standard library provides several functions for working with files, including:

fopen() - Opens a file. 

fclose() - Closes a file.

fprintf() - Writes formatted text to a file.

fscanf() - Reads formatted text from a file.

fputc() - Writes a single character to a file.

fgetc() - Reads a single character from a file.

fwrite() - Writes a block of bytes to a file.

fread() - Reads a block of bytes from a file.

Working with files in the C programming language provides a powerful tool for data management, but requires attention to resource handling and error checking. Through the standard library, programmers can efficiently implement functionalities for both text and binary files, with flexibility for various types of applications. With basic operations such as opening, reading, writing, and closing, the C programming language also enables advanced techniques such as positioning and binary data processing, making it suitable for a wide range of tasks. Understanding basic operations such as opening, reading, writing, and closing files is crucial for developing applications that handle large amounts of data. First, we will focus on and examine C code for working with text files.

Reading and Writing Text Files in C Programming

Text files are one of the fundamental types of files used in programming, including the C programming language. They represent a sequence of characters that are typically human-readable, making them ideal for storing data such as text documents, configuration files, logs, or simple tables. Text files are files in which data is written in the form of characters according to a specific encoding, most commonly ASCII or UTF-8. Each character in the file has its place in the sequence, and special characters like newline \n or tab \t are used for formatting. Unlike binary files, which store data in raw, machine-readable format, text files are universal and easily opened in text editors like Notepad or Visual Studio Code. In the C programming language, text files are processed using FILE type pointers and a set of functions from <stdio.h>. The basic steps in working with text files include:
  • Opening a text file - The fopen() function is used to open a file, and modes such as "r" (read), "w" (write), or "a" (append) specify the action.
  • Writing to a text file - Functions like fprintf() for formatted text, fputs() for strings, or fputc() for individual characters are used for writing text.
  • Reading from a text file - fscanf() is used for formatted data, fgets() for reading lines, or fgetc() for individual characters.
  • Closing the file - After finishing work, the file is closed with fclose(fp) to release resources.
Theoretically, all of this might seem complicated, which is why we are moving on to the practical part, where you will see for yourself how simple the C code for working with text files actually is. Open your terminal and type the following code.

manuel@manuel-virtual-machine:~$ sudo apt-get update

manuel@manuel-virtual-machine:~$ sudo apt-get upgrade

manuel@manuel-virtual-machine:~$ clear

manuel@manuel-virtual-machine:~$ ls

manuel@manuel-virtual-machine:~$ cd tutorials

manuel@manuel-virtual-machine:/tutorials$ ls

manuel@manuel-virtual-machine:/tutorials$ cd c_tutorial

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ ls

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ mkdir phonebook

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ cd phonebook

manuel@manuel-virtual-machine:/tutorials/c_tutorial/phonebook$ code .

Create a file and name it phonebook.c, then type the following code. 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

#define MAX_LENGTH 50

 

// Structure for storing contact data

struct Contact {

    char firstName[MAX_LENGTH];

    char lastName[MAX_LENGTH];

    char company[MAX_LENGTH];

    char phone[MAX_LENGTH];

};

 

// Function to display the menu

void displayMenu() {

    printf("\n=== PHONE BOOK ===\n");

    printf("1. Add new contact\n");

    printf("2. Show all contacts\n");

    printf("3. Delete contact\n");

    printf("4. Edit contact details\n");

    printf("5. Exit\n");

    printf("Choose an option: ");

}

 

// Function to add a contact

void addContact() {

    struct Contact contact;

    FILE *fp = fopen("phonebook.txt", "a");

    if (fp == NULL) {

        printf("Error opening file!\n");

        return;

    }

 

    printf("Enter first name: ");

    fgets(contact.firstName, MAX_LENGTH, stdin);

    contact.firstName[strcspn(contact.firstName, "\n")] = 0;

 

    printf("Enter last name: ");

    fgets(contact.lastName, MAX_LENGTH, stdin);

    contact.lastName[strcspn(contact.lastName, "\n")] = 0;

 

    printf("Enter company: ");

    fgets(contact.company, MAX_LENGTH, stdin);

    contact.company[strcspn(contact.company, "\n")] = 0;

 

    printf("Enter phone number: ");

    fgets(contact.phone, MAX_LENGTH, stdin);

    contact.phone[strcspn(contact.phone, "\n")] = 0;

 

    fprintf(fp, "%s|%s|%s|%s\n", contact.firstName, contact.lastName, contact.company, contact.phone);

    fclose(fp);

    printf("Contact successfully added!\n");

}

 

// Function to show all contacts

void showContacts() {

    FILE *fp = fopen("phonebook.txt", "r");

    if (fp == NULL) {

        printf("Phonebook is empty or file does not exist!\n");

        return;

    }

 

    char line[200];

    int counter = 1;

    printf("\n=== Contact List ===\n");

    while (fgets(line, sizeof(line), fp) != NULL) {

        char firstName[MAX_LENGTH], lastName[MAX_LENGTH], company[MAX_LENGTH], phone[MAX_LENGTH];

        sscanf(line, "%[^|]|%[^|]|%[^|]|%s", firstName, lastName, company, phone);

        printf("%d. First Name: %s, Last Name: %s, Company: %s, Phone: %s\n",

               counter++, firstName, lastName, company, phone);

    }

    fclose(fp);

}

 

// Function to delete a contact

void deleteContact() {

    FILE *fp = fopen("phonebook.txt", "r");

    if (fp == NULL) {

        printf("Phonebook is empty or file does not exist!\n");

        return;

    }

 

    FILE *temp = fopen("temp.txt", "w");

    if (temp == NULL) {

        printf("Error creating temporary file!\n");

        fclose(fp);

        return;

    }

 

    int serialNumber;

    printf("Enter the serial number of the contact to delete: ");

    scanf("%d", &serialNumber);

    getchar(); // Clear buffer

 

    char line[200];

    int current = 1;

    int deleted = 0;

 

    while (fgets(line, sizeof(line), fp) != NULL) {

        if (current != serialNumber) {

            fputs(line, temp); // Copy all except the selected contact

        } else {

            deleted = 1;

        }

        current++;

    }

 

    fclose(fp);

    fclose(temp);

 

    remove("phonebook.txt");

    rename("temp.txt", "phonebook.txt");

 

    if (deleted) {

        printf("Contact successfully deleted!\n");

    } else {

        printf("Contact with that serial number not found!\n");

    }

}

 

// Function to edit contact details

void editContact() {

    FILE *fp = fopen("phonebook.txt", "r");

    if (fp == NULL) {

        printf("Phonebook is empty or file does not exist!\n");

        return;

    }

 

    FILE *temp = fopen("temp.txt", "w");

    if (temp == NULL) {

        printf("Error creating temporary file!\n");

        fclose(fp);

        return;

    }

 

    int serialNumber;

    printf("Enter the serial number of the contact to edit: ");

    scanf("%d", &serialNumber);

    getchar(); // Clear buffer

 

    char line[200];

    int current = 1;

    int edited = 0;

 

    while (fgets(line, sizeof(line), fp) != NULL) {

        if (current == serialNumber) {

            struct Contact newContact;

            printf("Enter new first name: ");

            fgets(newContact.firstName, MAX_LENGTH, stdin);

            newContact.firstName[strcspn(newContact.firstName, "\n")] = 0;

 

            printf("Enter new last name: ");

            fgets(newContact.lastName, MAX_LENGTH, stdin);

            newContact.lastName[strcspn(newContact.lastName, "\n")] = 0;

 

            printf("Enter new company: ");

            fgets(newContact.company, MAX_LENGTH, stdin);

            newContact.company[strcspn(newContact.company, "\n")] = 0;

 

            printf("Enter new phone number: ");

            fgets(newContact.phone, MAX_LENGTH, stdin);

            newContact.phone[strcspn(newContact.phone, "\n")] = 0;

 

            fprintf(temp, "%s|%s|%s|%s\n", newContact.firstName, newContact.lastName, newContact.company, newContact.phone);

            edited = 1;

        } else {

            fputs(line, temp); // Copy other contacts unchanged

        }

        current++;

    }

 

    fclose(fp);

    fclose(temp);

 

    remove("phonebook.txt");

    rename("temp.txt", "phonebook.txt");

 

    if (edited) {

        printf("Contact successfully edited!\n");

    } else {

        printf("Contact with that serial number not found!\n");

    }

}

 

int main() {

    int choice;

    while (1) {

        displayMenu();

        scanf("%d", &choice);

        getchar(); // Clear buffer after scanf

 

        switch (choice) {

            case 1:

                addContact();

                break;

            case 2:

                showContacts();

                break;

            case 3:

                deleteContact();

                break;

            case 4:

                editContact();

                break;

            case 5:

                printf("Thank you for using the phone book!\n");

                return 0;

            default:

                printf("Invalid option, try again!\n");

        }

    }

    return 0;

}

When you execute the given code, you will get similar following result.

manue@DESKTOP-E2QR9K9 MINGW64 /d/tutorials/c_tutorials/phonebook

$ gcc phonebook.c -o phonebook

 

manue@DESKTOP-E2QR9K9 MINGW64 /d/tutorials/c_tutorials/phonebook

$ ./phonebook

 

=== PHONE BOOK ===

1. Add new contact    

2. Show all contacts  

3. Delete contact     

4. Edit contact details

5. Exit

Choose an option: 1   

Enter first name: Manuel Radovanović

Enter last name: Radovanović

Enter company: MFS

Enter phone number: 123456789

Contact successfully added!

 

=== PHONE BOOK ===

1. Add new contact

2. Show all contacts

3. Delete contact

4. Edit contact details

5. Exit

Choose an option: 2

 

=== Contact List ===

1. First Name: Manuel Radovanovic, Last Name: Radovanovic, Company: MFS, Phone: 123456789

 

=== PHONE BOOK ===

1. Add new contact

2. Show all contacts

3. Delete contact

4. Edit contact details

5. Exit

Choose an option: 4

Enter the serial number of the contact to edit: 1

Enter new first name: Manuel

Enter new last name: Radovanović

Enter new company: MFS

Enter new phone number: 123456789

Contact successfully edited!

 

=== PHONE BOOK ===

1. Add new contact

2. Show all contacts

3. Delete contact

4. Edit contact details

5. Exit

Choose an option: 2

 

=== Contact List ===

1. First Name: Manuel, Last Name: Radovanovic, Company: MFS, Phone: 123456789

 

=== PHONE BOOK ===

1. Add new contact

2. Show all contacts

3. Delete contact

4. Edit contact details

5. Exit

Choose an option: 1

Enter first name: Hanna Smith  

Enter last name: Smith

Enter company: Taxi

Enter phone number: 987654321

Contact successfully added!

 

=== PHONE BOOK ===

1. Add new contact

2. Show all contacts

3. Delete contact

4. Edit contact details

5. Exit

Choose an option: 2

 

=== Contact List ===

1. First Name: Manuel, Last Name: Radovanovic, Company: MFS, Phone: 123456789

2. First Name: Hanna Smith, Last Name: Smith, Company: Taxi, Phone: 987654321

 

=== PHONE BOOK ===

1. Add new contact

2. Show all contacts

3. Delete contact

4. Edit contact details

5. Exit

Choose an option: 3

Enter the serial number of the contact to delete: 2

Contact successfully deleted!

 

=== PHONE BOOK ===

1. Add new contact

2. Show all contacts

3. Delete contact

4. Edit contact details

5. Exit

Choose an option: 5

Thank you for using the phone book!

You can also watch a video of how the program is coded.


C - Tutorial – 27. How to Work with Text Files in the C Programming Language, A Phonebook Example

Reading and Writing Binary Files in C Programming

Binary files are a type of file used to store data in a raw, machine-readable format, directly as that data is represented in computer memory. In the C programming language, working with binary files enables efficient storage and manipulation of data that doesn't need to be human-readable, unlike text files that are formatted as a sequence of characters. Binary files originated from the need for computer systems to efficiently store and transfer data in a format optimized for machine processing, not for human interpretation. In the early days of computing, data was often stored in text format because it facilitated program development and debugging, allowing programmers to easily read and modify files.

However, as applications became more complex, e.g., due to databases, multimedia files, or executable programs, the text format became inefficient due to size and the need for data conversion between memory form and readable form. Binary files evolved as a solution, so instead of translating data into characters, they are written directly as bytes representing the value in memory, such as a number in hexadecimal form. This enabled faster reading and writing, less space consumption, and support for complex data structures like arrays, structures, or images.

In the C programming language, binary files are supported through the standard library <stdio.h> with functions like fread() and fwrite(), which are designed to work with raw bytes instead of formatted text. Binary files are a powerful tool for working with data that requires speed and compactness, originating from the need for efficiency in computing. While text files serve for communication between humans and machines, binary files are optimized for communication between machines and programs, sacrificing readability for performance. Understanding this difference is crucial for choosing the right format depending on the application's needs, whether you are storing logs textually or serializing a data structure in binary. Open your terminal and type the following code.

manuel@manuel-virtual-machine:~$ sudo apt-get update

manuel@manuel-virtual-machine:~$ sudo apt-get upgrade

manuel@manuel-virtual-machine:~$ clear

manuel@manuel-virtual-machine:~$ ls

manuel@manuel-virtual-machine:~$ cd tutorials

manuel@manuel-virtual-machine:/tutorials$ ls

manuel@manuel-virtual-machine:/tutorials$ cd c_tutorial

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ ls

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ mkdir marathon_sign_up

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ cd marathon_sign_up

manuel@manuel-virtual-machine:/tutorials/c_tutorial/marathon_sign_up$ code .

Create a file and name it marathon.c, then type the following code.

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

#define MAX_NAME_LENGTH 50

 

// Structure for storing person data

struct Person {

    char name[MAX_NAME_LENGTH];

    int age;

    float height;

};

 

// Function to display the menu

void displayMenu() {

    printf("\n=== PEOPLE DATABASE (Binary File) ===\n");

    printf("1. Add new person\n");

    printf("2. Show all people\n");

    printf("3. Delete person\n");

    printf("4. Edit person details\n");

    printf("5. Exit\n");

    printf("Choose an option: ");

}

 

// Function to add a person

void addPerson() {

    struct Person person;

    FILE *fp = fopen("people.bin", "ab"); // Append in binary mode

    if (fp == NULL) {

        printf("Error opening file!\n");

        return;

    }

 

    printf("Enter name: ");

    fgets(person.name, MAX_NAME_LENGTH, stdin);

    person.name[strcspn(person.name, "\n")] = 0;

 

    printf("Enter age: ");

    scanf("%d", &person.age);

    getchar(); // Clear buffer

 

    printf("Enter height (in meters): ");

    scanf("%f", &person.height);

    getchar(); // Clear buffer

 

    fwrite(&person, sizeof(struct Person), 1, fp);

    fclose(fp);

    printf("Person successfully added!\n");

}

 

// Function to show all people

void showPeople() {

    FILE *fp = fopen("people.bin", "rb");

    if (fp == NULL) {

        printf("Database is empty or file does not exist!\n");

        return;

    }

 

    struct Person person;

    int counter = 1;

    printf("\n=== List of People ===\n");

    while (fread(&person, sizeof(struct Person), 1, fp) == 1) {

        printf("%d. Name: %s, Age: %d, Height: %.2f\n",

               counter++, person.name, person.age, person.height);

    }

    fclose(fp);

}

 

// Function to delete a person

void deletePerson() {

    FILE *fp = fopen("people.bin", "rb");

    if (fp == NULL) {

        printf("Database is empty or file does not exist!\n");

        return;

    }

 

    FILE *temp = fopen("temp.bin", "wb");

    if (temp == NULL) {

        printf("Error creating temporary file!\n");

        fclose(fp);

        return;

    }

 

    int serialNumber;

    printf("Enter the serial number of the person to delete: ");

    scanf("%d", &serialNumber);

    getchar(); // Clear buffer

 

    struct Person person;

    int current = 1;

    int deleted = 0;

 

    while (fread(&person, sizeof(struct Person), 1, fp) == 1) {

        if (current != serialNumber) {

            fwrite(&person, sizeof(struct Person), 1, temp); // Copy all except selected

        } else {

            deleted = 1;

        }

        current++;

    }

 

    fclose(fp);

    fclose(temp);

 

    remove("people.bin");

    rename("temp.bin", "people.bin");

 

    if (deleted) {

        printf("Person successfully deleted!\n");

    } else {

        printf("Person with that serial number not found!\n");

    }

}

 

// Function to edit person details

void editPerson() {

    FILE *fp = fopen("people.bin", "rb");

    if (fp == NULL) {

        printf("Database is empty or file does not exist!\n");

        return;

    }

 

    FILE *temp = fopen("temp.bin", "wb");

    if (temp == NULL) {

        printf("Error creating temporary file!\n");

        fclose(fp);

        return;

    }

 

    int serialNumber;

    printf("Enter the serial number of the person to edit: ");

    scanf("%d", &serialNumber);

    getchar(); // Clear buffer

 

    struct Person person;

    int current = 1;

    int edited = 0;

 

    while (fread(&person, sizeof(struct Person), 1, fp) == 1) {

        if (current == serialNumber) {

            struct Person newPerson;

            printf("Enter new name: ");

            fgets(newPerson.name, MAX_NAME_LENGTH, stdin);

            newPerson.name[strcspn(newPerson.name, "\n")] = 0;

 

            printf("Enter new age: ");

            scanf("%d", &newPerson.age);

            getchar(); // Clear buffer

 

            printf("Enter new height (in meters): ");

            scanf("%f", &newPerson.height);

            getchar(); // Clear buffer

 

            fwrite(&newPerson, sizeof(struct Person), 1, temp);

            edited = 1;

        } else {

            fwrite(&person, sizeof(struct Person), 1, temp); // Copy unchanged records

        }

        current++;

    }

 

    fclose(fp);

    fclose(temp);

 

    remove("people.bin");

    rename("temp.bin", "people.bin");

 

    if (edited) {

        printf("Person successfully edited!\n");

    } else {

        printf("Person with that serial number not found!\n");

    }

}

 

int main() {

    int choice;

    while (1) {

        displayMenu();

        scanf("%d", &choice);

        getchar(); // Clear buffer after scanf

 

        switch (choice) {

            case 1:

                addPerson();

                break;

            case 2:

                showPeople();

                break;

            case 3:

                deletePerson();

                break;

            case 4:

                editPerson();

                break;

            case 5:

                printf("Thank you for using the people database!\n");

                return 0;

            default:

                printf("Invalid option, try again!\n");

        }

    }

    return 0;

}

When you execute the given code, you will get similar following result.

manue@DESKTOP-E2QR9K9 MINGW64 /d/tutorials/c_tutorials/marathon_sign_up

$ gcc marathon.c -o marathon

 

manue@DESKTOP-E2QR9K9 MINGW64 /d/tutorials/c_tutorials/marathon_sign_up

$ ./marathon

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person    

2. Show all people   

3. Delete person     

4. Edit person details

 

manue@DESKTOP-E2QR9K9 MINGW64 /d/tutorials/c_tutorials/marathon_sign_up

$ ./marathon

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person    

2. Show all people   

3. Delete person     

4. Edit person details

5. Exit

Choose an option: 1  

Enter name: Manuell Radovanovic

Enter age: 49

Enter height (in meters): 1.88

Person successfully added!

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person

2. Show all people

3. Delete person

4. Edit person details

5. Exit

Choose an option: 2

 

=== List of People ===

1. Name: Manuell Radovanovic, Age: 49, Height: 1.88

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person

2. Show all people

3. Delete person

4. Edit person details

5. Exit

Choose an option: 4

Enter the serial number of the person to edit: 1

Enter new name: Manuel Radovanovic

Enter new age: 49

Enter new height (in meters): 1.88

Person successfully edited!

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person

2. Show all people

3. Delete person

4. Edit person details

5. Exit

Choose an option: 2

 

=== List of People ===

1. Name: Manuel Radovanovic, Age: 49, Height: 1.88

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person

2. Show all people

3. Delete person

4. Edit person details

5. Exit

Choose an option: 1

Enter name: Rebecca Smith

Enter age: 27

Enter height (in meters): 1.79

Person successfully added!

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person

2. Show all people

3. Delete person

4. Edit person details

5. Exit

Choose an option: 2

 

=== List of People ===

1. Name: Manuel Radovanovic, Age: 49, Height: 1.88

2. Name: Rebecca Smith, Age: 27, Height: 1.79

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person

2. Show all people

3. Delete person

4. Edit person details

5. Exit

Choose an option: 3

Enter the serial number of the person to delete: 2

Person successfully deleted!

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person

2. Show all people

3. Delete person

4. Edit person details

5. Exit

Choose an option: 2

 

=== List of People ===

1. Name: Manuel Radovanovic, Age: 49, Height: 1.88

 

=== PEOPLE DATABASE (Binary File) ===

1. Add new person

2. Show all people

3. Delete person

4. Edit person details

5. Exit

Choose an option: 5

Thank you for using the people database!

You can also watch a video of how the program is coded.


C Tutorial – 28. How to Work with Binary Files in the C, A Marathon Sign Up Program Example

Basics of Dynamic Linking: The Role of .dll and .so Libraries in C Programming

DLL - Dynamic-Link Library files are libraries that contain functions and resources that can be shared between multiple programs in the Windows operating system. In the C programming language, DLL libraries enable code modularity and the reuse of functionality without the need to include the entire source code in each application. To create a DLL library for your C programs, certain knowledge is required, which can be outlined in three steps:

Writing code for the DLL:

A C file is created that contains the functions we want to expose to other programs.

Function declaration with __declspec(dllexport):

Functions that we want to be externally accessible must be marked __declspec(dllexport).

Compiling into a DLL file:

A compiler like MinGW (gcc) or MSVC (cl) is used.

To understand how a DLL library is created and used in your C programs, it is best to review on one the simplest example. Please note that DLL libraries are used exclusively for the Windows environment and will not work on Linux operating systems. Switch to the Windows environment, launch Visual Studio Code, and create a new project. Name it 'hello'. Create a file named hello.c, which we will use to generate a DLL library, and enter the following simple C code.

#include <stdio.h>

__declspec(dllexport) void hello() {

    printf("Hello from DLL!\n");

}

In Visual Studio Code, open the terminal panel with Command Prompt and execute the following commands to create the hello.dll file. 

D:\tutorials\c_tutorials\hello>gcc -c hello.c -o hello.o

D:\tutorials\c_tutorials\hello>gcc -shared -o hello.dll hello.o

Once you have created the .dll file, you can then create main.c, the main file that will use the created library. Enter the following C code into the main.c file.

#include <windows.h>

#include <stdio.h>

 

typedef void (*HelloFunc)(); // Defining the function type

 

int main() {

    HINSTANCE hDLL = LoadLibrary("hello.dll"); // Loading the DLL

    if (hDLL == NULL) {

        printf("Cannot load DLL!\n");

        return 1;

 

    }

 

    HelloFunc hello = (HelloFunc)GetProcAddress(hDLL, "hello"); // Retrieving the function address

    // Retrieving the function address

    if (hello == NULL) {

        printf("Cannot find the function!\n");

        FreeLibrary(hDLL);

        return 1;

 

    }

   

    hello(); // Calling the function from the DLL

    FreeLibrary(hDLL); // Releasing the DLL

    return 0;

}

When you execute the given code, you will get following result.

D:\tutorials\c_tutorials\hello>gcc main.c -o main.exe

D:\tutorials\c_tutorials\hello>main.exe

Hello from DLL!

You can also watch a video of how the program is coded.


C Tutorial – 29. How to Create A .DLL Library in the C Programming Language on Windows?

Unlike .dll libraries, .so - shared objects are dynamic libraries used on Unix-based operating systems, such as Linux and macOS. They serve to share code between multiple programs during execution, similar to how .dll files work on the Windows operating system. They enable modularity, reduce the size of executable files, and facilitate the updating of common functionalities without recompiling the entire program. .so libraries evolved alongside Unix systems. Their origin can be traced back to the early days of Unix in the 1970s, when programmers wanted a more efficient way to share code between processes.

The concept of dynamic libraries became more standardized with the development of System V Unix in the 1980s, and they were later refined in modern systems like Linux, which originated in 1991. On Linux, .so files are part of the ELF - Executable and Linkable Format standard, which defines how executable files and libraries are organized. This was a response to the need for flexibility and resource optimization on Unix systems, where previously only static libraries .a files existed. Although .so and .dll serve a similar purpose, dynamic linking of code, there are key differences due to the platforms they operate on. Open your terminal and type the following code.

manuel@manuel-virtual-machine:~$ sudo apt-get update

manuel@manuel-virtual-machine:~$ sudo apt-get upgrade

manuel@manuel-virtual-machine:~$ clear

manuel@manuel-virtual-machine:~$ ls

manuel@manuel-virtual-machine:~$ cd tutorials

manuel@manuel-virtual-machine:/tutorials$ ls

manuel@manuel-virtual-machine:/tutorials$ cd c_tutorial

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ ls

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ mkdir library

manuel@manuel-virtual-machine:/tutorials/c_tutorial$ cd library

manuel@manuel-virtual-machine:/tutorials/c_tutorial/library$ code .

Create a file and name it mathlib.c, then type the following code.

#include <stdio.h> 

// Function for addition

int add(int a, int b) {

    return a + b;

}

 

// Function for subtraction

int subtract(int a, int b) {

    return a - b;

}

 

// Optional function to display library info

void printInfo() {

    printf("Math Library: Simple arithmetic operations\n");

}

Create a file and name it library.c, then type the following code.

#include <stdio.h>

#include <stdlib.h>

#include <dlfcn.h> // For dynamic library loading

 

int main() {

    // Pointer to the library

    void *libHandle;

 

    // Function type definitions from the library

    typedef int (*ArithmeticFunc)(int, int);

    typedef void (*PrintFunc)();

 

    // Load the library

    libHandle = dlopen("./libmathlib.so", RTLD_LAZY);

    if (!libHandle) {

        fprintf(stderr, "Error loading library: %s\n", dlerror());

        return 1;

    }

 

    // Clear any previous errors

    dlerror();

 

    // Retrieve functions from the library

    ArithmeticFunc add = (ArithmeticFunc)dlsym(libHandle, "add");

    char *error = dlerror();

    if (error != NULL) {

        fprintf(stderr, "Error finding 'add': %s\n", error);

        dlclose(libHandle);

        return 1;

    }

 

    ArithmeticFunc subtract = (ArithmeticFunc)dlsym(libHandle, "subtract");

    error = dlerror();

    if (error != NULL) {

        fprintf(stderr, "Error finding 'subtract': %s\n", error);

        dlclose(libHandle);

        return 1;

    }

 

    PrintFunc printInfo = (PrintFunc)dlsym(libHandle, "printInfo");

    error = dlerror();

    if (error != NULL) {

        fprintf(stderr, "Error finding 'printInfo': %s\n", error);

        dlclose(libHandle);

        return 1;

    }

 

    // Use the functions

    printInfo();

    printf("Addition: 5 + 3 = %d\n", add(5, 3));

    printf("Subtraction: 10 - 4 = %d\n", subtract(10, 4));

 

    // Close the library

    dlclose(libHandle);

    return 0;

}

When you compile and execute the given code, you will get similar following result.

manuel@manuel:~/tutorials/c_tutorial/library$ gcc -fPIC -c mathlib.c -o mathlib.o 

manuel@manuel:~/tutorials/c_tutorial/library$ gcc -shared -o libmathlib.so mathlib.o 

manuel@manuel:~/tutorials/c_tutorial/library$ gcc library.c -o mathprogram -ldl 

manuel@manuel:~/tutorials/c_tutorial/library$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

manuel@manuel:~/tutorials/c_tutorial/library$ ./mathprogram 

manuel@manuel:~/tutorials/c_tutorial/library$ ./mathprogram

Math Library: Simple arithmetic operations

Addition: 5 + 3 = 8

Subtraction: 10 - 4 = 6

manuel@manuel:~/tutorials/c_tutorial/library$

You can also watch a video of how the program is coded.


C Tutorial – 30. How to Create A .so Library in the C Programming Languag

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

No comments:

Post a Comment