C Compile: Dynamic Connection library (. so file) (go to)

Source: Internet
Author: User

Vamei Source: Http://www.cnblogs.com/vamei Welcome reprint, Please also keep this statement. Thank you!

In "on paper: Algorithms and data Structures", I have a C program in each article that implements algorithms and data structures (such as stacks and related operations). In the same program, there are main () functions for testing, struct definitions, function prototypes, TypeDef, and so on.

Such a practice is not "environmentally friendly". The actual application of the algorithm and the implementation of the algorithm are mixed together. If I want to reuse the previous source program, I have to make a lot of changes and recompile it. The best solution is to implement modularity: Just keep the pure algorithm implementation, detach the header file, and compile a library. Each time you need to use the library (such as using the stack data structure), in the program include header files, connection library. This way, you do not need to change the source program every time.

I'm here to show you how to create a shared library in a UNIX environment. Under UNIX, the shared library is suffixed with so (Shared object). A shared library is similar to a DLL under Windows, and is dynamically connected while the program is running. Multiple processes can connect to the same shared library.

Shared libraries

This article uses the Ubuntu test, using GCC as the compiler.

Program cleanup

The following program comes from an armchair: stack, which is the C implementation of the stack data structure:

/* by Vamei *//* with single-linked list to implement stack */#include <stdio.h> #include <stdlib.h>typedef stru CT node *position;typedef int elementtp;//point to the head node of the listtypedef struct node *stack;    struct Node {elementtp element; Position next;}; Stack init_stack (void); void Delete_stack (Stack); Elementtp Top (stack), void push (Stack, elementtp);    Elementtp pop (stack), int is_null (stack), void main (void) {elementtp A;    int i;    STACK SK;    SK = Init_stack ();    Push (SK, 1);    Push (SK, 2);    Push (SK, 8); printf ("Stack is null"?    %d\n ", Is_null (SK));        for (i=0; i<3; i++) {a = pop (SK);    printf ("Pop:%d\n", a); } printf ("Stack is null"?        %d\n ", Is_null (SK)); Delete_stack (SK);} /* * Initiate the stack * malloc the head node.    * Head node doesn ' t store valid data * Head->next is the top node */stack init_stack (void) {position NP;    STACK SK;    NP = (position) malloc (sizeof (struct node));  Np->next = NULL;Sk->next is the top node SK = NP; Return SK;} /* Pop out all elements * and then delete the head node */void delete_stack (Stack sk) {while (!is_null (SK)) {pop (SK    ); } free (SK);} /* View the top frame */elementtp top (STACK SK) {return (sk->next->element);}    /* * Push a value into the stack */void push (Stack sk, elementtp value) {position NP, oldtop;        OldTop = sk->next;    NP = (position) malloc (sizeof (struct node));    Np->element = value;    Np->next = sk->next; Sk->next = NP;    }/* * Pop out the top value */elementtp pop (STACK sk) {elementtp element;    Position top, Newtop;        if (Is_null (SK)) {printf ("Pop () on an empty stack");    Exit (1);        } else {top = sk->next;             element = top->element;        Newtop = top->next;        Sk->next = Newtop;        Free (top);    return element; }}/* Check whether a stack is Empty*/int is_null (Stack sk) {returN (sk->next = = NULL);} 

The main () section above is for testing, not a function module, and should be removed when creating a library.

Some statements in the program will be reused. Like what:

typedef struct NODE *position;typedef int elementtp;//Point to the  head node of the listtypedef struct node *stack; s Truct Node {    elementtp element;    Position next;}; Stack init_stack (void); void Delete_stack (Stack); Elementtp Top (stack), void push (Stack, elementtp); Elementtp pop (stack); int is_null (stack);

This section of the program declares a number of structures and pointers, as well as function prototypes for stack operations. When we call Kushi in other programs (such as creating a stack, or performing a pop operation), we also need to write these declarations. We save these declarations needed in the actual call to a header file, Mystack.h. In a program that is actually called, you can simply include the header file, avoiding the hassle of writing these statement statements every time.

After cleaning the C program for MYSTACK.C:

/* by Vamei *//* with single-linked list to implement stack */#include <stdio.h> #include <stdlib.h>
#include "Mystack.h"


/* * Initiate the stack * malloc the head node. * Head node doesn ' t store valid data * Head->next is the top node */stack init_stack (void) {position NP; STACK SK; NP = (position) malloc (sizeof (struct node)); Np->next = NULL; Sk->next is the top node SK = NP; Return SK;} /* Pop out all elements * and then delete the head node */void delete_stack (Stack sk) {while (!is_null (SK)) {pop (SK ); } free (SK);} /* View the top frame */elementtp top (STACK SK) {return (sk->next->element);} /* * Push a value into the stack */void push (Stack sk, elementtp value) {position NP, oldtop; OldTop = sk->next; NP = (position) malloc (sizeof (struct node)); Np->element = value; Np->next = sk->next; Sk->next = NP; }/* * Pop out the top value */elementtp pop (STACK sk) {elementtp element; Position top, Newtop; if (Is_null (SK)) {printf ("Pop () on an empty stack"); Exit (1); } else{top = sk->next; element = top->element; Newtop = top->next; Sk->next = Newtop; Free (top); return element; }}/* Check whether a stack is Empty*/int is_null (Stack sk) {return (Sk->next = = null);}

#include "..."; The statement will first look for the appropriate file in the working directory. If you use GCC, the-i option is added and will be found in the path provided by-I.

making. So files

Our goal is to create a shared library, the. so file.

First, compile the STACK.C:

$GCC-C-fpic-o MYSTACK.O mystack.c

-C means only compilation (compile), not connection. The-o option is used to describe the output file name. GCC will generate a target (object) file MYSTACK.O.

Note the-fpic option. Pic refers to position independent Code. This option is required for shared libraries to enable dynamic connectivity (linking).

To build a shared library:

$GCC-shared-o libmystack.so MYSTACK.O

The library file starts with Lib. The shared library file is suffixed with. So. -shared indicates that a shared library is generated.

In this way, the shared library is complete.. so files and. h files are all located in the current working path (.).

Working with shared libraries

We write a test.c to actually invoke the shared library:

#include <stdio.h> #include "mystack.h"
/*
* Call functions in Mystack Library
*/void Main (void) { elementtp A; int i; STACK SK; SK = Init_stack (); Push (SK, 1); Push (SK, 2); Push (SK, 8); printf ("Stack is null"? %d\n ", Is_null (SK)); for (i=0; i<3; i++) { a = pop (SK); printf ("Pop:%d\n", a); } printf ("Stack is null"? %d\n ", Is_null (SK)); Delete_stack (SK);}

Note that we include mystack.h at the beginning of the program.

Compile the above program. The compiler needs to know the. h file location.

    • For the # include "...", the compiler will search for the. h file in the current path. You can also use the-I option to provide additional search paths, such as-i/home/vamei/test.
    • For # include <...>, the compiler looks in the default include search path.

The compiler also needs to know which library file we used in GCC:

    • Use the-l option to describe the name of the library file. Here, we will use-lmystack (that is, the Libmystack library file).
    • Use the-l option to describe the path where the library file resides. Here, we use-L. (That is, the. path).

If the-l option is not provided, GCC will look in the default library file search path.

You can use the following command to learn about the include default search path on your computer:

$ ' gcc-print-prog-name=cc1 '-V

Learn the library default search path:

$GCC-print-search-dirs

The. h and. So files that we need are all in the current path, so compile with the following command:

$GCC-O test test.c-lmystack-l.

The test executable file will be generated.

Use

$./test

Execute the program

Run the program

Although we have successfully compiled the test executable, it is very likely that it will not execute. One might be a permissions issue. We need to have permission to execute this file, see Linux file Management background knowledge

Another situation is:

./test:error while loading shared libraries:libmystack.so:cannot open Shared object file:no such file or directory

This is because the operating system cannot find the library. Libmystack.so is located in the current path, outside the default path of the library file. Although we provided the location of the. So file at compile time (compile), this information was not written to the test executable (runtime). You can use the following command to test:

$LDD Test

The LDD is used to display the library on which the executable file depends. Show:

    Linux-vdso.so.1 =  (0x00007fff31dff000)    libmystack.so = not found    libc.so.6 =/lib/x86_64- Linux-gnu/libc.so.6 (0x00007fca30de7000)    /lib64/ld-linux-x86-64.so.2 (0x00007fca311cb000)

This means that the test executable cannot find the libmystack.so library file it needs.

In order to solve the above problem, we can put the. so file in the default search path. But sometimes, especially in multi-user environments, we don't have permission to write on the default search path.

One solution is to set the ld_library_path environment variable. For example:

$export ld_library_path=.

This way, when the executable executes, the operating system will search for the library file under Ld_library_path and then to the default path. The downside of an environment variable is that it affects all the executable programs. If we are not careful when compiling other programs, it is likely that other executables will not run. Therefore,ld_library_path environment variables are used for testing.

Another solution, which is to provide the-rpath option, is to write the search path information to the test file (Rpath represents the runtime path). This makes it unnecessary to set environment variables. The downside to this is that if the library file is moved, we need to recompile test. Compile the test.c using the following command:

$GCC-G-O test test.c-lmystack-l.-wl,-rpath=.

-WL indicates that the-rpath option is passed to the connector (linker).

Test successful execution results in:

Stack is null? 0pop:8pop:2pop:1stack is null? 1

C Compile: Dynamic Connection library (. so file) (go to)

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.