zoukankan      html  css  js  c++  java
  • C++---初识《通过g++ / makefile 编译和调用动态库so文件》(ubuntu)

    C++---初识《通过g++ / makefile  编译和调用动态库so文件》(ubuntu)

    ------------------------目录-----------------------------

    一、通过makefile  编译和调用动态库so文件

    二、通过makefile  编译和调用动态库so文件

    -------------------------正文----------------------------

    一、通过makefile  编译和调用动态库so文件

     1、动态库的编译
      举例,这里有一个头文件:test.h,三个.c文件:test_a.c、test_b.c、test_c.c,这几个文件编译成一个动态库:libtest.so。

    文件test.h:
    
    #include   "stdio.h"
    void test_a();
    void test_b();
    void test_c();
    文件test_a.c:
    
    #include "test.h"
    void test_a()
    {
      printf("this is in test_a...
    ");
    }
    文件test_b.c:
    
    #include "test.h"
    void test_b()
    {
      printf("this is in test_b...
    ");
    }
    文件test_c.c:
    
    #include "test.h"
    void test_c()
    {
        printf("this is in test_c...
    ");
    }

    将这几个文件编译成一个动态库:libtest.so
     $ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so


    2、动态库的链接
      在1、中,已经成功生成了一个自己的动态链接库libtest.so,下面通过一个程序来调用这个库里的函数。程序的源文件为:test.c。

    test.c:
    
    #include "test.h"
    
    int main()
    {
      test_a();
      test_b();
      test_c();
      return 0;
    }

    将test.c与动态库libtest.so链接生成执行文件test:
     $   gcc test.c -L. -ltest -o test

    测试是否动态连接,如果列出libtest.so,那么应该是连接正常了:
     $   ldd test

    执行:
     $  ./test        #可以看到它是如何调用动态库中的函数的。

    遇到问题:
    u@u1604:~/C_learn/makefile_so$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so u@u1604:~/C_learn/makefile_so$ gcc test.c -L. -ltest -o test u@u1604:~/C_learn/makefile_so$ ldd test linux-vdso.so.1 => (0x00007ffc096bf000) libtest.so => not found libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2e43587000) /lib64/ld-linux-x86-64.so.2 (0x00007f2e43951000)

    解决方式一:
    u@u1604:~/C_learn/makefile_so$ sudo cp libtest.so /lib # libtest.so复制到/usr/lib下 # 删除命令 : sudo rm /lib/libtest.so
    [sudo] u 的密码:
    u@u1604:~/C_learn/makefile_so$ gcc test.c -L. -ltest -o test
    u@u1604:~/C_learn/makefile_so$ ldd test
        linux-vdso.so.1 =>  (0x00007ffd96947000)
        libtest.so => /lib/libtest.so (0x00007f07a2820000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f07a2456000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f07a2a22000)

    成功:
    u@u1604:~/C_learn/makefile_so$ ./test
    this is in test_a...
    this is in test_b...
    this is in test_c..


    二、通过makefile  编译和调用动态库so文件

     

    文件../hello/hello.c
    
    #include "hello.h"
    
    void hello()
    {
        printf("Hello .....
    ");
    }
    文件../hello/hello.h
    
    #ifndef _HEAD_H
    #define _HEAD_H
    #include <stdio.h>
    
    void hello();
    
    #endif
    文件../hello/Makefile

    CC = gcc OBJS = $(wildcard *.c) TARGET = libhello.so all:   $(CC) $(OBJS) -fPIC -shared -o $(TARGET)   sudo mv ./$(TARGET) /lib
    clean:   rm $(SRCS) $(headfile)

    【解释】主要命令: gcc -hello.c -fPIC -shared -o libhello.so,
    这里生成的libhello.so并不是在系统 /lib目录下的,所以将.so文件移动到系统/lib里去
    文件 test.c
    
    #include "test.h"
    
    #include <sys/types.h>  
    #include <sys/wait.h>
    
    int main()
    {
        hello();
        return 0;
    
    }
    文件 test.h
    
    #ifndef _HEAD_H
    #define _HEAD_H
    #include <stdio.h>
    
    #endif
    文件 makefile

    CC = gcc OBJS = $(wildcard *.c) TARGET = test all: cd ./hello; make $(CC) $(OBJS) -L/lib -lhello -o $(TARGET) clean: rm -rf *o $(TARGET) cd ./hello; make clean

    【解释】注意这里的makefile,既make此目录下的,还要进去子目录hello里去make,
    所以首先进去子目录cd ./hello;make,然后要连接libhello.so,
    主要是 gcc test.c -L/lib -lhello -o test,记得要清除.o 和.so文件
    结果
    u@u1604:~/C_learn/makefile_so$ make cd ./hello; make make[1]: Entering directory '/home/u/C_learn/makefile_so/hello' gcc hello.c -fPIC -shared -o libhello.so sudo mv ./libhello.so /lib [sudo] u 的密码: make[1]: Leaving directory '/home/u/C_learn/makefile_so/hello' gcc test.c -L/lib -lhello -o test test.c: In function ‘main’: test.c:8:5: warning: implicit declaration of function ‘hello’ [-Wimplicit-function-declaration] hello(); ^ u@u1604:~/C_learn/makefile_so$ ./test Hello .....

    问题:

    如果在打印出现的信息中,发现有一行: libtest.so => not found
    则表明链接程序找不到我们的libtest.so文件哦,为什么呢?因为链接程序只寻找固定目录,例如/lib目录。
    如果我们的当前目录是诸如/home/u/a/b/c这种目录,那么人家是不会主动了解到的。
    怎么办?办法一:把libtest.so拷贝到链接程序的搜索路径目录下。 办法二:设置环境变量LD_LIBRARY_PATH,增加当前路径到该变量中。
    看看现在LD_LIBRARY_PATH有什么内容吧?
    1、执行 echo $LD_LIBRARY_PATH 就打印出来。 2、配置环境变量的方法简单点就是: LD_LIBRARY_PATH=LD_LIBRARY_PATH:"/root/nana/so" export LD_LIBRARY_PATH 3、好了,再次执行ldd就有新发现了。 4、执行./***, OK,输出正常。

      " 办法二:设置环境变量LD_LIBRARY_PATH,增加当前路径到该变量中。 "尝试设置环境路径了,可能没对,几经折腾还没编译通过。回头编译通过,再来记录。

      今天收获了,g++  ---->   makefile  ----->  cmake  linux下学习C++编译的三层境界的思维,前者是后者思维的基础,后者是前者进一步提升编程效率的优化。学会三者,是在linux下学习c++必会的技能,后面再学习如何写makelist.txt。

  • 相关阅读:
    递归与尾递归(C语言)
    超酷算法:Levenshtein自动机
    编程面试的10大算法概念汇总
    C 语言中的指针和内存泄漏
    计算机实际上是如何工作的
    超酷算法:同型哈希
    4个Linux服务器监控工具
    2015-3-23
    2015-3-20
    2015-3-19
  • 原文地址:https://www.cnblogs.com/carle-09/p/11343002.html
Copyright © 2011-2022 走看看