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。