1. 为什么有的模型要编译成库文件
库文件:
一句话概述:
将函数封装起来,放在里面,提供接口,供调用。
库文件可以说是程序员必须接触的东西,我们常听说库,什么编码库,xx库啊等等,这些库,其实它的前身仍然是代码(跟我们平常写的.c等等这些文件差不多),只不过,它编译生成的不再是程序(里面没有main),而只是类似于头文件之类的,只提供接口,给别人调用。
好处:
①把常用的放在库中,需要的就直接调用(可以添加头文件来进行声明,否则,会隐式声明)
②把不想公开的代码放在库中,但是留出头文件,给出接口,让其他人使用。
怎么编译生成库:
预备知识:
库文件包括动态库,以及静态库。
动态库是指编译的时候不把这个库文件所需要的东西编译进去,而是在执行的时候再到库中寻找相应的内容;
静态库是指吧程序所需的函数从库中拿出来,然后编译进程序里面,后续执行就不再需要库了。
双方各有好处,前者,明显的好处就是程序文件更小,而后者程序文件比较大,但是,运行不需要其他的库支持。
过程:
主要为4大过程:
①代码,常规书写,不用写main,然后,下一步,编译:
代码大致如下:
(1).c文件如下:
#include <stdio.h>
void print_hello()
{
printf("hello everybody\n");
}
1
2
3
4
5
6
1
2
3
4
5
6
.h文件:
#ifndef __HELLO_H__
#define __HELLO_H
void print_hello(); //这个可用,也可不用,不用的话,就变成隐式声明。
#endif
1
2
3
4
1
2
3
4
②gcc -c hello.c //这一步是为了生成目标文件,但是,其实不需要它也行,不过,它是生成静态库与动态库的中间状态。
③ ar cr libmyhello.a hello.o //生成libmyhello.a 这么一个静态库,注意命名规则libxxx.a
④编译执行程序:gcc xxx.c -o xxx -L ./libmyhello.a // 调用方法1;
gcc xxx.c -o xxx -lmyhello //调用方法2,此时,需要-l后面自动补了,但是,需要放到设备的lib环境变量中
执行程序:
#include <stdio.h>
#include "hello.h"
int main()
{
print_hello(); //能调用库里面的函数,输出“hello everybody”
return 0;
}
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
动态库:
①②同上;
③gcc -fPIC -shared -o libmyfirstso.so myfirstso.c //生成了动态库,注意命名规则;
④编译执行程序:gcc xxx.c -o xxx -L ./libmyfirstso.so //方法1;
gcc xxx.c -o xxx -lmyfirstso //方法2,同上,需要放到设备的lib环境变量中
当然,也可以将他们混合在一起编译也行,如果是想指定路径的话,直接指定即可,如:-L ./lib/libmyfirstso.so
总结:
库文件非常重要,有以下三点需要注意:
①需要了解的是静态库与动态库的区别;
②需要掌握静态库的生成指令(ar cr libhello.a hello.o)、动态库生成指令(gcc -fPIC -shared -o libhelloso.so hello.o);
③需要掌握如何利用库编译执行程序(-L ./libhello.a ; -lhello)(两种方法)
2. Solaris下如何编译生成动态库
解决编译问题或者做补丁时需要更新文件,然后单独编译某个工程,生成相应的动态库,Windows下界面操作可以很方便的实现编译相应的工程,生成.dll文件,而Solaris下是命令行操作,编译生成的动态库为.so格式,主要有以下几个步骤:
1.更新
a.更新文件夹
cd到文件夹所在目录,执行如下命令行
cleartool update -ove 文件夹名
例如:cd /......../server/include
Cleartool update –ove foldername
完成对文件夹foldername的更新
b.更新文件
cd到文件所在目录,执行如下命令行
cleartool update -ove ./文件名
例如:cd /.../include/
cleartool update –ove filename.h
完成对文件filename.h的更新
2.编译
更新完毕后需要重新编译生成新的动态库
a.首先cd到makefile文件夹下
例如:cd /..../makefile
b.执行环境变量
. ./setenv.sh
c.编译相应的makefile文件
gmake –f makefile文件
例如:gmake –f makefilename.makefile
完成对makefilename.makefile的编译。
生成的动态库目录:
/.../server/lib/release
3. c++中如何把类编译成类似于库文件,以后直接包含头文件即可
请搜索“nmake makefile cl.exe lib”之类的关键字。
比如
-------------------------------
CL.exe
CL.exe是控制Microsoft C和C++编译器与链接器的32位工具。编译器产生通用对象文件格式(COFF)对象(.obj)文件。链接器产生可执行文件(.exe)或动态链接库文件(DLL)。注意,所有编译器选项都区分大小写。若要编译但不链接,请使用/c。使用NMAKE生成输出文件。使用BSCMAKE支持类浏览。以下是一个完整的编译器选项分类列表。
优化
选项 作用
/O1 创建小代码
/O2 创建快速代码
/Oa 假设没有别名
/Ob 控制内联展开
/Od 禁用优化
/Og 使用全局优化
/Oi 生成内部函数
/Op 改善浮点数一致性
/Os 代码大小优先
/Ot 代码速度优先
/Ow 假定在函数调用中使用别名
/Ox 使用最大优化 (/Ob1gity /Gs)
/Oy 省略框架指针
代码生成
选项 作用
/clr 启用C++的托管扩展并产生在公共语言运行库上运行的输出文件
/EH 指定异常处理模型
/G3 优化代码以优选386处理器。在Visual C++ 5.0 中已经停用,编译器将忽略此选项
/G4 优化代码以优选486处理器。在 Visual C++ 5.0中已经停用,编译器将忽略此选项
/G5 优化代码以优选Pentium
/GB 与/G6等效;将_M_IX86的值设置为600
/Gd 使用__cdecl调用约定
/Ge 激活堆栈探测
/GF 启用字符串池
/GH 调用挂钩函数 _penter
/GL 启用全程序优化
/Gm 启用最小重新生成
/Gr 启用运行时类型信息 (RTTI)
/Gr 使用__fastcall调用约定
/GS 控制堆栈探测
/GT 支持使用静态线程本地存储区分配的数据的纤程安全
/GX 启用同步异常处理
/Gy 启用函数级链接
/GZ 使用__stdcall调用约定
/MD 使用MSVCRT.lib创建多线程DLL
/MDd 使用MSVCRTD.lib 创建调试多线程DLL
/ML 使用LIBC.lib 创建单线程可执行文件
/MLd 使用LIBCD.lib 创建调试单线程可执行文件
/MT 使用LIBCMT.lib创建多线程可执行文件
/MTd 使用LIBCMTD.lib创建调试多线程可执行文件
输出文件
选项 作用
/FA 创建列表文件设置列表文件名
/Fd 重命名程序数据库文件
/Fe 重命名可执行文件
/Fm 创建映射文件
/Fo 创建对象文件
/Fp 指定预编译头文件名
/FR 生成浏览器文件
/Fx 将插入的代码与源文件合并
……
链接
选项 作用
/F 设置堆栈大小
/LD 创建动态链接库
/LDd 创建调试动态链接库
/link 将指定的选项传递给LINK
/MD 使用MSVCRT.lib编译以创建多线程DLL
/MDd 使用MSVCRTD.lib编译以创建调试多线程DLL
/ML 使用LIBC.lib编译以创建单线程可执行文件
/MLd 使用LIBCD.lib编译以创建调试单线程可执行文件
/MT 使用LIBCMT.lib编译以创建多线程可执行文件
/MTd 使用 LIBCMTD.lib 编译以创建调试多线程可执行文件
……
……
……
更多的我就不贴出来了。。。msdn中对nmake作了详细说明的。
下面一个nmake的makefile例子:
#命令
CC=cl.exe
DEL=del /Q /S
#头文件与库文件目录
INCLUDES=
LIBS=
#编译链接选项与宏定义
MT=MD ---------------(1)
DEFS=-DWIN32
MOD= ---------------(2)
#输出文件
OUTPUT=test.exe
OBJS=main.obj
#内部变量
CFLAGS=/$(MT) $(INCLUDES) $(DEFS) /nologo
LINK=link $(MOD) /OUT:"$(OUTPUT)"
#依赖关系
all:$(OBJS)
$(LINK) $(OBJS)
main.obj:
$(CC) $(CFLAGS) main.cpp -Fo%|fF.obj
clean:
del /Q /S $(OBJS) $(OUTPUT)*
(1):
MD 使用MSVCRT.lib创建多线程DLL
MDd 使用MSVCRTD.lib 创建调试多线程 DLL
ML 使用LIBC.lib创建单线程可执行文件
MLd 使用LIBCD.lib创建调试单线程可执行文件
MT 使用LIBCMT.lib创建多线程可执行文件
MTd 使用LIBCMTD.lib创建调试多线程可执行文件
(2):
为空 生成可执行文件
/LIB 生成静态链接库
/DLL 生成动态链接库
4. c++中如何把类编译成类似于库文件,以后直接包含头文件即可
使用两个文件,一个为 文件名.h,一个为 文件名.cpp
文件名.h里这么写:
#ifndef (这里随便写,最好是文件名)_FILE_H_
#define _FILE_H_
//类的声明
#endif
文件名.cpp里这么写
#include "文件名.h"
//类的实现
注意类的实现函数名前面加 类名::
编译,编译器只会编译cpp文件。这时就可以通过包含h文件去使用类了。如果是其他工程使用,只需要拷贝obj文件和h文件就行了。
那个被编译成了lib文件,放在了头文件所在的include文件夹同层的lib文件夹下
5. 如何将源文件编译成库文件
问题说的不是很清楚!
如果你是希望你编的函数能像库函数那样直接调用的话
可以把你的函数放到一个文件里
如果以后你那个程序需要这些函数时直接包含该文件就行了
像使用头文件那样#include"myfile.c"( 注意这里是用双引号)
然后在你程序中就可以直接调用你自定义的函数了
如果我理解题目错误,敬请原谅!
【原创答人】
6. 怎么用Keil将C程序封装成lib库
在团队工作中,经常会有模块维护和代码封装的问题。把需要封装的代码打成一个lib无疑是一种很好的方式。
1.创建lib
创建一个lib很容易,只需要创建一个target,然后把需要封装的代码全部加进来,然后再Options of Target中选择Create Library,然后编译,因为是lib所以不需要链接,编译过了,你的lib就创建了。当然了,为了别人可以轻松的使用,请提供头文件支持哦。
2.使用lib
使用lib就更容易了,把lib和头文件加入你的工程,直接调用就是了。lib库会和你工程中其它编译后的obj一起链接,形成最后的目标文件。
3.注意事项
首先,Startup和中断处理程序不要封入LIB,这些程序会在链接的时候产生问题。具体的原因么,有点复杂,应该是中断程序的link机制有所不同的关系吧。
其次,Lib的文件要分的细一点,没有调用关系的两个函数不要放到同一个C文件中,因为LIB51在链接的时候是按模块来链接的,一个模块就对应一个C文件,假如链接器因为要使用你一个函数fA而引入了A模块,那么A模块中的另外的函数也会被引入,而另外的函数你又没有使用的话,那么就会引发Keil经典的UNCALLED FUNC的warning。这个warning在Keil的文档中说的好清楚了,我粘过来吧:
It is common practice ring the development process to write but not call
additional functions. While the compiler permits this without error, the
Linker/Locator does not treat this code casually because of the support for data
overlaying, and emits a warning message.
Interrupt functions are never called, they are invoked by the hardware. An
uncalled routine is treated as a potential interrupt routine by the linker. This
means that the function is assigned non-overlayable data space for its local
variables. This quickly exhausts all available data memory (depending upon the
memory model used).
If you unexpectedly run out of memory, be sure to check for linker warnings
relating to uncalled or unused routines. You can use the linker’s IXREF
directive to include a cross reference list in the linker map (.M51) file.
大意就是说,Keil的内存应用模式是指定地址的,也就是要根据调用关系来决定哪块地址可以被复用。对于这种没人调用的函数,Keil会认为是中断处理程序,并不能决定调用关系,所以此类uncalled函数的空间不能和其他的程序共享,也就是说,这函数用多少RAM,你就少多少RAM。那uncall多了会怎么样?----废话,当然是内存溢出了。
所以,lib的功能可以做的大而全,但是里面的模块一定要分的要多细,有多细,只有这样,你才能像在windows上用CRT一样舒服的使用LIB。
个人总结
1. 生成lib 的工程可以没有main函数,可以只有一个.c文件,一个.c文件中可以只有一个函数
2. 需要在lib工程中建立一个.h文件, 必须用extern声明各全局变量和函数.
3. 调用lib文件的工程中必须包括lib中的.h文件, 也就是lib工程和调用工程都包含同一个.h文件(好像有点废话)
4.Lib的文件要分的细一点,没有调用关系的两个函数不要放到同一个C文件中. 没有调用关系的最好是一个函数单独放在一个.c文件中.这是为了避免在keil中应用程序调用lib库里出现告警. 因为LIB51在链接的时候是按模块来链接的,一个模块就对应一个C文件,假如链接器因为要使用你一个函数fA而引入了A模块,那么A模块中的另外的函数也会被引入,而另外的函数你又没有使用的话,那么就会引发Keil经典的UNCALLED FUNC的warning。
通常为每一个函数编一个.C文件,而整个lib用一个.h文件,这样就可以使只有被调用的函数参与连接
5.调用lib库时需要在工程中将.lib文件加进来. 在Group中右键,然后Add ,注意文件类型中选择*.lib.
7. C++通过什么编译器编译成的静态库给ios调用
用的是gcc编译器或者xcode编译就可以。
在开发过程中,经常会碰到一些在不同工程中经常用到的部分,把这些部分抽取出来做成一个静态库往往是一个比较好的做法。xcode里就有制作静态库的模板,相关的制作步骤网上也有很多,但在实际的操作中,还是有不少细节方面需要注意。以下是我碰到的一些问题总结。
1.编译release版本的库
在“Manage Schemes”中,将“Build Configuration”的选项改为“Release”即可。如图:
2.静态库中包含category
如果你在静态库工程中使用了category,那么你可能会碰到链接问题,解决的办法就是需要同时在生成静态库的工程和使用静态库的工程中使用“-all_load”编译选项,即在对应target的"Build Settings"中的“Other Linker Flags”选项添加“-all_load”。注意:使用静态库的工程中是一定要加该编译选项的!!至于生成静态库的工程中加不加没有试过,不过建议还是加上该编译选项。
3.静态库支持的SDK版本
为了使自己的静态库尽可能多的支持IOS的系统版本,应该在"IOS Deployment Target"这个选项中选择自己所需的IOS版本。设置如下图,这个是我的静态库工程中的配置,红框框起来的是我修改过的选项。
4.自动拷贝头文件
在工程对应的target的“Build Phases”下添加“Copy Headers”的选项。该选项默认是没有的,添加方法是点击下方的“Add Build Phase”按钮后选择后即可添加。该选项下有3个子选项,分别是Public,Private,Project。通过点击下方的加号,可以将工程中的头文件添加到“Project”中,在其中的对应头文件点击右键,选择“Move to Public Group”,当头文件移到“Pulic”后,编译工程以后,在工程编译后.a文件所在的路径下,会同时出现一个"usr/local/include"的文件夹,其中的头文件就是public group中的头文件。这时只需将.a文件和这个路径下的头文件拷贝到所需工程文件即可。
转载
8. vxworks新建工程,和如何生成库文件及如何使用
File-New-Vxworks Downloadable Kernel MoleProject 如下图
弹出
输入工程名点击next
点击next
点击next
点击next
在红线出选择相应的编译器点击next
红线处是决定生成什么样的文件。例如Linker是生成可执行文件。尔下图是生成动态链接库
然后点击next再finish
生成的库怎么用
把生成库文件(文件名为*.a)的路径及文件名复制到下图位置
右键工程选择属性点击build Properties-build Macros弹出
在Image工程也是使用空格分开
注意:斜杠是“/”
9. 哪位知道TI公司的CCS3.3怎么生成l自己库文件文件吗比如把某些算法制作成库文件来使用。
依次点击project--new,在新建一个工程的时候,在弹出的对话框里有一个选项是选择编译输出文件,有out文件和lib文件可选,选择lib,则工程编译通过后是生成库文件。
10. vs 命令行编译静态库
_declspec(dllexport) void test_print(char* sz_input);
这是动态链接库 -- dllexport ,dll是动态链接库。
不是你说的静态库。
动态链接库,应用程序调用它,编译链接时要有.lib, 运行时要有.dll
Debug\ -- 给别的程序用,要用 Release\,不能用 Debug\
char * __ptr64 sz_input;
__ptr64 -- 32位机上,指针sz_input截断为32位.
char * __ptr32 sz_input;
__ptr32 -- 64位机上,指针sz_input变32位
wchar_t,_MBCS -- 表明你要用双字节字符,那么程序就不应当用 单字节char 型。如果你要编的不是要用双字节字符,那么 就不要 wchar_t,_MBCS。