精华内容
下载资源
问答
  • 1、.h头文件是编译时必须的,lib是链接时...静态链接就好比一个电视机,你不知道电视机内部的具体结构是怎样的 头文件就好比一个电视机遥控器,提供接口,让你可以使用 故而源程序中要想使用,就必须包含该

    1、.h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的。

    头文件,是文本文件,通常只是用来【声明】常量、自定义类型、函数
    
    静态链接库,是经过编译生成的二进制文件,具体【定义】是不可见的
    
    打个比方:
    静态链接库就好比一个电视机,你不知道电视机内部的具体结构是怎样的
    头文件就好比一个电视机遥控器,提供接口,让你可以使用库

    故而源程序中要想使用库,就必须包含该库的头文件;即,要想使用电视(库文件),就必须要有该电视的遥控器(接口,即头文件)

     

    但是在使用时,不仅要包含lib库文件,还是要包含相应的头文件。

    例如:要是用printf(),就应该在源程序中包含#include <stdio.h>一样。

     

    2、静态链接库不同于动态链接库(*.dll),

    静态库情况下,函数和数据被编译进一个二进制文件(通常扩展名为*.LIB),
    Visual C++的编译器在链接过程中将从静态库中恢复这些函数和数据并把他们和应用程序中的其他模块组合在一起生成可执行文件
    格式如:#pragma comment(lib,"XXX.lib")
    这个过程称为"静态链接",此时因为应用程序所需的全部内容都是从库中复制了出来,
    所以静态库本身并不需要与可执行文件一起发行。

    3、linux下的静态链接库

    linux下的静态链接库是*.a文件,与动态链接库.so对应。
    linux下.a文件,如果编写了入口函数,也可以直接执行

     

    4、静态链接库与动态链接库都是共享代码的方式

    如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。

    但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。

     

    静态链接库和动态链接库的另外一个区别在于:

    静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。

     

    5、“每一个lib文件就是若干函数(假设只有函数)的定义”
    lib库有两种,一种是包含了函数所在DLL文件和文件中函数位置的信息,称为导出库;

    一种是包含函数代码本身,一般现有的DLL,用的是前一种库;

    以前在DOS下的TC/BC等,是后一种库。包含函数原型声明的,是头文件(.h)。



    “通过#include包含这些函数声明的头文件后,我们的应用程序就可以使用lib文件中的函数”

    指定编译器链接相应的库文件

    在IDE环境下,一般是一次指定所有用到的库文件,编译器自己寻找每个模块需要的库;

    在命令行编译环境下,需要指定每个模块调用的库。

    6、“那他和直接给出那个函数定义的文件,比如.cpp文件,和头文件有什么区别,静态链接库有什么用”
    cpp文件是源代码,库文件是编译后的二进制代码,比如你可以调用Windows的API,但是不能看到其源代码一样

    “还有不明白的是,静态链接库中的lib文件只要用到,则整个lib文件的内容都放进了exe文件中,那它是被编译进去还是链接的时候连接进去的呢?”
    在链接的时候将lib链接到目标代码中。


     

    7、静态链接库(Lib)
    在VC++6.0中new一个名称为libTest的static library工程

    并新建lib.h和lib.cpp两个文件,lib.h和lib.cpp的源代码如下:

    //文件:lib.h
    #ifndef LIB_H
    #define LIB_H
    extern "C" int add(int x,int y);   //声明为C编译、连接方式的外部函数,意思就是add()函数要用c编译器来编译,它在其它的.cpp源文件中定义。
    #endif


    //文件:lib.cpp
    #include "lib.h"
    int add(int x,int y)
    {
    return x + y;
    }


      编译这个工程就得到了一个.lib文件,这个文件就是一个函数库,它提供了add的功能。

           将头文件和.lib文件提交给用户后,用户就可以直接使用其中的add函数了。(注意提交的是.h头文件和.lib文件,二者都要给,而不是仅仅提供.lib文件)

    标准Turbo C2.0中的C库函数(我们用来的scanf、printf、memcpy、strcpy等)就来自这种静态库

     

    但是在使用时,不仅要包含lib库文件,还是要包含相应的头文件。

    例如:要是用printf(),就应该在源程序中包含#include <stdio.h>一样。

     

     

    8、下面来看看怎么使用这个库,在libTest工程所在的工作区内new一个libCall工程。

    libCall工程仅包含一个main.cpp文件,它演示了静态链接库的调用方法,

    其源代码如下:

    #include <stdio.h>
    #include "..\lib.h"//不可丢失 ,头文件不可丢
    #pragma comment( lib, "..\\debug\\libTest.lib" )  //指定与静态库一起连接
    int main(int argc, char* argv[])
    {
    printf( "2 + 3 = %d", add( 2, 3 ) );
    }


      静态链接库的调用就是这么简单,或许我们每天都在用,可是我们没有明白这个概念。

           代码中#pragma comment( lib , "..\\debug\\libTest.lib" )的意思是指本文件(即main.cpp)生成的.obj文件应与libTest.lib一起连接



      

    展开全文
  • 文章目录问题来源我的问题头文件、库文件动态链接库头文件.h库文件.lib动态链接库.dll三者的关系静态链接动态链接初识 Fortran 预处理包含文件 includeFortran中function简单使用声明interface调用function声明...

    问题来源

    课题需要用Ansys做拓扑优化计算,有限元计算部分可以用APDL直接进行,而优化部分需要从ANSYS提取结构刚度矩阵等数据进行计算。ANSYS给出的是数据接口是用Fortran写的,因此课题组一直都是用APDL + Fortran进行计算。
      之前用的环境是vs 2005 + ivf,有点太老了用着不太舒服所以折腾了快一个礼拜搞了vs2017 + Intel 2019全家桶和VSCode + gfortran + lapack两套开发环境。(为了方便实验室的师弟师妹,已经做了两套教程,后面陆续会补上。这不是重点
      在折腾的过程中遇到了一点关于库函数的问题问题,让我对自己已有的对程序库函数还有头文件的理解产生了怀疑,因此专门去网上查了头文件(.h)、库文件(.lib)、和动态链接库文件(.dll)的关系。

    我的问题

    上网翻了一些资料,发现我对对头文件、库函数和动态连接库的理解没有大问题。理清思路之后,发现困扰我的其实是下面两个问题。

    • Fortran中的对包含文件 include(头文件)的预处理
    • Fortran中自定义函数的(声明)使用方式

    为了防止以后时间长了又忘记了,将查阅内容总结如下:

    1. 头文件、库文件和动态链接库
    2. 初识 Fortran 预处理
    3. Fortran中function的简单使用

    头文件、库文件和动态链接库

    参考了博客园CSDN的这两篇帖子。对每种文件依次回答如下问题:这个文件

    • 是什么?
    • 有什么作用?
    • 什么时候需要?
    • 在哪里存放?

    头文件.h

    头文件作为一种包含功能函数、数据接口声明的载体文件,主要用于保存 函数的声明。.h头文件是 编译时必须的。C\C++标准库头文件一般都存放在 /include目录下。

    库文件.lib

    lib库是一种可执行代码的二进制形式,是别人已经写好、适用成熟、在遵守相关协议下可以复用被操作系统载入内存中执行的代码。 lib库文件存放 函数的定义(实现),是 链接时需要的。库文件一般存放在 /lib文件下。
      lib库文件分为静态库和动态链接库(.dll)的导入库。

    动态链接库.dll

    dll库文件存放的是 函数可执行代码,一般在 /bin/lib文件夹下。动态库dll是程序 运行时需要的。

    三者的关系

    简单来说,库文件通过头文件向外导出接口,用户通过头文件找到库文件中需要的函数实现代码进行链接至程序当中。不理解不用纠结,先往下看。

    静态链接

    静态链接用到的lib库文件叫做 静态链接库
      简而言之,静态连接就是头文件告诉编译器要用到的函数是什么样子,然后编译器去lib文件里将程序运行时用到的指令和数据找出来,并将它们从lib中复制出来全部打包到可执行程序exe中。
      运行程序时将它们提取出来装入内存中,使得程序可以顺利运行,因此程序运行的时候不再需要其它的库文件。这种方式虽然简单但是粗暴,不仅使得exe程序很臃肿而且极大程度的浪费内存空间。

    动态链接

    动态链接用到的lib库文件叫做 动态链接库导入库,dll库叫做 动态链接库
      针对静态链接的缺点,动态链接将exe运行时需要的数据和指令的具体内容存在dll中,exe本身并不储存这些数据。在运行的时候,exe再将它们从dll中提取出来,这样exe程序就不会很臃肿。
      虽然h头文件告诉了程序要用的函数是什么样子,但是程序怎么直到到底在哪个dll中找到所需的函数指令和数据呢?这就是导入库lib的作用了。
      lib将接口操作和数据(用什么方法,从哪个dll库,(库中)什么地方调用所需函数和数据)告诉编译器并将它们放在exe中。程序运行时找到对应的dll库,将所需的内容提取出来。因此IDE设置时附加依赖项的是lib不是dll,dll是动态链接程序运行时必须的。
      不同的程序可以从同一个dll中提取所需指令和数据,因此dll也叫共享库。对于大型项目,动态链接可以极大的节约空间,减小版本迭代时发布程序的体量。

    初识 Fortran 预处理

    这一节主要参考了这篇博客,摘录原文如下:

    预处理在Fortran语法中并未规定,但绝大多数编译器做了相应扩充。本文介绍了部分编译器环境下的Fortran预处理语句,例如宏定义、包含语句、条件编译等。
      预处理,是编译器在 编译之前,对源代码进行的一些“替换”、“选择” 等操作。它对于代码的宏观控制、维护、跨平台等都有很好的作用。
    > 注意,预处理只是简单的对源代码文件进行替换,与 Fortran 的语法并没有直接关系。预处理的结果,才是真正的 Fortran 源代码,并交给编译器编译成二进制的目标代码。这个过程大概如下图:
    在这里插入图片描述
      然而,Fortran 语法中,并没有规定任何预处理的内容。因此,一部分编译器扩充了自己的预处理语句,也有一些编译器使用了现成的 C 语言的预处理器,于是继承了 C 语言预处理的写法。
      本文会介绍一部分的预处理语句,但并不能保证他们能在读者的编译器上使用。请读者 阅读自己使用的编译器帮助文档,以便了解该编译器支持的预处理语句和使用方法。

    包含文件 include

    包含文件被大量应用在 C 语言头文件中。但 Fortran 本身并不需要子程序的原型,函数也使用(interface接口)而不是原型。module 用 mod 文件实现接口。所以,Fortran 并不需要头文件。
      在较老的代码中,由于大量使用了 common 共享数据。因此,常常把 common 里的数据定义放入 include 文件。
      包含文件其实非常简单,它完全等效于打开被包含文件,全选,复制,然后粘贴在 include 语句处。它只是一个预处理的语句,并不参与语法的任何编译,也没有 module 或其他语法那样复杂的逻辑关系。
    在这里插入图片描述
      被包含文件(如 inc.h)只是简单的用文件内容替换 include 语句,它可以是任何文件名和扩展名(如 .h 或 .inc 或 .par 或任何扩展名),只要它实际上是书写有 fortran 代码的文本文件。
      此外,如果包含文件(如name.f90)是自由格式,那么被包含文件(如 inc.h)也必须是自由格式。如果一个是固定格式,另一个也必须是固定格式。
      需要注意的是,由于被包含文件(如 inc.h)已经被替换到 name.F90 文件中。因此,它不能再被编译参与链接。所以,它不必,也不能出现在工程、解决方案中。这是区别于“多文件编译连接”的。

    Fortran中function简单使用

    Fortran中function、subroutine、 interface和module的简单使用主要参考了这篇CSDN博客。原文内容可以直接点进去看,这里只总结一下我的问题。

    声明interface调用function

    我在参考Intel MKL库调用的例子时,有如下的程序开头:

    !    vcMul  Example Program Text
    !*******************************************************
          include "_rms.fi"
          program MKL_VML_TEST
          include "mkl_vml.f90"
          ...
    

    其中"_rms.fi"中定义了程序program MKL_VML_TEST中调用的sub函数,"mkl_vml.f90"在MKL的include文件夹下,里面定义了MKL_VML函数的使用接口。根据上一节对于Fortran对于include文件的处理,相当于在代码里定义了sub子函数和function的接口interface。这个程序例子能够正常运行,也验证了与前面的叙述正确性。

    声明function

    当我参考另一个MKL库的调用例子ZDOTU_MAIN时,我发现这个例子里并没有关于MKL库函数的接口声明,而是只用external ZDOTUcomplex*16 ZDOTU声明了MKL函数ZDOTU是外部函数和它的返回数据类型。

    !      Z D O T U  Example Program Text
    !*****************************************************
     program  ZDOTU_MAIN
    *
          integer    n, incx, incy
          integer    xmax, ymax
          parameter  (xmax=20, ymax=20)
          complex*16 x(xmax), y(ymax), res
          integer    i
    *       Intrinsic Functions
          intrinsic  abs
    *       External Subroutines
          external   ZDOTU, PrintVectorZ
          complex*16 ZDOTU
          ...
    

    这个例子我没有成功运行,但是我仿照它的格式写了一个测试函数program testblas:

    program testblas
        implicit none
        !external sdot
        real sdot !声明BLAS库函数 实数向量内积
        real::a(2)=(/1,1/),c(2),b(2)=(/2,3/),d
    
        call scopy(2,a,1,c,1)  !调用BLAS库scopy函数,讲向量a复制给c
        print*,"scopy函数"
        print*,"a"
        print*,a
        print*,"c"
        print*,c
    
        print*,"sdot函数"
        d = sdot(2,a,1,b,1)
        print*,"d"
        print*,d
    end program testblas
    

    程序调用BLAS库的实数向量内积sdot函数和实数向量复制scopy函数进行向量运算,程序运行结果如下:
    在这里插入图片描述  这说明Fortran程序调用funtion函数,可以不用声明函数原型(定义接口,说明function的参数类型及返回数据类型),只在程序开头声明函数返回类型即可。通过实验,将program testblas中前三行替换以下两种种写法也可以通过编译。

    • 写法a
    	implicit none
        external,real sdot	!声明BLAS库函数 实数向量内积
    
    • 写法b
    	!implicit none
        external sdot	 !声明BLAS库函数 实数向量内积
    

    结论

    结合在网上找的资料,最后得出结论:

    1. 可以通过(1)定义interface调用function函数。
    2. 也可以声明‘type functionname’的方式,即以function函数的返回数据类型 + 函数名声明自定义function函数并在程序中调用。
    3. 通过‘type functionname’声明function函数时,建议使用写法a的形式。implicit none保证没有隐式类型,external说明是外部定义函数避免混淆(比如把函数当初变量)。

    附录

    为了方便以后验证,这里给出program MKL_VML_TEST源码。

    vcmul.f

    !  Content:
    !    vcMul  Example Program Text
    !*******************************************************************************
          include "_rms.fi"
          
          program MKL_VML_TEST
          
          include "mkl_vml.f90"
          real(kind=4) :: srelerr
          real(kind=8) :: drelerr
          real(kind=4) :: crelerr
          real(kind=8) :: zrelerr
    
          complex(kind=4) cA(10)
          complex(kind=4) cB(10)
          complex(kind=4) cBha0(10)
          complex(kind=4) cBha1(10)
          complex(kind=4) cBha2(10)
          complex(kind=4) cBla1(10)
          complex(kind=4) cBla2(10)
          complex(kind=4) cBep1(10)
          complex(kind=4) cBep2(10)
    
          real(kind=4) CurRMS,MaxRMS
    
          integer(kind=8) mode
          integer tmode
          integer i, vec_len
    
          vec_len=10
          MaxRMS=0.0
    
          cA( 1)=(-100.0000,100.0000)
          cA( 2)=(-77.7777,77.7777)
          cA( 3)=(-55.5555,55.5555)
          cA( 4)=(-33.3333,33.3333)
          cA( 5)=(-11.1111,11.1111)
          cA( 6)=(11.1111,-11.1111)
          cA( 7)=(33.3333,-33.3333)
          cA( 8)=(55.5555,-55.5555)
          cA( 9)=(77.7777,-77.7777)
          cA(10)=(100.0000,-100.0000)
          cB( 1)=(0.0000000000000000e+000,-2.0000000000000000e+004)
          cB( 2)=(0.0000000000000000e+000,-1.2098741959948209e+004)
          cB( 3)=(0.0000000000000000e+000,-6.1728271672816772e+003)
          cB( 4)=(0.0000000000000000e+000,-2.2222179836717260e+003)
          cB( 5)=(0.0000000000000000e+000,-2.4691309516836372e+002)
          cB( 6)=(0.0000000000000000e+000,-2.4691309516836372e+002)
          cB( 7)=(0.0000000000000000e+000,-2.2222179836717260e+003)
          cB( 8)=(0.0000000000000000e+000,-6.1728271672816772e+003)
          cB( 9)=(0.0000000000000000e+000,-1.2098741959948209e+004)
          cB(10)=(0.0000000000000000e+000,-2.0000000000000000e+004)
    
          call VCMUL(vec_len,cA,cA,cBha0)
    
          mode=VML_EP
          call VMCMUL(vec_len,cA,cA,cBep1,mode)
    
          tmode=VML_EP
          tmode=VMLSETMODE(tmode)
          call VCMUL(vec_len,cA,cA,cBep2)
    
          mode=VML_LA
          call VMCMUL(vec_len,cA,cA,cBla1,mode)
    
          tmode=VML_LA
          tmode=VMLSETMODE(tmode)
          call VCMUL(vec_len,cA,cA,cBla2)
    
          mode=VML_HA
          call VMCMUL(vec_len,cA,cA,cBha1,mode)
    
          tmode=VML_HA
          tmode=VMLSETMODE(tmode)
          call VCMUL(vec_len,cA,cA,cBha2)
    
          do i=1,10
              if(cBha0(i) .ne. cBha1(i)) then
                  print *,"Error! Difference between VCMUL and"
                  print *," VMCMUL in VML_HA mode detected"
                  stop 1
              endif
              if(cBha1(i) .ne. cBha2(i)) then
                  print *,"Error! Difference between VCMUL and"
                  print *," VMCMUL in VML_HA mode detected"
                  stop 1
              endif
              if(cBla1(i) .ne. cBla2(i)) then
                  print *,"Error! Difference between VCMUL and"
                  print *," VMCMUL in VML_LA mode detected"
                  stop 1
              endif
              if(cBep1(i) .ne. cBep2(i)) then
                  print *,"Error! Difference between VCMUL and"
                  print *," VMCMUL in VML_EP mode detected"
                  stop 1
              endif
          end do
    
          print *,"vcMul test/example program"
          print *,""
          print *,"                    Arguments                         ", &
         &        "      vcMul"
          print *,"======================================================", &
         &        "========================"
          do i=1,vec_len
                print 10,cA(i),cA(i),"    ",cBha0(i)
                CurRMS=crelerr(cB(i),cBha0(i))
                if(CurRMS>MaxRMS) MaxRMS=CurRMS
          end do
    
          print *,""
          if(MaxRMS>=1e-5) then
                print 11,"Error! Relative accuracy is ",MaxRMS
                stop 1
          else
                print 11,"Relative accuracy is ",MaxRMS
          endif
    
    10    format(E12.3,E12.3,E12.3,E12.3,A5,E12.3,E12.3)
    11    format(A,F25.16)
    
          end
    

    _rms.fi

    !  Content:
    !    routines for relative error calculation
    !*******************************************************************************
    
          real(kind=4) function sfabs(a)
    
          real(kind=4) :: a
    
          if(a>=0.0) then
            sfabs=a
          else
            sfabs=-1.0*a
          endif
    
          end function
    
    
          real(kind=8) function dfabs(a)
    
          real(kind=8) :: a
    
          if(a>=0.0) then
            dfabs=a
          else
            dfabs=-1.0d+000*a
          endif
    
          if(dfabs<1e-15) then
            dfabs=1e-15
          endif
    
          end function
    
    
          real(kind=4) function srelerr(a,b)
    
          real(kind=4) :: a
          real(kind=4) :: b
          real(kind=4) :: sfabs
    
          srelerr=sfabs((a-b)/a)
    
          end function
    
    
          real(kind=8) function drelerr(a,b)
    
          real(kind=8) :: a
          real(kind=8) :: b
          real(kind=8) :: dfabs
    
          drelerr=dfabs((a-b)/a)
    
          end function
    
    
          real(kind=4) function crelerr(a,b)
    
          complex(kind=4) :: a
          complex(kind=4) :: b
          real(kind=4) :: sfabs
    
          real(kind=4) re
          real(kind=4) im
    
          re=sfabs((REAL(a)-REAL(b))/REAL(a))
          im=sfabs((AIMAG(a)-AIMAG(b))/AIMAG(a))
    
          if(re>=im) then
            crelerr=re
          else
            crelerr=im
          endif
    
          end function
    
    
          real(kind=8) function zrelerr(a,b)
    
          complex(kind=8) :: a
          complex(kind=8) :: b
          real(kind=8) :: dfabs
    
          real(kind=8) re
          real(kind=8) im
    
          re=dfabs((REAL(a)-REAL(b))/REAL(a))
          im=dfabs((AIMAG(a)-AIMAG(b))/AIMAG(a))
    
          if(re>=im) then
            zrelerr=re
          else
            zrelerr=im
          endif
    
          end function
    

    展开全文
  • 1. 目录结构如下:example|——src 目录(存放源代码文件)|——hello.c|——lib 目录(存放用来生成文件)|——test.c 用来生成静态libhello.a|——include 目录(存放程序中使用的头文件)|——hello.h2....

    1. 目录结构如下:

    example

    |——src 目录(存放源代码文件)

    |——hello.c

    |——lib 目录(存放用来生成库的文件)

    |——test.c 用来生成静态库libhello.a

    |——include 目录(存放程序中使用的头文件)

    |——hello.h

    2. 编写的各个目录下的源文件

    hello.h 文件

    extern void print(char *);

    test.c 文件

    #include

    void print(char *msg)

    {

    print(“%s\n”, msg);

    }

    hello.c 文件

    #include “hello.h”

    int main()

    {

    print(“Hello static library!”);//这里用到的是静态库中的函数

    return 0;

    }

    3. 编写lib/Makefile.am 文件

    noinst_LIBRARIES=libhello.a

    libhello_a_SOURCES=test.c

    AUTOMAKE_OPTIONS=foreign

    第一行noinst 表示生成的是静态库,不需要make install ,直接制定它的位置和名字就

    可以使用。

    第二行表示用来生成静态库的源文件。如果要把静态库生成到其他地方,可以在=后面

    加上路径(建议用绝对路径,并将所要用到的静态库生成在同一个文件夹下,如lib)。

    第三行AUTOMAKE_OPTIONS 是Automake 的选项。Automake 主要是帮助开发 GNU 软

    件的人员来维护软件,所以在执行Automake 时,会检查目录下是否存在标准 GNU 软件中

    应具备的文件,例如 'NEWS'、'AUTHOR'、 'ChangeLog' 等文件。设置为foreign 时,Automake

    会改用一般软件的标准来检查。如果不加这句的话,需要在autoconf之前,先执行touch NEWS

    README AUTHORS ChangeLog 来生成'NEWS'、'AUTHOR'、 'ChangeLog' 等文件

    4. 编写src/Makefile.am 文件

    AUTOMAKE_OPTIONS=foreign

    INCLUDES= -I../include

    bin_PROGRAMS=hello

    hello_SOURCES=hello.c

    hello_LDADD=../lib/libhello.a

    第二行指定头文件的位置,-I 是idirafter 的缩写。../include 指定头文件的位置,..是上

    一级目录,也就是这里的example 目录。

    第三行指定生成可执行文件名hello,在这里可执行文件生成在src 下,建议将可执行文

    件生成到一个特定的文件夹下,让它和源代码分开,如/root/test 目录下。写法为:

    bin_PROGRAMS=/root/test/hello,后面的第四、五行也相对应地变为:

    _root_test_hello_SOURCES=hello.c

    _root_test_hello_LDADD=../lib/libhello.a

    第四行指定生成可执行文件hello 的源代码文件,如果hello.c 在其他目录下,需要加上

    完整的路径。

    第五行指定需要使用静态库的位置。

    5. 生成静态库文件lib/libhello.a。

    执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修改其内容。

    #configure.in

    # Process this file with autoconf to produce a configure script.

    AC_PREREQ(2.59)

    AC_INIT(libhello.a,1.1,[])

    AM_INIT_AUTOMAKE

    # Checks for programs.

    AC_PROG_CC

    # Checks for libraries.

    AC_PROG_RANLIB//需要加入的内容,因为使用了静态库

    # Checks for header files.

    # Checks for typedefs, structures, and compiler characteristics.

    # Checks for library functions.

    AC_OUTPUT([Makefile])

    AC_INIT(FILE)

    该宏用来检查源代码所在路径,autoscan 会自动产生,一般无须修改它。

    AM_INIT_AUTOMAKE(PACKAGE,VERSION)

    这个是使用 Automake 所必备的宏,PACKAGE 是所要产生软件的名称,VERSION 是版

    本编号。也可以把包和版本号等信息放在AC_INIT(FILE) 宏里。

    AC_PROG_CC

    检查系统可用的C 编译器,若源代码是用C 写的就需要这个宏。

    AC_OUTPUT(FILE)

    设置 configure 所要产生的文件,若是Makefile ,configure 便会把它检查出来的结果

    填充到Makefile.in 文件后产生合适的 Makefile。 后面的FILE 是一个Makefile 的输出列表,

    你可以选着将要输出的Makefile 的位置和个数。建议只在src 中输出Makefile。

    在lib 目录下依次执行 aclocal 、autoconf、automake --add-missing、./configure、make,

    此时在该目录下就可以看到生成的静态库文件libhello.a

    6. 在src 目录下,执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修

    改其内容。

    #configure.in

    # Process this file with autoconf to produce a configure script.

    AC_PREREQ(2.59)

    AC_INIT(hello,1.1,[])

    AM_INIT_AUTOMAKE

    AC_CONFIG_SRCDIR([hello.c])

    # Checks for programs.

    AC_PROG_CC

    # Checks for libraries.

    # Checks for header files.

    # Checks for typedefs, structures, and compiler characteristics.

    # Checks for library functions.

    AC_OUTPUT([Makefile])

    7. 在src 目录下依次执行 aclocal 、autoconf、automake --add-missing、./configure、make,

    生成可执行文件hello

    8. 执行make install 进行安装,最后输入hello 来运行程序,查看效果:

    Hello static library!

    执行成功!

    使用gcc 创建和使用静态库

    1. 编写mylib.h 文件

    #ifndef _mylib_h_

    #define _mylib_h_

    void welcome();

    void outstring(const char * str);

    #endif

    2. 编写mylib.c 文件,用来生成静态库。

    #include

    void welcome()

    {

    printf(“welcome to libmylib\n”);

    }

    void outstring(const char * str)

    {

    if(str!=NULL)

    printf(“%s”,str);

    }

    3. 编译源文件,产生目标代码

    gcc –o mylib.o –c mylib.c

    4. 将上面产生的目标文件加入到静态库中,并把静态库拷贝到系统默认的路径

    ar rcs libmylib.a mylib.o

    cp libmylib.a /usr/lib/

    5. 编写测试程序来使用刚才创建的静态库 libmylib.a

    #include “mylib.h”

    #include

    Int main()

    {

    printf(“create and use library:\n”);

    welcome();

    outstring(“It’s a successful\n”);

    }

    6. 编译使用库函数的程序

    gcc –o test test.c -lmylib

    运行./test 查看结果。

    使用Automake 创建和使用动态库

    动态库与静态库的差别在于:动态库是在程序执行的时候加载到内存,供调用函数使用。

    1. 目录结构如下:

    example

    |——src 目录(存放源代码文件)

    |——hello.c

    |——lib 目录(存放用来生成库的文件)

    |——test.c 用来生成动态库libhello.la

    |——include 目录(存放程序中使用的头文件)

    |——hello.h

    2. 编写各个目录下的源文件如下:

    hello.h 文件

    extern void print(char *);

    test.c 文件

    #include

    void print(char *msg)

    {

    print(“%s\n”, msg);

    }

    hello.c 文件

    #include “hello.h”

    int main()

    {

    print(“Hello static library!”);//这里用到的是动态库中的函数

    return 0;

    }

    3. 在lib 目录下编译需要生成动态库的文件,生成动态库,并安装到系统的标准库中,供

    程序调用。具体步骤如下:

    (1) 编写Makefile.am 文件

    AUTOMAKE_OPTIONS=foreign

    lib_LTLIBRARIES=libhello.la

    libhello_la_SOURCES=test.c

    这里lib_LTLIBRARIES 的意思是生成的动态库,然后指定动态库依赖的源文件

    test.c ,若有多个源文件用空格隔开。

    (2) 在lib 目录下,用命令autoscan 产生configure.scan 文件,并改名为configure.in。 这

    里需加上宏AC_PROG_LIBTOOL,表示利用libtool 来自动生成动态库

    #configure.in

    # Process this file with autoconf to produce a configure script.

    AC_PREREQ(2.59)

    AC_INIT(hello,1.0, [miaoquan@nou.com.cn])

    AM_INIT_AUTOMAKE

    AC_CONFIG_SRCDIR([test.c])

    #AC_CONFIG_HEADER([config.h])

    # Checks for programs.

    AC_PROG_CC

    # Checks for header files.

    # Checks for typedefs, structures, and compiler characteristics.

    # Checks for library functions.

    AC_PROG_LIBTOOL

    AC_CONFIG_FILES([Makefile])

    AC_OUTPUT

    (3) 执行命令aclocal、libtoolize -f -c 、autoconf、automake --add-missing、./configure、

    make、make install 将动态库安装到系统的标准库中,以供调用(一般为/usr/local/lib)。

    注:libtoolize 提供了一种标准的方式来将libtool 支持加入一个软件包,而GNU libtool 是

    一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中。

    4. 生成src 目录下的hello 可执行文件

    (1) 编写src/Makefile.am 文件

    AUTOMAKE_OPTIONS=foreign

    INCLUDES= -I../include

    bin_PROGRAMS=hello

    hello_SOURCES=hello.c

    hello_LDADD=-lhello

    -ldir 指定编译时搜索库的路径。与静态库不同的是,创建动态库时不用指定库路

    径,编译器自动在标准库中查找libhello.so 文件。

    (2) 执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修改其内容。

    # configure.in

    # Process this file with autoconf to produce a configure script.

    AC_PREREQ(2.59)

    AC_INIT(hello,1.0, [miaoquan@nou.com.cn])

    AM_INIT_AUTOMAKE

    AC_CONFIG_SRCDIR([hello.c])

    #AC_CONFIG_HEADER([config.h])

    # Checks for programs.

    AC_PROG_CC

    # Checks for header files.

    # Checks for typedefs, structures, and compiler characteristics.

    # Checks for library functions.

    AC_CONFIG_FILES([Makefile])

    AC_OUTPUT

    (3) 在src 目录下编译并生成目标文件,执行命令aclocal、libtoolize -f -c 、autoconf、

    automake --add-missing、./configure、make,此时你一定会觉得,成功近在咫尺了。再

    执行目标文件./hello,结果却在你的意料之外:

    ./hello: error while loading shared libraries: libhello.so.0 : cannot open shared object file:

    No such file or directory

    在执行目标文件的时候,Shell 找不到共享库的位置,需要我们手工载入库路径。

    5. shell 搜索动态库路径位置的两种方法

    (1) 使用命令导入动态库的路径,命令如下:

    export LD_LIBRARY_PATH=dir (如/usr/local/lib)

    (2) 修改/etc/ld.so.conf 文件,加入搜索路径,修改后用ldconfig 命令载入修改。

    将自己可能存放库文件的路径都加入到/etc/ld.so.conf 中是明智的选择 ^_^。添加

    方法也极其简单,将库文件的绝对路径直接写进去就OK 了,一行一个。例如:

    /usr/local/lib

    /usr/lib

    /lib

    需要注意的是:这种搜索路径的设置方式对于程序连接时的库(包括共享库和静态

    库)的定位已经足够了,但是对于使用了共享库的程序的执行还是不够的。这是 因为

    为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所

    以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。/etc/ld.so.cache 是一个非

    文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由

    /sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一起而生成的(ldconfig 命令

    要以 root 权限执行)。因此,为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中

    进行了库搜索路径的设置之后,还必须要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache

    文件之后才可以。ldconfig ,简单的说,它的作用就是将/etc/ld.so.conf 列出的路径下的库

    文件 缓存到/etc/ld.so.cache 以供使用。因此当安装完一些库文件,(例如刚安装好glib),

    或者修改ld.so.conf 增加新的库路径后,需要运行一下/sbin/ldconfig 使所有的库文件都

    被缓存到ld.so.cache 中,如果没做,即使库文件明明就在/usr/lib 下的,也是不会被使

    用的,结果编译过程中报错,缺少xxx 库,去查看发现明明就在那放着,搞的想大骂

    computer 蠢猪一个^_^。极力推荐使用这种方法!

    利用gcc 创建和使用动态库

    1. 用下面的命令将mylib.c 程序创建成一个动态库:

    gcc –fPIC –o mylib.o –c mylib.c

    gcc –shared –o libtt.so mylib.o

    -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),

    则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的

    任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不

    是固定的。

    -shared 作用于链接阶段,实际传递给链接器ld,让其添加作为共享库所需要的额外描

    述信息,去除共享库所不需的信息。

    也可以直接使用下面一条命令:

    gcc –fPIC –shared –o libtt.so mylib.c

    2. 将动态库拷贝到linux 的标准库中,usr/local/lib 或者/usr/lib 或者/lib:

    cp libttt.so /usr/local/lib

    3. 编译src 目录下的源程序时,指定动态库文件的目录,调用动态库中的函数

    gcc –o test test.c /usr/lib/libttt.so

    4. 设置shell 动态库搜索路径,运行生成的可执行文件。

    ---------------------------------------------------------------------------

    AUTOMAKE_OPTIONS=foreign

    INCLUDES=-I$(top_srcdir)/libpr/include -I$(top_srcdir)/vt/include

    noinst_PROGRAMS =libvt.so

    libvt_so_SOURCES=vty/vtcmd.c vty/vtdrv.c vty/vty.c vty/evtd.c telnet/telcmd.c telnet/teldrv.c telnet/telnegot.c telnet/telsvr.c telnet/telsess.c vty/defcmd.c vty/vtobj.c

    libvt_so_LDFLAGS = -fPIC -shared

    libvt_so_LDADD=$(top_srcdir)/libpr/libpr.a

    bin_PROGRAMS = test_telnetd

    test_telnetd_SOURCES = test/test_telnetd.c

    test_telnetd_LDADD=$(top_srcdir)/libpr/libpr.a libvt.so

    上面这段代码是从我的一个工程的Makefile.am中摘抄过来的,使用不少技巧。

    1、动态库实际上也是ELF格式,所以我们使用PROGRAMS宏,automake将他按执行文件规格设置环境,如果使用noinstall_LIBRARIES那么就变成*.a静态库了。

    2、因为是动态库,所以我们有必要加入-fPIC -shared

    3、test_telnetd需要调用libvt.so,所以他们之间存在依赖关系。我们将libvt.so直接添加在LDADD 中,automake会自动他们建立依赖关系,在Makefile中可以到test_telnetd_DEPENDENCIES,里面包含 libvt.so。

    这里有几个要紧需要注意:

    1、$(bin_PROGRAMS)编译顺序在$(noinstall_PROGRAMS)之前,因为test_telnetd需要libvt.so,所以会找不到libvt.so。

    2、在LDADD中如果使用-lvt不会建立依赖关系,如果使用$(top_srcdir)/vt/libvt.so也不行。

    3、实际上如果不行的话,我们可以直接使用test_telnetd_DEPENDENCIES来指定libvt.so

    4、如果需要make install 安装libvt.so到lib,那么使用XXX_PROGRAMS=...的方法,然后指定XXXbin=...就行了。类似于bin_PROGRAMS。

    这里使用到的技巧都很有用,值得记录下来。

    posted on 2011-06-01 13:22 艾斯维亚 阅读(5153) 评论(0)  编辑 收藏 引用

    展开全文
  • 目录结构如下:example|——src 目录(存放源代码文件)|——hello.c|——lib 目录(存放用来生成文件)|——test.c 用来生成静态libhello.a|——include 目录(存放程序中使用的头文件)|——hello.h2. 编写的各个...

    使用Automake 创建和使用静态库

    1. 目录结构如下:

    example

    |——src 目录(存放源代码文件)

    |——hello.c

    |——lib 目录(存放用来生成库的文件)

    |——test.c 用来生成静态库libhello.a

    |——include 目录(存放程序中使用的头文件)

    |——hello.h

    2. 编写的各个目录下的源文件

    hello.h 文件

    extern void print(char *);

    test.c 文件

    #include

    void print(char *msg)

    {

    print(“%s/n”, msg);

    }

    hello.c 文件

    #include “hello.h”

    int main()

    {

    print(“Hello static library!”);//这里用到的是静态库中的函数

    return 0;

    }

    3. 编写lib/Makefile.am 文件

    noinst_LIBRARIES=libhello.a

    libhello_a_SOURCES=test.c

    AUTOMAKE_OPTIONS=foreign

    第一行noinst 表示生成的是静态库,不需要make install ,直接制定它的位置和名字就

    可以使用。

    第二行表示用来生成静态库的源文件。如果要把静态库生成到其他地方,可以在=后面

    加上路径(建议用绝对路径,并将所要用到的静态库生成在同一个文件夹下,如lib)。

    第三行AUTOMAKE_OPTIONS 是Automake 的选项。Automake 主要是帮助开发 GNU 软

    件的人员来维护软件,所以在执行Automake 时,会检查目录下是否存在标准 GNU 软件中

    应具备的文件,例如 'NEWS'、'AUTHOR'、 'ChangeLog' 等文件。设置为foreign 时,Automake

    会改用一般软件的标准来检查。如果不加这句的话,需要在autoconf之前,先执行touch NEWS

    README AUTHORS ChangeLog 来生成'NEWS'、'AUTHOR'、 'ChangeLog' 等文件

    4. 编写src/Makefile.am 文件

    AUTOMAKE_OPTIONS=foreign

    INCLUDES= -I../include

    bin_PROGRAMS=hello

    hello_SOURCES=hello.c

    hello_LDADD=../lib/libhello.a

    第二行指定头文件的位置,-I 是idirafter 的缩写。../include 指定头文件的位置,..是上

    一级目录,也就是这里的example 目录。

    第三行指定生成可执行文件名hello,在这里可执行文件生成在src 下,建议将可执行文

    件生成到一个特定的文件夹下,让它和源代码分开,如/root/test 目录下。写法为:

    bin_PROGRAMS=/root/test/hello,后面的第四、五行也相对应地变为:

    _root_test_hello_SOURCES=hello.c

    _root_test_hello_LDADD=../lib/libhello.a

    第四行指定生成可执行文件hello 的源代码文件,如果hello.c 在其他目录下,需要加上

    完整的路径。

    第五行指定需要使用静态库的位置。

    5. 生成静态库文件lib/libhello.a。

    执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修改其内容。

    #configure.in

    # Process this file with autoconf to produce a configure script.

    AC_PREREQ(2.59)

    AC_INIT(libhello.a,1.1,[])

    AM_INIT_AUTOMAKE

    # Checks for programs.

    AC_PROG_CC

    # Checks for libraries.

    AC_PROG_RANLIB//需要加入的内容,因为使用了静态库

    # Checks for header files.

    # Checks for typedefs, structures, and compiler characteristics.

    # Checks for library functions.

    AC_OUTPUT([Makefile])

    /

    AC_INIT(FILE)

    该宏用来检查源代码所在路径,autoscan 会自动产生,一般无须修改它。

    AM_INIT_AUTOMAKE(PACKAGE,VERSION)

    这个是使用 Automake 所必备的宏,PACKAGE 是所要产生软件的名称,VERSION 是版

    本编号。也可以把包和版本号等信息放在AC_INIT(FILE) 宏里。

    AC_PROG_CC

    检查系统可用的C 编译器,若源代码是用C 写的就需要这个宏。

    AC_OUTPUT(FILE)

    设置 configure 所要产生的文件,若是Makefile ,configure 便会把它检查出来的结果

    填充到Makefile.in 文件后产生合适的 Makefile。 后面的FILE 是一个Makefile 的输出列表,

    你可以选着将要输出的Makefile 的位置和个数。建议只在src 中输出Makefile。

    在lib 目录下依次执行 aclocal 、autoconf、automake --add-missing、./configure、make,

    此时在该目录下就可以看到生成的静态库文件libhello.a

    6. 在src 目录下,执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修

    改其内容。

    #configure.in

    # Process this file with autoconf to produce a configure script.

    AC_PREREQ(2.59)

    AC_INIT(hello,1.1,[])

    AM_INIT_AUTOMAKE

    AC_CONFIG_SRCDIR([hello.c])

    # Checks for programs.

    AC_PROG_CC

    # Checks for libraries.

    # Checks for header files.

    # Checks for typedefs, structures, and compiler characteristics.

    # Checks for library functions.

    AC_OUTPUT([Makefile])

    7. 在src 目录下依次执行 aclocal 、autoconf、automake --add-missing、./configure、make,

    生成可执行文件hello

    8. 执行make install 进行安装,最后输入hello 来运行程序,查看效果:

    Hello static library!

    执行成功!

    使用gcc 创建和使用静态库

    1. 编写mylib.h 文件

    #ifndef _mylib_h_

    #define _mylib_h_

    void welcome();

    void outstring(const char * str);

    #endif

    2. 编写mylib.c 文件,用来生成静态库。

    #include

    void welcome()

    {

    printf(“welcome to libmylib/n”);

    }

    void outstring(const char * str)

    {

    if(str!=NULL)

    printf(“%s”,str);

    }

    3. 编译源文件,产生目标代码

    gcc –o mylib.o –c mylib.c

    4. 将上面产生的目标文件加入到静态库中,并把静态库拷贝到系统默认的路径

    ar rcs libmylib.a mylib.o

    cp libmylib.a /usr/lib/

    5. 编写测试程序来使用刚才创建的静态库 libmylib.a

    #include “mylib.h”

    #include

    Int main()

    {

    printf(“create and use library:/n”);

    welcome();

    outstring(“It’s a successful/n”);

    }

    6. 编译使用库函数的程序

    gcc –o test test.c -lmylib

    运行./test 查看结果。

    使用Automake 创建和使用动态库

    动态库与静态库的差别在于:动态库是在程序执行的时候加载到内存,供调用函数使用。

    1. 目录结构如下:

    example

    |——src 目录(存放源代码文件)

    |——hello.c

    |——lib 目录(存放用来生成库的文件)

    |——test.c 用来生成动态库libhello.la

    |——include 目录(存放程序中使用的头文件)

    |——hello.h

    2. 编写各个目录下的源文件如下:

    hello.h 文件

    extern void print(char *);

    test.c 文件

    #include

    void print(char *msg)

    {

    print(“%s/n”, msg);

    }

    hello.c 文件

    #include “hello.h”

    int main()

    {

    print(“Hello static library!”);//这里用到的是动态库中的函数

    return 0;

    }

    3. 在lib 目录下编译需要生成动态库的文件,生成动态库,并安装到系统的标准库中,供

    程序调用。具体步骤如下:

    (1) 编写Makefile.am 文件

    AUTOMAKE_OPTIONS=foreign

    lib_LTLIBRARIES=libhello.la

    libhello_la_SOURCES=test.c

    这里lib_LTLIBRARIES 的意思是生成的动态库,然后指定动态库依赖的源文件

    test.c ,若有多个源文件用空格隔开。

    (2) 在lib 目录下,用命令autoscan 产生configure.scan 文件,并改名为configure.in。 这

    里需加上宏AC_PROG_LIBTOOL,表示利用libtool 来自动生成动态库

    #configure.in

    # Process this file with autoconf to produce a configure script.

    AC_PREREQ(2.59)

    AC_INIT(hello,1.0, [miaoquan@nou.com.cn])

    AM_INIT_AUTOMAKE

    AC_CONFIG_SRCDIR([test.c])

    #AC_CONFIG_HEADER([config.h])

    # Checks for programs.

    AC_PROG_CC

    # Checks for header files.

    # Checks f    or typedefs, structures, and compiler characteristics.

    # Checks for library functions.

    AC_PROG_LIBTOOL

    AC_CONFIG_FILES([Makefile])

    AC_OUTPUT

    (3) 执行命令aclocal、libtoolize -f -c 、autoconf、automake --add-missing、./configure、

    make、make install 将动态库安装到系统的标准库中,以供调用(一般为/usr/local/lib)。

    注:libtoolize 提供了一种标准的方式来将libtool 支持加入一个软件包,而GNU libtool 是

    一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中。

    4. 生成src 目录下的hello 可执行文件

    (1) 编写src/Makefile.am 文件

    AUTOMAKE_OPTIONS=foreign

    INCLUDES= -I../include

    bin_PROGRAMS=hello

    hello_SOURCES=hello.c

    hello_LDADD=-lhello

    -ldir 指定编译时搜索库的路径。与静态库不同的是,创建动态库时不用指定库路

    径,编译器自动在标准库中查找libhello.so 文件。

    (2) 执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修改其内容。

    # configure.in

    # Process this file with autoconf to produce a configure script.

    AC_PREREQ(2.59)

    AC_INIT(hello,1.0, [miaoquan@nou.com.cn])

    AM_INIT_AUTOMAKE

    AC_CONFIG_SRCDIR([hello.c])

    #AC_CONFIG_HEADER([config.h])

    # Checks for programs.

    AC_PROG_CC

    # Checks for header files.

    # Checks for typedefs, structures, and compiler characteristics.

    # Checks for library functions.

    AC_CONFIG_FILES([Makefile])

    AC_OUTPUT

    (3) 在src 目录下编译并生成目标文件,执行命令aclocal、libtoolize -f -c 、autoconf、

    automake --add-missing、./configure、make,此时你一定会觉得,成功近在咫尺了。再

    执行目标文件./hello,结果却在你的意料之外:

    ./hello: error while loading shared libraries: libhello.so.0 : cannot open shared object file:

    No such file or directory

    在执行目标文件的时候,Shell 找不到共享库的位置,需要我们手工载入库路径。

    5. shell 搜索动态库路径位置的两种方法

    (1) 使用命令导入动态库的路径,命令如下:

    export LD_LIBRARY_PATH=dir (如/usr/local/lib)

    (2) 修改/etc/ld.so.conf 文件,加入搜索路径,修改后用ldconfig 命令载入修改。

    将自己可能存放库文件的路径都加入到/etc/ld.so.conf 中是明智的选择 ^_^。添加

    方法也极其简单,将库文件的绝对路径直接写进去就OK 了,一行一个。例如:

    /usr/local/lib

    /usr/lib

    /lib

    需要注意的是:这种搜索路径的设置方式对于程序连接时的库(包括共享库和静态

    库)的定位已经足够了,但是对于使用了共享库的程序的执行还是不够的。这是 因为

    为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所

    以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。/etc/ld.so.cache 是一个非

    文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由

    /sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一起而生成的(ldconfig 命令

    要以 root 权限执行)。因此,为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中

    进行了库搜索路径的设置之后,还必须要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache

    文件之后才可以。ldconfig ,简单的说,它的作用就是将/etc/ld.so.conf 列出的路径下的库

    文件 缓存到/etc/ld.so.cache 以供使用。因此当安装完一些库文件,(例如刚安装好glib),

    或者修改ld.so.conf 增加新的库路径后,需要运行一下/sbin/ldconfig 使所有的库文件都

    被缓存到ld.so.cache 中,如果没做,即使库文件明明就在/usr/lib 下的,也是不会被使

    用的,结果编译过程中报错,缺少xxx 库,去查看发现明明就在那放着,搞的想大骂

    computer 蠢猪一个^_^。极力推荐使用这种方法!

    利用gcc 创建和使用动态库

    1. 用下面的命令将mylib.c 程序创建成一个动态库:

    gcc –fPIC –o mylib.o –c mylib.c

    gcc –shared –o libtt.so mylib.o

    -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),

    则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的

    任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不

    是固定的。

    -shared 作用于链接阶段,实际传递给链接器ld,让其添加作为共享库所需要的额外描

    述信息,去除共享库所不需的信息。

    也可以直接使用下面一条命令:

    gcc –fPIC –shared –o libtt.so mylib.c

    2. 将动态库拷贝到linux 的标准库中,usr/local/lib 或者/usr/lib 或者/lib:

    cp libttt.so /usr/local/lib

    3. 编译src 目录下的源程序时,指定动态库文件的目录,调用动态库中的函数

    gcc –o test test.c /usr/lib/libttt.so

    4. 设置shell 动态库搜索路径,运行生成的可执行文件。

    ------------by David Liu

    展开全文
  • 生成动态库文件二、在C语言程序中调用dll动态库1.第一种调用方法:仅配置dll文件路径(“显示链接”)2.第二种调用方法:配置.h,lib,dll文件路径三、JNA调用动态库四、JNI调用动态库五、附加内容1. 错误记录1.1 ...
  • 从组成上看,动态库和静态库的差异在于动态库多了一份dll文件,导致动态库可以独立存在, 2、链接方式 静态库:只能静态链接 动态库:动态链接和静态链接 3、运行效果 静态库:相当于直接把代码段...
  • 1、文件结构 include: .h文件 lib: .a文件 test: .c文件 2、GCC指令 gcc test/main.c -I include/ -L lib/ -l test -o test.out 在编译 main.c 的时候,我们需要使用-I(大写的字母i)选项指明头文件的包含路径,...
  • 从组成上看,动态库和静态库的差异在于动态库多了一份dll文件,导致动态库可以独立存在, 2、链接方式 静态库:只能静态链接 动态库:动态链接和静态链接 3、运行效果 静态库:相当于直接把代码段写入到exe或...
  • 先看我的项目文档结构:include文件夹里是openssl的头文件,lib文件里是C的动态库,service里面有C的调用。service中的C代码调用部分代码如下/* #cgo CFLAGS : -I../include #cgo windows LDFLAGS: -L../lib -...
  • linux 动态库

    2019-09-19 10:20:47
    1.文件结构 hello (用于生产动态库文件) + hello.c hello.h Makefile lib(用于存放编译好的动态库) test.c test Makefile 2.相关代码 hello.h #ifndef _HELLO...
  • 动态链接vs静态链接

    千次阅读 2016-09-07 11:26:51
    静态库和动态库链接分析 1文件组成结构 2链接方式 3运行效果 4差别 5编译 6导出类的链接 7导出子类 静态链接库LIB和动态链接库DLL的区别 一静态链接库与动态链接库区别 1 静态链接库比较简单 2动态链接库 二LIB文件 ...
  • DLL即动态链接库(Dynamic-Link Library)的缩写,相当于Linux下的共享对象。...一般的动态库程序有lib文件和dll文件lib文件是编译时期连接到应用程序中的,而dll文件才是运行时才会被调用的。 为了根号...
  • 动态链接和静态

    2020-05-28 00:24:54
    在c语言中,编写库文件时,一般包含.h文件和.cpp文件,.h文件中包含了函数和数据结构的声明,.cpp文件中包含了函数的实现。 动态链接库和静态库的区别 动态库:需要伴随.lib文件,运行时需要调用库函数时,需要在....
  • 本文以工程libtest为例来说明用gcc创建和使用静态库、动态库的过程。libtest工程目录结构如下:libtest/include/hello.h文件内容:#ifndef __HELLO_H__#define __HELLO_H__void sayHello(void);#endiflibtest/lib/...
  • 文章目录cmake模板—生成自己的动态库和静态库目录结构顶层CMakeLists.txtsrc里的CMakeLists.txtlib里的CMakeLists.txt cmake模板—生成自己的动态库和静态库 目录结构 进入build,执行cmake …;make;make install...
  • 动态链接包含:lib文件和dll文件,静态链接中不能再包含其他的动态链接或者静态,而在动态链接中还可以再包含其他的动态或静态链接。此外他们都会用到定义了函数和相关数据结构的.h头文件,其中:.h...
  • 在linux环境下文件的类型是不依赖于其后缀名的,一般地: .so 是共享库,相当于windows的.dll ...下面以工程libtest为例说明gcc创建和使用静态库、动态库的过程,libtest目录结构和内容如图1所示,其中
  • 使用Automake 创建和使用静态库/动态库 一, 静态库的生成 1. 目录结构如下: example |——src 目录(存放源代码文件) |——hello.c |——lib 目录(存放用来生成库的文件)...
  • linux文件结构

    千次阅读 2018-09-18 14:40:09
    usr:系统用户工具和程序,bin:用户命令,include:标准头文件,lib库文件,src:内核源代码。 tmp:临时文件。 dev:所有外部设备文件(驱动)。 home:用户文件夹。 lib:放动态库。 mnt:临时挂载其他...
  • 前言: 编译器 Qt Creator, 系统环境 win7 64 位1....下一步(工程名为 sharedlib)生成的目录结构如图:修改 sharedlib.h 中的代码:// sharedlib.h#ifndef SHAREDLIB_H#define SHAREDLIB_H#include "sh...
  • Linux文件目录结构

    2020-11-22 18:42:59
    一、Linux文件目录结构 Linux 的文件系统是采用级层式的树状目录结构,在此结构...系统开机需要的最基本的动态链接共享,作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享。 /etc 系统管理所
  • openssl动态编译

    2019-01-29 16:59:52
    文件目录结构 | bin | openssl.exe //openssl可执行程序 libeay32.dll //openssl用到的动态链接 ssleay32.dll //openssl用到的动态链接 | include // 包含所需的头文件 | openssl ssl.h等 | lib //静态...
  • 本文介绍使用cmake来编译动态库和静态库,源码非常简单,重点是掌握文件的组织方式以及cmake的使用。 文章目录目录结构add.cCMakeLists.txtCMAKE_ARCHIVE_OUTPUT_DIRECTORYCMAKE_LIBRARY_OUTPUT_DIRECTORYadd_...
  • 动态库的动态加载和静态加载

    千次阅读 2016-07-19 09:18:21
    在这种情况下,如果这个dll的导出函数参数有内部定义的数据类型,显然是违反低耦合性原则的,实际上这种情况下编写dll方应该提供.h、.lib和.dll文件给使用者的,即你不能以动态库的动态加载方式调用,而是以动态库的...
  • 使用Automake 创建和使用静态 ...|——lib 目录(存放用来生成文件) |——test.c 用来生成静态libhello.a |——include 目录(存放程序中使用的头文件) |——hello.h 2. 编写的各个目录下的源文件 he...
  • 目录 1. 文件目录结构 ... 库文件源代码 3. 编译生成库文件 1. 文件目录结构 首先创建如下目录结构: └── lib ├── build # ├── CMakeLists.txt └── src # ├── add.c ...
  • 关于动态库so的makefile编写

    千次阅读 2020-12-27 15:36:45
    测试的相关代码目录结构 ...使用命令ldd test查看test链接动态库文件的情况: not found情况处理 此情况表示链接器找不到我们需要的那个so文件,那么需要执行命令 export LD_LIBRARY_PATH=./lib:$LD_LIBRARY
  • LINUX文件目录结构 /bin :目录下存放常用命令 /boot :存放linux启动核心.../lib动态连接共享,类似Windows 的dll文件 /lost+found:一般空目录,非正常关机存放一些文件 /media :识别设备挂载该目录...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 644
精华内容 257
关键字:

动态库文件lib结构