A. LIB静态库怎么定义导出函数
静态库不需要定义导出,只要有.h头文件就可以调用。
可以阅读《程序员的自我修养--链接、装载与库》的PDF了解静态库、动态库的原理
静态库可能只是定位DLL用,也可能含有代码,链接时会把这部分代码直接包含到程序不需要导出
B. 关于动态库 静态库 区别与使用 路径查找等
一、引言
我们通常把一些公用函数制作成函数库,供其它程序使用。
函数库分为静态库和动态库两种。
通常情况下,对函数库的链接是放在编译时期(compile time)完成的。所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file)。程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到相应目录下下。所以这些函数库被成为静态库(static libaray),通常文件名为“libxxx.a”的形式。
其实,我们也可以把对一些库函数的链接载入推迟到程序运行的时期(runtime)。这就是动态链接库(dynamic link library)技术。
二、两者区别:
a,静态库的使用需要:
1 包含一个对应的头文件告知编译器lib文件里面的具体内容
2 设置lib文件允许编译器去查找已经编译好的二进制代码
b,动态库的使用:
程序运行时需要加载动态库,对动态库有依赖性,需要手动加入动态库
c,依赖性:
静态链接表示静态性,在编译链接之后, lib库中需要的资源已经在可执行程序中了, 也就是静态存在,没有依赖性了
动态,就是实时性,在运行的时候载入需要的资源,那么必须在运行的时候提供 需要的 动态库,有依赖性, 运行时候没有找到库就不能运行了
d,区别:
简单讲,静态库就是直接将需要的代码连接进可执行程序;动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。
做成静态库可执行文件本身比较大,但不必附带动态库
做成动态库可执行文件本身比较小,但需要附带动态库
链接静态库,编译的可执行文件比较大,当然可以用strip命令精简一下(如:strip libtest.a),但还是要比链接动态库的可执行文件大。程序运行时间速度稍微快一点。
静态库是程序运行的时候已经调入内存,不管有没有调用,都会在内存里头。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
其在编译程序时若链接,程序运行时会在系统指定的路径下搜索,然后导入内存,程序一般执行时间稍微长一点,但编译的可执行文件比较小;动态库是程序运行的时候需要调用的时候才装入内存,不需要的时候是不会装入内存的。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
三、动态链接库的特点与优势
首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:
1. 可以实现进程之间的资源共享。
什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段。
2. 将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。
3. 甚至可以真正坐到链接载入完全由程序员在程序代码中控制。
程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。
静态库:在编译的时候加载生成目标文件,在运行时不用加载库,在运行时对库没有依赖性。
动态库:在目标文件运行时加载,手动加载,且对库有依赖性。
具体在开发中用到哪种库,我觉得还是根据实际的内存大小,ROM大小,运行的速度等综合考虑。
C. 怎么在外面调用一个没导出函数的lib
静态库不需要定义导出,只要有.h头文件就可以调用。 可以阅读《程序员的自我修养--链接、装载与库》的PDF了解静态库、动态库的原理 静态库可能只是定位DLL用,也可能含有代码,链接时会把这部分代码直接包含到程序不需要导出
D. c语言中stdiolib什么意思
stdio:是standard in/out的缩写,标准输入输出。stdio.h头文件中包含了许多标准输入输出函数,如printf()、scanf()、fgets()等
stdlib:是standard library的缩写,标准库。stdlib.h头文件中包含了许多有用的库类型和库函数,这些函数都是预先定义好的,以简化程序员的工作。例如malloc()、free()、rand()、system()等等。
E. java程序员 工作后都用到哪些jar 包 ,干什么用的
从你说 SSH 就说明:你以后可能会从事 Web 开发,所以你应该看一下
1.Ajax 用在Web开发中,用于异步获取服务端数据,企业一般使用JQuery框架
2.要熟练运用 JavaScript,这个很重要
3.一般公司还要求会 EJB、JMS、WebService,这些对于刚毕业的,了解就可以了
4.数据库,你主学 Oracle 就可以了
5.操作系统,一般公司会要求对 Linux 要会操作
对于 jar 包,你要会使用线程(Thread 类、Runnable 接口),这个企业中用的多
以上内容在网络上都可以搜相关资料,有兴趣可以看一下
F. jdk下的lib和jdk\jre下的lib一样吗
jdk下的lib和jdk/jre下的lib文件是一样的,这只是为了不同场景下的使用,解释如下:
1.普通用户装jre即可。开发人员需要安装jdk,其中包括jre。所以jdk目录下包括jre目录。两个jre大体相同,有细微的差别。两套 jre ,是针对不同的工作职责!不同的 jre 负责各自范围的内容。当用户只需要执行 java 的程序时,那么C:\Program Files\Java\jre1.5.0_08的 jre 就 ok !
2.当用户是 java 程序员,则需要 java 开发环境。编译时,系统就会优先去找C:\Program Files\Java\jdk1.5.0_08\bin下的“ java 、 javac ”这些命令所在目录或者他们的父目录的 jre 。即开发环境下运行的是 jdk 下的 jre 。
G. lib和dll有什么区别,什么叫静态链接库,什么叫动态连接库
静态链接库与动态链接库区别
静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。但是若使用 DLL,该 DLL 不必被包含在最终 EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与 EXE 独立的 DLL 文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。如果在当前工程中有多处对dll文件中同一个函数的调用,那么执行时,这个函数只会留下一份拷贝。但是如果有多处对lib文件中同一个函数的调用,那么执行时,该函数将在当前程序的执行空间里留下多份拷贝,而且是一处调用就产生一份拷贝。
静态链接库与静态链接库调用规则总体比较如下:
1、 静态链接库(比较简单):
首先,静态链接库的使用需要库的开发者提供生成库的.h头文件和.lib文件。生成库的.h头文件中的声明格式如下:
extern "C" 函数返回类型 函数名(参数表);
在调用程序的.cpp源代码文件中如下:
#include "../lib.h"
#pragma comment(lib,"..//debug//libTest.lib") //指定与静态库一起链接
其次因为静态链接库是将全部指令都包含入调用程序生成的EXE文件中。因此如果用的是静态链接库,那么也就不存在“导出某个函数提供给用户使用”的情况,要想用就得全要!要不就都别要!
2、 态链接库:
动态链接库的使用需要库的开发者提供生成的.lib文件和.dll文件。或者只提供dll文件。
首先我们必须先注意到DLL内的函数分为两种:
1) 出函数,可供应用程序调用;
2) LL内部函数,只能在 DLL 程序使用,应用程序无法调用它们。
因此调用程序若想调用DLL中的某个函数就要以某种形式或方式指明它到底想调用哪一个函数。
Ø 对于DLL的导出,可以采用如下方法:
#ifdef WLL_EXPORTS
#define WLL_API __declspec(dllexport)
#else
#define WLL_API __declspec(dllimport)
#endif
这是导出类的宏定义,将导出类必须加上该宏,才能被导出。
此处的WLL_EXPORTS会出现在 projectàsettingsàC++à PreProcessor的PreProcessor definition中,这个MACRO表明其要定义一个导出宏。
当前库编译时,加了WLL_API的类将被导出,而包含该头文件的其他调用DLL或EXE,由于没有定义WLL_API宏,将申明为导入该类。
Ø 动态库函数的调用,可以采用静态链接的方式,主要步骤如下:
包含DLL中导出的头文件。
采用#pragma comment(lib,"..//debug//libTest.lib")导入动态库生成的*.lib头文件。或在projectàsettingsàLinkeràInput的Additional Dependencies中加入lib文件。
将动态库生成的*.dll文件放到EXE或DLL的同一目录下。
Ø 也可以采用动态加载的方式调用,步骤如下:
Another.dll有一个int Add(int x,int y) 函数。则完整的调用过程如下:
typedef int (* FunPtr)(int,int); //定义函数指针
FunPtr funPtr;
Handle handle =LoadLibrary("Another.dll");
funPtr =(FunPtr)GetProcAddress(handle ,"Add");
funPtr(2,3); // 2+3;
FreeLibrary(handle); // 释放载入的动态库
LIB文件
目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。
静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。
动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。
导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。
这也是实际上很多开源代码发布的惯用方式:
1、 预编译的开发包:包含一些.dll文件和一些.lib文件。其中这里的.lib就是导入库,而不要错以为是静态库。但是引入方式和静态库一样,要在链接路径上添加找到这些.lib的路径。而.dll则最好放到最后产生的应用程序exe执行文件相同的目录。这样运行时,就会自动调入动态链接库。
2、 用户自己编译:下载的是源代码,按照readme自己编译。生成很可能也是.dll + .lib(导入库)的库文件
3、 如果你只有dll,并且你知道dll中函数的函数原型,那么你可以直接在自己程序中使用LoadLibary调入DLL文件,GetProcAddress获取函数地址,然后调用。
DLL文件
动态链接库 (DLL) 是作为共享函数库的可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个 DLL 副本的内容。
动态链接与静态链接的不同之处在于它允许可执行模块(.dll 文件或 .exe 文件)仅包含在运行时定位 DLL 函数的可执行代码所需的信息。在静态链接中,链接器从静态链接库获取所有被引用的函数,并将库同代码一起放到可执行文件中。
使用动态链接代替静态链接有若干优点。DLL 节省内存,减少交换操作,节省磁盘空间,更易于升级,提供售后支持,提供扩展 MFC 库类的机制,支持多语言程序,并使国际版本的创建轻松完成。
API 就是应用程序编程接口。它是能用来操作组件、应用程序或者操作系统的一组函数。典型的情况下,API 由一个或多个提供某种特殊功能的 DLL 组成。
DLL 是一个文件,其中包含了在 Microsoft Windows下运行的任何应用程序都可调用的函数。运行时,DLL 中的函数动态地链接到调用它的应用程序中。无论有多少应用程序调用 DLL 中的某个函数,在磁盘上只有一个文件包含该函数,且只在它调入内存时才创建该 DLL。 您听到最多的 API 可能是 Windows API,它包括构成 Windows 操作系统的各种 DLL。每个 Windows 应用程序都直接或间接地与 Windows API 互动。Windows API 保证 Windows 下运行的所有应用程序的行为方式一致。
随着 Windows 操作系统的发展,现已发布了几个版本的 Windows API。Windows 3.1 使用 Win16 API。Microsoft Windows NT、Windows 95 和 Windows 98平台使用 Microsoft Win32 API。除 Windows API 外,其他一些 API 也已发布。例如,邮件应用程序编程接口 (MAPI) 是一组可用于编写电子邮件应用程序的 DLL。API 传统上是为开发 Windows 应用程序的 C 和 C++ 程序员编写的,但其他的编程语言(包括VBA)也可以调用 DLL 中的函数。因为大部分 DLL 主要是为 C 和 C++ 程序员编写和整理说明的,所以调用 DLL 函数的方法与调用 VBA 函数会有所不同。在使用 API 时必须了解如何给 DLL 函数传递参数。
警告:调用 Windows API 和 其他 DLL 函数可能会给您的应用程序带来不良影响。从自己的代码中直接调用 DLL 函数时,您绕过了 VBA 通常提供的一些安全机制。如果在定义或调用 DLL 函数时出现错误(所有程序员都不可避免),可能会在应用程序中引起应用程序错误(也称为通用性保护错误,或 GPF)。最好的解决办法是在运行代码以前保存该项目,并确保了解 DLL 函数调用的原理。
H. 动态库和静态库的区别
我们通常把一些公用函数制作成函数库,供其它程序使用。
函数库分为静态库和动态库两种。
静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。
在创建函数库前,我们先来准备举例用的源程序,并将函数库的源程序编译成.o文件。
第1步:编辑得到举例的程序--hello.h、hello.c和main.c;
hello.h(见程序1)为该函数库的头文件。
hello.c(见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"Hello XXX!"。
main.c(见程序3)为测试库文件的主程序,在主程序中调用了公用函数hello。
程序1: hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
程序2: hello.c
#include
void hello(const char *name)
{
printf("Hello %s!/n", name);
}
程序3: main.c
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
第2步:将hello.c编译成.o文件;
无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。
在系统提示符下键入以下命令得到hello.o文件。
# gcc -c hello.c
#
(注1:本文不介绍各命令使用和其参数功能,若希望详细了解它们,请参考其他文档。)
(注2:首字符"#"是系统提示符,不需要键入,下文相同。)
我们运行ls命令看看是否生存了hello.o文件。
# ls
hello.c hello.h hello.o main.c
#
(注3:首字符不是"#"为系统运行结果,下文相同。)
在ls命令结果中,我们看到了hello.o文件,本步操作完成。
下面我们先来看看如何创建静态库,以及使用它。
第3步:由.o文件创建静态库;
静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令。
在系统提示符下键入以下命令将创建静态库文件libmyhello.a。
# ar cr libmyhello.a hello.o
#
我们同样运行ls命令查看结果:
# ls
hello.c hello.h hello.o libmyhello.a main.c
#
ls命令结果中有libmyhello.a。
第4步:在程序中使用静态库;
静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将公用函数连接到目标文件中。注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件。
在程序3:main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公用函数hello。下面先生成目标程序hello,然后运行hello程序看看结果如何。
# gcc -o hello main.c -L. -lmyhello
# ./hello
Hello everyone!
#
我们删除静态库文件试试公用函数hello是否真的连接到目标文件 hello中了。
# rm libmyhello.a
rm: remove regular file `libmyhello.a'? y
# ./hello
Hello everyone!
#
程序照常运行,静态库中的公用函数已经连接到目标文件中了。
我们继续看看如何在Linux中创建动态库。我们还是从.o文件开始。
第5步:由.o文件创建动态库文件;
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyhello.so。用gcc来创建动态库。
在系统提示符下键入以下命令得到动态库文件libmyhello.so。
# gcc -shared -fPCI -o libmyhello.so hello.o
#
我们照样使用ls命令看看动态库文件是否生成。
# ls
hello.c hello.h hello.o libmyhello.so main.c
#
第6步:在程序中使用动态库;
在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们先运行gcc命令生成目标文件,再运行它看看结果。
# gcc -o hello main.c -L. -lmyhello
# ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory
#
哦!出错了。快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。我们将文件 libmyhello.so复制到目录/usr/lib中,再试试。
# mv libmyhello.so /usr/lib
# ./hello
Hello everyone!
#
成功了。这也进一步说明了动态库在程序运行时是需要的。
我们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情,来试试看。
先删除 除.c和.h外的 所有文件,恢复成我们刚刚编辑完举例程序状态。
# rm -f hello hello.o /usr/lib/libmyhello.so
# ls
hello.c hello.h main.c
#
在来创建静态库文件libmyhello.a和动态库文件libmyhello.so。
# gcc -c hello.c
# ar cr libmyhello.a hello.o
# gcc -shared -fPCI -o libmyhello.so hello.o
# ls
hello.c hello.h hello.o libmyhello.a libmyhello.so main.c
#
通过上述最后一条ls命令,可以发现静态库文件libmyhello.a和动态库文件libmyhello.so都已经生成,并都在当前目录中。然后,我们运行gcc命令来使用函数库myhello生成目标文件hello,并运行程序 hello。
# gcc -o hello main.c -L. -lmyhello
# ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory
#
从程序hello运行的结果中很容易知道,当静态库和动态库同名时, gcc命令将优先使用动态库。
I. 程序员说的库是什么
在计算机科学中,库是用于开发软件的子程序集合。库和可执行文件的区别是,库不是独立程序,他们是向其他程序提供服务的代码。