導航:首頁 > 源碼編譯 > BCB編譯message在哪

BCB編譯message在哪

發布時間:2023-07-15 12:20:42

Ⅰ altium designer 編譯PCB之後message 面板 怎麼沒信息

如果你的操作是正常的話,那麼應該恭喜你,你的設計完全正確。
如果這個message 面板沒找到,可以在左正角的「system」中找到它。
當然,這里編譯說完全正確,只是根據你的原理圖和你的PCB規則編譯的,如果原理圖有問題,或者PCB規則不對,結果還是有問題的。

Ⅱ 關於C語言預處理命令

第一句有問題。
比如
#ifndef WIN32
#endif printf("OK\n");
在這里,這個printf就不會被執行。也就是說, 一行中, 只能有一條預處理指令,
當編譯的預處理階段, 編譯器識別了一條完整的預處理指令後,後面的所有東西他都不要了。
對於第二句,在函數里,我們是可以使用預處理指令的。
比如
void fun(void)
{
#ifdef WIN32
... // 對於windows系統環境的操作
#else
... // 對於windows以外的系統環境的操作
#endif /* WIN32 */
...
}

樓上的同學, 你是在哪兒本書上看的? 介紹一下唄

Ⅲ 在IAR上,怎樣查看編譯的信息

在View中打開Message窗口,在窗口中右鍵選擇options,在出來的對話框中的 Show build message:後面選擇編譯信息顯示的詳細程度,點擊確定後編譯一下,你就能在Message窗口中看到編譯信息了。

Ⅳ pragma message輸出在哪

Message 參數能夠在編譯信息輸出窗口中輸出相應的信息,這對於源代碼信息的控制是非常重要的。其使用方法為: #pragma message(消息文本)當編譯器遇到這條指令時就在編譯輸出窗口中將消息文本列印出來。
當我們在程序中定義了許多宏來控制源代碼版本的時候,我們自己有可能都會忘記有沒有正確的設置這些宏,此時我們可以用這條指令在編譯的時候就進行檢查。假設我們希望判斷自己有沒有在源代碼的什麼地方定義了_X86這個宏可以用下面的方法 #ifdef _X86#pragma message(_X86 macro activated!)#endif當我們定義了_X86這個宏以後,應用程序在編譯時就會在編譯輸出窗口裡顯示「_X86 macro activated! 」。我們就不會因為不記得自己定義的一些特定的宏而抓耳撓腮了。 (比較常用)
只要在頭文件的最開始加入這條指令就能夠保證頭文件被編譯一次,這條指令實際上在VC6中就已經有了,但是考慮到兼容性並沒有太多的使用它。
#pragma once是編譯相關,就是說這個編譯系統上能用,但在其他編譯系統不一定可以,也就是說移植性差,不過現在基本上已經是每個編譯器都有這個定義了。
#ifndef,#define,#endif這個是C++語言相關,這是C++語言中的宏定義,通過宏定義避免文件多次編譯。所以在所有支持C++語言的編譯器上都是有效的,如果寫的程序要跨平台,最好使用這種方式 #pragma hdrstop表示預編譯頭文件到此為止,後面的頭文件不進行預編譯。BCB可以預編譯頭文件以加快鏈接的速度,但如果所有頭文件都進行預編譯又可能占太多磁碟空間,所以使用這個選項排除一些頭文件。
有時單元之間有依賴關系,比如單元A依賴單元B,所以單元B要先於單元A編譯。你可以用#pragma startup指定編譯優先順序,如果使用了#pragma package(smart_init) ,BCB就會根據優先順序的大小先後編譯。 #pragma comment(...)該指令將一個注釋記錄放入一個對象文件或可執行文件中。
常用的lib關鍵字,可以幫我們連入一個庫文件。
每個編譯程序可以用#pragma指令激活或終止該編譯程序支持的一些編譯功能。例如,對循環優化功能: #pragma loop_opt(on)//激活#pragma loop_opt(off)//終止有時,程序中會有些函數會使編譯器發出你熟知而想忽略的警告,如「Parameter xxx is never used in function xxx」,可以這樣: #pragma warn—100//#100intinsert_record(REC*r){/*functionbody*/}#pragma warn+100//#100backon函數會產生一條有唯一特徵碼100的警告信息,如此可暫時終止該警告。
每個編譯器對#pragma的實現不同,在一個編譯器中有效在別的編譯器中幾乎無效。可從編譯器的文檔中查看。 #pragma pack(n)和#pragm apop()struct sample{char a;double b;};當sample結構沒有加#pragma pack(n)的時候,sample按最大的成員那個對齊;
(所謂的對齊是指對齊數為n時,對每個成員進行對齊,既如果成員a的大小小於n則將a擴大到n個大小;
如果a的大小大於n則使用a的大小;)所以上面那個結構的大小為16位元組.
當sample結構加#pragma pack(1)的時候,sizeof(sample)=9位元組;無空位元組。
(另註:當n大於sample結構的最大成員的大小時,n取最大成員的大小。
所以當n越大時,結構的速度越快,大小越大;反之則)
#pragma pop()就是取消#pragma pack(n)的意思了,也就是說接下來的結構不用#pragma pack(n) #pragma comment(comment-type,[commentstring])comment-type是一個預定義的標識符,指定注釋的類型,應該是compiler,exestr,lib,linker之一。
comment string是一個提供為comment-type提供附加信息的字元串。
注釋類型:
1、compiler:
放置編譯器的版本或者名字到一個對象文件,該選項是被linker忽略的。
2、exestr:
在以後的版本將被取消。
3、lib:
放置一個庫搜索記錄到對象文件中,這個類型應該是和comment string(指定你要Linker搜索的lib的名稱和路徑)這個庫的名字放在Object文件的默認庫搜索記錄的後面,linker搜索這個這個庫就像你在命令行輸入這個命令一樣。你可以在一個源文件中設置多個庫記錄,它們在object文件中的順序和在源文件中的順序一樣。如果默認庫和附加庫的次序是需要區別的,使用Z編譯開關是防止默認庫放到object模塊。
4、linker:
指定一個連接選項,這樣就不用在命令行輸入或者在開發環境中設置了。
只有下面的linker選項能被傳給Linker. /DEFAULTLIB,/EXPORT,/INCLUDE,/MANIFESTDEPENDENCY,/MERGE,/SECTION(1) /DEFAULTLIB:library
/DEFAULTLIB 選項將一個 library 添加到 LINK 在解析引用時搜索的庫列表。用 /DEFAULTLIB指定的庫在命令行上指定的庫之後和 .obj 文件中指定的默認庫之前被搜索。忽略所有默認庫 (/NODEFAULTLIB) 選項重寫 /DEFAULTLIB:library。如果在兩者中指定了相同的 library 名稱,忽略庫 (/NODEFAULTLIB:library) 選項將重寫 /DEFAULTLIB:library。
(2)/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
使用該選項,可以從程序導出函數,以便其他程序可以調用該函數。也可以導出數據。通常在 DLL 中定義導出。entryname是調用程序要使用的函數或數據項的名稱。ordinal 在導出表中指定范圍在 1 至 65,535 的索引;如果沒有指定 ordinal,則 LINK 將分配一個。NONAME關鍵字只將函數導出為序號,沒有 entryname。
DATA 關鍵字指定導出項為數據項。客戶程序中的數據項必須用 extern __declspec(dllimport)來聲明。
有三種導出定義的方法,按照建議的使用順序依次為:
源代碼中的 __declspec(dllexport).def 文件中的 EXPORTS 語句LINK 命令中的 /EXPORT 規范所有這三種方法可以用在同一個程序中。LINK 在生成包含導出的程序時還創建導入庫,除非生成中使用了 .exp 文件。
LINK 使用標識符的修飾形式。編譯器在創建 .obj 文件時修飾標識符。如果 entryname以其未修飾的形式指定給鏈接器(與其在源代碼中一樣),則 LINK 將試圖匹配該名稱。如果無法找到唯一的匹配名稱,則 LINK 發出錯誤信息。當需要將標識符指定給鏈接器時,請使用 Dumpbin 工具獲取該標識符的修飾名形式。
(3)/INCLUDE:symbol
/INCLUDE 選項通知鏈接器將指定的符號添加到符號表。
若要指定多個符號,請在符號名稱之間鍵入逗號 (,)、分號 (;) 或空格。在命令行上,對每個符號指定一次 /INCLUDE:symbol。
鏈接器通過將包含符號定義的對象添加到程序來解析 symbol。該功能對於添包含不會鏈接到程序的庫對象非常有用。用該選項指定符號將通過 /OPT:REF 重寫該符號的移除。
我們經常用到的是#pragma comment(lib,*.lib)這類的。#pragma comment(lib,Ws2_32.lib)表示鏈接Ws2_32.lib這個庫。 和在工程設置里寫上鏈入Ws2_32.lib的效果一樣,不過這種方法寫的 程序別人在使用你的代碼的時候就不用再設置工程settings了 介紹
用#pragma data_seg建立一個新的數據段並定義共享數據,其具體格式為: #pragma data_seg(shareddata)HWNDsharedwnd=NULL;//共享數據#pragma data_seg()-----------------------------------------------------------------
1,#pragma data_seg()一般用於DLL中。也就是說,在DLL中定義一個共享的有名字的數據段。最關鍵的是:這個數據段中的全局變數可以被多個進程共享,否則多個進程之間無法共享DLL中的全局變數。
2,共享數據必須初始化,否則微軟編譯器會把沒有初始化的數據放到.BSS段中,從而導致多個進程之間的共享行為失敗。例如, #pragma data_seg(MyData)intg_Value;//.#pragma data_seg()//DLL提供兩個介面函數:int GetValue(){ return g_Value;}void SetValue(int n){ g_Value=n;}然後啟動兩個進程A和B,A和B都調用了這個DLL,假如A調用了SetValue(5); B接著調用int m = GetValue(); 那麼m的值不一定是5,而是一個未定義的值。因為DLL中的全局數據對於每一個調用它的進程而言,是私有的,不能共享的。假如你對g_Value進行了初始化,那麼g_Value就一定會被放進MyData段中。換句話說,如果A調用了SetValue(5); B接著調用int m = GetValue(); 那麼m的值就一定是5,這就實現了跨進程之間的數據通信。 #pragma region是Visual C++中特有的預處理指令。它可以讓你折疊特定的代碼塊,從而使界面更加清潔,便於編輯其他代碼。折疊後的代碼塊不會影響編譯。你也可以隨時展開代碼塊以進行編輯等操作。
格式: #pragma region name#pragma endregion comment使用示例如下: #pragma region VariablesHWND hWnd;const size_t Max_Length = 20;//other variables#pragma endregion This region contains global variables.如上邊所示,需要折疊的代碼必須包含在#pragma region和#pragma endregion之間。#pragma region和#pragma endregion之後可以添加一些用來注釋的文字。當你折疊代碼塊後,這些文字會顯示在折疊的位置。
折疊代碼塊的方法:如同Visual C++中折疊函數、類、命名空間,當代碼被包含在如上所述的指令之間後,#pragma region這一行的左邊會出現一個「-」號,單擊以折疊內容,同時「-」號會變成「+」號,再次單擊可以展開代碼塊。
此預編譯指令在Visual Studio 2005及以上版本可以使用。但是在Visual Studio 2005中,當#pragma region之後包含類似「1st」這類的文字,會導致「error C2059: syntax error : 'bad suffix on number'」的編譯錯誤。避免使用數字或者將數字與字母分離可以解決這個問題。

Ⅳ 預處理指令#pragma db code是什麼意思

一、作用是設定編譯器的狀態或者是指示編譯器完成一些特定的動作。#pragma指令對每個編譯器給出了一個方法,在保持與C和 C++語言完全兼容的情況下,給出主機或操作系統專有的特徵。依據定義,編譯指示是機器或操作系統專有的,且對於每個編譯器都是不同的。

二、常用的pragma指令的詳細解釋。
1.#pragma once。保證所在文件只會被包含一次,它是基於磁碟文件的,而#ifndef則是基於宏的。
2.#pragma warning。允許有選擇性的修改編譯器的警告消息的行為。有如下用法:
#pragma warning(disable:4507 34; once:4385; error:164) 等價於:
#pragma warning(disable:4507 34) // 不顯示4507和34號警告信息
#pragma warning(once:4385) // 4385號警告信息僅報告一次
#pragma warning(error:164) // 把164號警告信息作為一個錯誤
#pragma warning(default:176) // 重置編譯器的176號警告行為到默認狀態
同時這個pragma warning也支持如下格式,其中n代表一個警告等級(1---4):
#pragma warning(push) // 保存所有警告信息的現有的警告狀態
#pragma warning(push,n) // 保存所有警告信息的現有的警告狀態,並設置全局報警級別為n
#pragma warning(pop) // 恢叢 鵲木 孀刺 趐ush和pop之間所做的一切改動將取消
例如:
#pragma warning(push)
#pragma warning(disable:4705)
#pragma warning(disable:4706)
#pragma warning(disable:4707)
#pragma warning(pop)
在這段代碼後,恢復所有的警告信息(包括4705,4706和4707)。
3.#pragma hdrstop。表示預編譯頭文件到此為止,後面的頭文件不進行預編譯。BCB可以預編譯頭文件以 加快鏈接的速度,但如果所有頭文件都進行預編譯又可能占太多磁碟空間,所以使用這個選項排除一些頭文 件。
4.#pragma message。在標准輸出設備中輸出指定文本信息而不結束程序運行。用法如下:
#pragma message("消息文本")。當編譯器遇到這條指令時就在編譯輸出窗口中將「消息文本」列印出來。
5.#pragma data_seg。一般用於DLL中,它能夠設置程序中的初始化變數在obj文件中所在的數據段。如果未指定參數,初始化變數將放置在默認數據段.data中,有如下用法:
#pragma data_seg("Shared") // 定義了數據段"Shared",其中有兩個變數a和b
int a = 0; // 存儲在數據段"Shared"中
int b; // 存儲在數據段".bss"中,因為沒有初始化
#pragma data_seg() // 表示數據段"Shared"結束,該行代碼為可選的
對變數進行專門的初始化是很重要的,否則編譯器將把它們放在普通的未初始化數據段中而不是放在shared中。如上述的變數b其實是放在了未初始化數據段.bss中。
#pragma data_seg("Shared")
int j = 0; // 存儲在數據段"Shared"中
#pragma data_seg(push, stack1, "Shared2") //定義數據段Shared2,並將該記錄賦予別名stack1,然後放入內部編譯器棧中
int l = 0; // 存儲在數據段"Shared2"中
#pragma data_seg(pop, stack1) // 從內部編譯器棧中彈出記錄,直到彈出stack1,如果沒有stack1,則不做任何操作
int m = 0; // 存儲在數據段"Shared"中,如果沒有上述pop段,則該變數將儲在數據段"Shared2"中
6.#pragma code_seg。它能夠設置程序中的函數在obj文件中所在的代碼段。如果未指定參數,函數將放置在默認代碼段.text中,有如下用法:
void func1() { // 默認存儲在代碼段.text中
}
#pragma code_seg(".my_data1")
void func2() { // 存儲在代碼段.my_data1中
}
#pragma code_seg(push, r1, ".my_data2")
void func3() { // 存儲在代碼段.my_data2中
}
#pragma code_seg(pop, r1)
void func4() { // 存儲在代碼段.my_data1中
}
7.#pragma pack。用來改變編譯器的位元組對齊方式。常規用法為:
#pragma pack(n) //將編譯器的位元組對齊方式設為n,n的取值一般為1、2、4、8、16,一般默認為8
#pragma pack(show) //以警告信息的方式將當前的位元組對齊方式輸出
#pragma pack(push) //將當前的位元組對齊方式放入到內部編譯器棧中
#pragma pack(push,4) //將位元組對齊方式4放入到內部編譯器棧中,並將當前的內存對齊方式設置為4
#pragma pack(pop) //將內部編譯器棧頂的記錄彈出,並將其作為當前的內存對齊方式
#pragma pack(pop,4) //將內部編譯器棧頂的記錄彈出,並將4作為當前的內存對齊方式
#pragma pack(pop,r1) //r1為自定義的標識符,將內部編譯器中的記錄彈出,直到彈出r1,並將r1的值作為當前的內存對齊方式;如果r1不存在,當不做任何操作
8.#pragma comment。將一個注釋記錄放置到對象文件或可執行文件中。
其格式為:#pragma comment( comment-type [,"commentstring"] )。其中,comment-type是一個預定義的標識符,指定注釋的類型,應該是compiler,exestr,lib,linker,user之一。
compiler:放置編譯器的版本或者名字到一個對象文件,該選項是被linker忽略的。
exestr:在以後的版本將被取消。
lib:放置一個庫搜索記錄到對象文件中,這個類型應該與commentstring(指定Linker要搜索的lib的名稱和路徑)所指定的庫類型一致。在對象文件中,庫的名字跟在默認搜索記錄後面;linker搜索這個這個庫就像你在命令行輸入這個命令一樣。你可以在一個源文件中設置多個庫搜索記錄,它們在obj文件中出現的順序與在源文件中出現的順序一樣。
如果默認庫和附加庫的次序是需要區別的,使用/Zl編譯開關可防止默認庫放到object模塊中。
linker:指定一個連接選項,這樣就不用在命令行輸入或者在開發環境中設置了。只有下面的linker選項能被傳給Linker:
/DEFAULTLIB
/EXPORT
/INCLUDE
/MANIFESTDEPENDENCY
/MERGE
/SECTION
(1)/DEFAULTLIB:library
/DEFAULTLIB選項將一個library添加到LINK在解析引用時搜索的庫列表。用/DEFAULTLIB指定的庫在命令行上指定的庫之後和obj文件中指定的默認庫之前被搜索。
忽略所有默認庫(/NODEFAULTLIB)選項重寫/DEFAULTLIB:library。如果在兩者中指定了相同的library名稱,忽略庫(/NODEFAULTLIB:library)選項將重寫/DEFAULTLIB:library。
(2)/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
使用該選項,可以從程序導出函數以便其他程序可以調用該函數,也可以導出數據。通常在DLL中定義導出。
entryname是調用程序要使用的函數或數據項的名稱。ordinal為導出表的索引,取值范圍在1至65535;如果沒有指定ordinal,則LINK將分配一個。NONAME關鍵字只將函數導出為序號,沒有entryname。DATA 關鍵字指定導出項為數據項。客戶程序中的數據項必須用extern __declspec(dllimport)來聲明。
有三種導出定義的方法,按照建議的使用順序依次為:
源代碼中的__declspec(dllexport)
.def文件中的EXPORTS語句
LINK命令中的/EXPORT規范
所有這三種方法可以用在同一個程序中。LINK在生成包含導出的程序時還要創建導入庫,除非在生成過程中使用了.exp 文件。
LINK使用標識符的修飾形式。編譯器在創建obj文件時修飾標識符。如果entryname以其未修飾的形式指定給鏈接器(與其在源代碼中一樣),則LINK將試圖匹配該名稱。如果無法找到唯一的匹配名稱,則LINK發出錯誤信息。當需要將標識符指定給鏈接器時,請使用Dumpbin工具獲取該標識符的修飾名形式。
(3)/INCLUDE:symbol
/INCLUDE選項通知鏈接器將指定的符號添加到符號表。若要指定多個符號,請在符號名稱之間鍵入逗號(,)、分號(;)或空格。在命令行上,對每個符號需指定一次/INCLUDE:symbol。
鏈接器通過將包含符號定義的對象添加到程序來解析symbol。該功能對於添加不會鏈接到程序的庫對象非常有用。
用該選項所指定的符號將覆蓋通過/OPT:REF對該符號進行的移除操作。
(4)/MANIFESTDEPENDENCY:manifest_dependency
/MANIFESTDEPENDENCY允許你指定位於manifest文件的段的屬性。/MANIFESTDEPENDENCY信息可以通過下面兩種方式傳遞給LINK:
直接在命令行運行/MANIFESTDEPENDENCY
通過#pragma comment
(5)/MERGE:from=to
/MERGE選項將第一個段(from)與第二個段(to)進行聯合,並將聯合後的段命名為to的名稱。
如果第二個段不存在,LINK將段(from)重命名為to的名稱。
/MERGE選項對於創建VxDs和重寫編譯器生成的段名非常有用。
(6)/SECTION:name,[[!]{DEKPRSW}][,ALIGN=#]
/SECTION選項用來改變段的屬性,當指定段所在的obj文件編譯的時候重寫段的屬性集。
可移植的可執行文件(PE)中的段(section)與新可執行文件(NE)中的節區(segment)或資源大致相同。
段(section)中包含代碼或數據。與節區(segment)不同的是,段(section)是沒有大小限制的連續內存塊。有些段中的代碼或數據是你的程序直接定義和使用的,而有些數據段是鏈接器和庫管理器(lib.exe)創建的,並且包含了對操作系統來說很重要的信息。
/SECTION選項中的name是大小寫敏感的。
不要使用以下名稱,因為它們與標准名稱會沖突,例如,.sdata是RISC平台使用的。
.arch
.bss
.data
.edata
.idata
.pdata
.rdata
.reloc
.rsrc
.sbss
.sdata
.srdata
.text
.xdata
為段指定一個或多個屬性。屬性不是大小寫敏感的。對於一個段,你必須將希望它具有的屬性都進行指定;如果某個屬性未指定,則認為是不具備這個屬性。如果你未指定R,W或E,則已存在的讀,寫或可執行狀態將不發生改變。
要對某個屬性取否定意義,只需要在屬性前加感嘆號(!)。
E:可執行的
R:可讀取的
W:可寫的
S:對於載入該段的鏡像的所有進程是共享的
D:可廢棄的
K:不可緩存的
P:不可分頁的
注意K和P是表示否定含義的。
PE文件中的段如果沒有E,R或W屬性集,則該段是無效的。
ALIGN=#選項讓你為一個具體的段指定對齊值。
user:放置一個常規注釋到一個對象文件中,該選項是被linker忽略的。
9.#pragma section。創建一個段。
其格式為:#pragma section( "section-name" [, attributes] )
section-name是必選項,用於指定段的名字。該名字不能與標准段的名字想沖突。可用/SECTION查看標准段的名稱列表。
attributes是可選項,用於指定段的屬性。可用屬性如下,多個屬性間用逗號(,)隔開:
read:可讀取的
write:可寫的
execute:可執行的
shared:對於載入該段的鏡像的所有進程是共享的
nopage:不可分頁的,主要用於Win32的設備驅動程序中
nocache:不可緩存的,主要用於Win32的設備驅動程序中
discard:可廢棄的,主要用於Win32的設備驅動程序中
remove:非內存常駐的,僅用於虛擬設備驅動(VxD)中
如果未指定屬性,默認屬性為read和write。
在創建了段之後,還要使用__declspec(allocate)將代碼或數據放入段中。
例如:
//pragma_section.cpp
#pragma section("mysec",read,write)
int j = 0;
__declspec(allocate("mysec"))
int i = 0;
int main(){}
該例中, 創建了段"mysec",設置了read,write屬性。但是j沒有放入到該段中,而是放入了默認的數據段中,因為它沒有使用__declspec(allocate)進行聲明;而i放入了該段中,因為使用__declspec(allocate)進行了聲明。
10.#pragma push_macro與#pragma pop_macro。前者將指定的宏壓入棧中,相當於暫時存儲,以備以後使用;後者將棧頂的宏出棧,彈出的宏將覆蓋當前名稱相同的宏。例如:
#include
#define X 1
#define Y 2
int main() {
printf("%d",X);
printf("\n%d",Y);
#define Y 3 // C4005
#pragma push_macro("Y")
#pragma push_macro("X")
printf("\n%d",X);
#define X 2 // C4005
printf("\n%d",X);
#pragma pop_macro("X")
printf("\n%d",X);
#pragma pop_macro("Y")
printf("\n%d",Y);
}
輸出結果:
1
2
1
2
1
3

Ⅵ VC 中如何使用 BCB 編譯的庫文件

在 Visual C++ 或者 Visual Studio 中, 是無法直接使用 BCB 工程編譯產生的庫文件的. 究其原因, 是由於微軟 Visual C++ lib 文件格式與 BCB 工程的 lib 文件格式不同所導致. Lib 文件中存放的是動態鏈接庫的介面信息, 而不會含有任何函數的內部實現細節. 因此, 我們可以直接通過 Dll 文件來反向生成特定格式的 lib 文件, 以便在 VC 和 BCB 中交叉使用各個編譯的動態鏈接庫.

以 MTK 平台的多路下載工具 SP_MDT 為例, 演示在 VC++ 中直接使用 BCB 編譯的 lib 庫的問題及解決方案. 我們以 Eboot 為例, 源代碼目錄下關於 Eboot 的文件有以下幾個:
Eboot 頭文件定義, 路徑: SP_MDT_SRCEboot
Eboot lib 庫文件, 路徑: SP_MDT_SRCLib
Eboot 動態鏈接庫文件, 路徑: SP_MDT_SRCoutput

我們新建一個 VC++ MFC 工程, 將上述文件全部拷貝到 MFC 工程目錄下, 同時在對話框中實現如下代碼段:

#include "interface.h"ANDROID_DL_HANDLE_T handle;
Android_DL_Create(&handle);

此時, 編譯工程會報出如下錯誤:

error LNK2019: 無法解析的外部符號 _Android_DL_Create@4
該符號在函數 "public: void __thiscall CLibDemoDlg::OnBnClickedOk(void)" 中被引用

原因在於我們僅僅包含了相應函數的頭文件, 而並沒有導入任何的函數實現(如 cpp 源文件或者 lib 庫文件). 接下來, 我們嘗試直接在 VC++ 中使用 BCB 編譯生成的 lib 庫文件, 加入以下代碼:

#pragma comment(lib, "eboot.lib")

編譯時報出如下錯誤:

eboot.lib : warning LNK4003: 無效的庫格式; 已忽略庫

顯然, VC++ 並不能正確的識別 BCB 所生成的 lib 庫文件. 那麼如何解決這個問題呢? 一般來說有兩種方法:

Ⅶ 如何使用C++Builder編譯Delphi使用Obj文件

一直以來,Delphi 都可以用命令行 dcc32 ProjectName.dpr 對項目進行編譯鏈接,非常方便,Delphi對項目文件的參數配置處理的很簡單,便於閱讀處理起來也很直觀,編譯的中間文件也很簡單(dcu,dcp)。
而C++Builder就沒那麼幸運了,因為包含了C++的特徵,各種編譯的中間文件:lib,obj,res,map,tds。後來新版又增加了一些預編譯文件:ilc,ild,ilf,...,pch,#00,...等等等等,各種搜索路徑(Include Path,Library Path,Browse Path...),要是用bcc32及ilink32手工進行編譯鏈接,命令的參數都足夠寫上大半天。幸好,在舊版C++Builder中,如果要用命令行編譯BCB項目,只要將bpr文件轉換為mak文件,再使用make命令進行編譯鏈接也比較方便,不需要過多的處理:
[plain] view plainprint?
bpr2mak -oProject1.mak Project1.bpr
make -fProject1.mak

自從Delphi/C++Builder開始使用 MSBuild* 編譯系統後(好像是RAD Studio 2006開始,具體忘記了),Delphi項目在保存為dpr的同時,也會保存一份dproj的項目文件,dpr依舊沿用舊格式,dproj 則以MSBuild規范以XML格式保存,除了可以用舊方式命令行編譯dpr外,也可以用:

[plain] view plainprint?
msbuild.exe /t:Rebuild /p:Config=Debug ProjectName.dproj

進行編譯,但msbuild必須設定一些環境變數,RAD Studio自帶了一個命令行工具已經做好了這些,其實就是設定了以下幾個環境變數($(BDS)\bin\rsvars.bat):

[plain] view plainprint?
@SET BDS=C:\Embarcadero\RAD Studio\7.0
@SET BDSCOMMONDIR=C:\Users\Public\Documents\RAD Studio\7.0
@SET FrameworkDir=C:\Windows\Microsoft.NET\Framework\v2.0.50727
@SET FrameworkVersion=v2.0.50727
@SET FrameworkSDKDir=
@SET PATH=%FrameworkDir%;%FrameworkSDKDir%;%PATH%
@SET LANGDIR=EN

C++Builder則又更杯具了一些,bpr2mak.exe工具已經沒有了,所以只能採用MSBuild進行命令行編譯。更加杯具的是,隨著Delphi和BCB被多次轉賣收購,新版本的發布似乎總會有各種各樣的Bug,比如手頭的RAD Studio 2009進行命令行編譯,Delphi正常,BCB則報出超過100個錯誤,類似如下:

[plain] view plainprint?
C:\Embarcadero\RAD Studio\7.0\Bin\CodeGear.Cpp.Targets(2175,3): error : Error: Unresolved external '__fastcall Strhlpr::UnicodeFree(System::UnicodeString&)' referenced from C:\EMBARCADERO\RAD STUDIO\7.0\LIB\DEBUG\VCLE.LIB|ustring
C:\Embarcadero\RAD Studio\7.0\Bin\CodeGear.Cpp.Targets(2175,3): error : Error: Unresolved external 'Typinfo::BooleanIdents' referenced from C:\EMBARCADERO\RAD STUDIO\7.0\LIB\DEBUG\VCLE.LIB|vclinit

檢查了一下發現編譯過程(bcc32.exe)沒有問題,只是在ilink32.exe鏈接過程中報錯,在IDE中打開此項目進行編譯,查看Message->Output窗口,比較兩者的ilink32命令行參數,發現兩者有兩個地方有明顯差異,一個是IDE生成的命令中沒有類似 C:\Embarcadero\RAD Studio\7.0\lib\EN\debug 的路徑(指的是EN這個目錄,去除上面rsvars.bat中的@SET LANGDIR=EN 就可以避免產生這樣的搜索路徑) ,但是雖然這個目錄不存在,也應該不至於導致出錯。第二個差異是缺少了rtl.bpi和vcl.bpi的附加obj參數,解決辦法是在$(BDS)\bin目錄中找到 CodeGear.Cpp.Targets 文件,用記事本打開,搜索字元「memmgr.lib「,在前面加上"rtl.bpi;vcl.bpi" (用;分隔,不含引號),一共有兩處要修改。或者查找 "c0w32",在後面加上 "rtl.bpi;vcl.bpi",只有一處修改 —— 因為IDE的命令行中 rtl.bpi vcl.bpi是在c0w32和memmgr.lib中間的。—— (注意:在XE2中,加在c0w32後面已經不管用了,編譯會報另一個錯誤VCL.BPIW.OBJ不存在,Targets文件有很大變化,可能參數的位置變動過了,導致與其他參數混在一起,所以還是加到memmgr.lib處更加合理)。

一些組件包比如DevExpress的Package,沒有dproj或者cproj 項目文件,只能通過IDE進行轉換,但坑爹的是bpk在好幾個版本以前(CRS 2007?)已經不支持bpk項目,根本打不開也談不上轉換了,但它其實是一個make文件,可惜用make命令編譯還是要出錯,不想去研究了。總之,BCB永遠活在Delphi的陰影下。

Ⅷ C++中怎樣寫宏定義

C/C++中宏使用總結
.C/C++中宏總結C程序的源代碼中可包括各種編譯指令,這些指令稱為預處理命令。雖然它們實際上不是C語言的一部分,但卻擴展了C程
序設計的環境。本節將介紹如何應用預處理程序和注釋簡化程序開發過程,並提高程序的可讀性。

ANSI標準定義的C語言預處理程序包括下列命令:

#define,#error,#i
nclude,#if,#else,#elif,#endif,#ifdef,#ifndef,#undef,#line,#pragma等。非常明顯,所有預處理命令均以符號#開頭,下面分別加以介紹。

1、#define

命令#define定義了一個標識符及一個串。在源程序中每次遇到該標識符時,均以定義的串代換它。ANSI標准將標識符定義為宏名,將替換過程稱為宏
替換。命令的一般形式為:

#define identifier string

注意:

? 該語句沒有分號。在標識符和串之間可以有任意個空格,串一旦開始,僅由一新行結束。

? 宏名定義後,即可成為其它宏名定義中的一部分。

? 宏替換僅僅是以文本串代替宏標識符,前提是宏標識符必須獨立的識別出來,否則不進行替換。例如: #define XYZ
this is a test,使用宏printf("XYZ");//該段不列印"this is a test"而列印"XYZ"。因為預編譯器識
別出的是"XYZ"

? 如果串長於一行,可以在該行末尾用一反斜杠' \'續行。

2、#error

處理器命令#error強迫編譯程序停止編譯,主要用於程序調試。

3、#i nclude

命令#i nclude使編譯程序將另一源文件嵌入帶有#i nclude的源文件,被讀入的源文件必須用雙引號或尖括弧括起來。例如:

#i nclude"stdio.h"或者#i nclude

這兩行代碼均使用C編譯程序讀入並編譯用於處理磁碟文件庫的子程序。

將文件嵌入#i nclude命令中的文件內是可行的,這種方式稱為嵌套的嵌入文件,嵌套層次依賴於具體實現。

如果顯式路徑名為文件標識符的一部分,則僅在哪些子目錄中搜索被嵌入文件。否則,如果文件名用雙引號括起來,則首先檢索當前工作目錄。如果未發現文件,
則在命令行中說明的所有目錄中搜索。如果仍未發現文件,則搜索實現時定義的標准目錄。

如果沒有顯式路徑名且文件名被尖括弧括起來,則首先在編譯命令行中的目錄內檢索。

如果文件沒找到,則檢索標准目錄,不檢索當前工作目錄。

4、條件編譯命令

有幾個命令可對程序源代碼的各部分有選擇地進行編譯,該過程稱為條件編譯。商業軟體公司廣泛應用條件編譯來提供和維護某一程序的許多顧客版本。

#if、#else,#elif及#endif

#if的一般含義是如果#if後面的常量表達式為true,則編譯它與#endif之間的代碼,否則跳過這些代碼。命令#endif標識一個#if塊的
結束。

#if constant-expression

statement sequence

#endif

跟在#if後面的表達式在編譯時求值,因此它必須僅含常量及已定義過的標識符,不可使用變數。表達式不許含有操作符sizeof(sizeof也是編譯
時求值)。

#else命令的功能有點象C語言中的else;#else建立另一選擇(在#if失敗的情況下)。

注意,# else屬於# if塊。

#elif命令意義與ELSE IF 相同,它形成一個if else-if階梯狀語句,可進行多種編譯選擇。

#elif 後跟一個常量表達式。如果表達式為true,則編譯其後的代碼塊,不對其它#elif表達式進行測試。否則,順序測試下一塊。

#if expression

statement sequence

#elif expression1

statement sequence

#endif

在嵌套的條件編譯中#endif、#else或#elif與最近#if或#elif匹配。

# ifdef 和# ifndef

條件編譯的另一種方法是用#ifdef與#ifndef命令,它們分別表示"如果有定義"及"如果無定義"。

# ifdef的一般形式是:

# ifdef macroname

statement sequence

#endif

#ifdef與#ifndef可以用於#if、#else,#elif語句中,但必須與一個#endif。

5、#undef

命令#undef 取消其後那個前面已定義過有宏名定義。一般形式為:

#undef macroname

6、#line

命令# line改變__LINE__與__FILE__的內容,它們是在編譯程序中預先定義的標識符。命令的基本形式如下:

# line number["filename"]

其中的數字為任何正整數,可選的文件名為任意有效文件標識符。行號為源程序中當前行號,文件名為源文件的名字。命令# line主要用於調試及其它特殊
應用。

注意:在#line後面的數字標識從下一行開始的數字標識。

7、預定義的宏名

ANSI標准說明了C中的五個預定義的宏名。它們是:

__LINE__

__FILE__

__DATE__

__TIME__

__STDC__

如果編譯不是標準的,則可能僅支持以上宏名中的幾個,或根本不支持。記住編譯程序也許還提供其它預定義的宏名。

__LINE__及__FILE__宏指令在有關# line的部分中已討論,這里討論其餘的宏名。

__DATE__宏指令含有形式為月/日/年的串,表示源文件被翻譯到代碼時的日期。

源代碼翻譯到目標代碼的時間作為串包含在__TIME__中。串形式為時:分:秒。

如果實現是標準的,則宏__STDC__含有十進制常量1。如果它含有任何其它數,則實現是非標準的。編譯C++程序時,編譯器自動定義了一個預處理名
字__cplusplus,而編譯標准C時,自動定義名字__STDC__。

注意:宏名的書寫由標識符與兩邊各二條下劃線構成。

(部分內容出自:http://www.bc-cn.net/Article/kfyy/cyy/jc/200511/919.html)

8、C、C++宏體中出現的#,#@,##

宏體中,#的功能是將其後面的宏參數進行字元串化操作(Stringfication),簡單說就是在對它所引用的宏變數通過替換後在其左右各加上一個
雙引號。

而##被稱為連接符(concatenator),用來將兩個Token連接為一個Token。注意這里連接的對象是Token就行,而不一定是宏的變
量。比如你要做一個菜單項命令名和函數指針組成的結構體的數組,並且希望在函數名和菜單項命令名之間有直觀的、名字上的關系。那就可以使用:宏參數##
固定部分。當然還可以n個##符號連接 n+1個Token,這個特性也是#符號所不具備的。

#@的功能是將其後面的宏參數進行字元化。

9、C宏中的變參...

...在C宏中稱為Variadic Macro,也就是變參宏。比如:

#define myprintf(templt,...) fprintf(stderr,templt,__VA_ARGS__)

或者#define myprintf(templt,args...) fprintf(stderr,templt,args)

第一個宏中由於沒有對變參起名,我們用默認的宏__VA_ARGS__來替代它。第二個宏中,我們顯式地命名變參為args,那麼我們在宏定義中就可以
用args來代指變參了。同C語言的stdcall一樣,變參必須作為參數表的最後有一項出現。當上面的宏中我們只能提供第一個參數templt時,C
標准要求我們必須寫成: myprintf(templt,);的形式。這時的替換過程為:myprintf("Error!\n",);替換為:
fprintf(stderr,"Error!\n",).

這是一個語法錯誤,不能正常編譯。這個問題一般有兩個解決方法。首先,GNU CPP提供的解決方法允許上面的宏調用寫成:
myprintf(templt);而它將會被通過替換變成: fprintf(stderr,"Error!\n",);

很明顯,這里仍然會產生編譯錯誤(非本例的某些情況下不會產生編譯錯誤)。除了這種方式外,c99和GNU CPP都支持下面的宏定義方式:

#define myprintf(templt, ...) fprintf(stderr,templt, ##__VAR_ARGS__)

這時,##這個連接符號充當的作用就是當__VAR_ARGS__為空的時候,消除前面的那個逗號。那麼此時的翻譯過程如下:
myprintf(templt);被轉化為: fprintf(stderr,templt);

這樣如果templt合法,將不會產生編譯錯誤。

10、#pragma的使用【轉載】

在所有的預處理指令中,#Pragma 指令可能是最復雜的了,它的作用是設定編譯器的狀態或者是指示編譯器完成一些特定的動作。#pragma指令對
每個編譯器給出了一個方法,在保持與C和C ++語言完全兼容的情況下,給出主機或操作系統專有的特徵。依據定義,編譯指示是機器或操作系統專有的,且
對於每個編譯器都是不同的。

其格式一般為: #Pragma Para,其中Para 為參數,下面來看一些常用的參數。

(1)message 參數。 Message 參數是我最喜歡的一個參數,它能夠在編譯信息輸出窗口中輸出相應的信息,這對於源代碼信息的控制是非常
重要的。其使用方法為:

#Pragma message("消息文本")

當編譯器遇到這條指令時就在編譯輸出窗口中將消息文本列印出來。

當我們在程序中定義了許多宏來控制源代碼版本的時候,我們自己有可能都會忘記有沒有正確的設置這些宏,此時我們可以用這條指令在編譯的時候就進行檢查。
假設我們希望判斷自己有沒有在源代碼的什麼地方定義了_X86這個宏可以用下面的方法

#ifdef _X86

#Pragma message("_X86 macro activated!")

#endif

當我們定義了_X86這個宏以後,應用程序在編譯時就會在編譯輸出窗口裡顯示"_

X86 macro activated!"。我們就不會因為不記得自己定義的一些特定的宏而抓耳撓腮了。

(2)另一個使用得比較多的pragma參數是code_seg。格式如:

#pragma code_seg( ["section-name"[,"section-class"] ] )

它能夠設置程序中函數代碼存放的代碼段,當我們開發驅動程序的時候就會使用到它。

(3)#pragma once (比較常用)

只要在頭文件的最開始加入這條指令就能夠保證頭文件被編譯一次,這條指令實際上在VC6中就已經有了,但是考慮到兼容性並沒有太多的使用它。

(4)#pragma hdrstop表示預編譯頭文件到此為止,後面的頭文件不進行預編譯。BCB可以預編譯頭文件以加快鏈接的速度,但如果所有頭文
件都進行預編譯又可能占太多磁碟空間,所以使用這個選項排除一些頭文件。

有時單元之間有依賴關系,比如單元A依賴單元B,所以單元B要先於單元A編譯。你可以用#pragma startup指定編譯優先順序,如果使用了
#pragma package(smart_init) ,BCB就會根據優先順序的大小先後編譯。

(5)#pragma resource "*.dfm"表示把*.dfm文件中的資源加入工程。*.dfm中包括窗體、外觀的定義。

(6)#pragma warning( disable : 4507 34; once : 4385; error : 164 )

等價於:

#pragma warning(disable:4507 34) // 不顯示4507和34號警告信息

#pragma warning(once:4385) // 4385號警告信息僅報告一次

#pragma warning(error:164) // 把164號警告信息作為一個錯誤。

同時這個pragma warning 也支持如下格式:

#pragma warning( push [ ,n ] )

#pragma warning( pop )

這里n代表一個警告等級(1---4)。

#pragma warning( push )保存所有警告信息的現有的警告狀態。

#pragma warning( push, n)保存所有警告信息的現有的警告狀態,並且把全局警告等級設定為n。

#pragma warning( pop )向棧中彈出最後一個警告信息,在入棧和出棧之間所作的一切改動取消。例如:

#pragma warning( push )

#pragma warning( disable : 4705 )

#pragma warning( disable : 4706 )

#pragma warning( disable : 4707 )

//.......

#pragma warning( pop )

在這段代碼的最後,重新保存所有的警告信息(包括4705,4706和4707)。
(7)pragma comment(...)

該指令將一個注釋記錄放入一個對象文件或可執行文件中。

常用的lib關鍵字,可以幫我們連入一個庫文件。

(8)用pragma導出dll中的函數

傳統的到出 DLL 函數的方法是使用模塊定義文件 (.def),Visual C++ 提供了更簡潔方便的方法,那就
是"__declspec()"關鍵字後面跟"dllexport",告訴連接去要導出這個函數,例如:

__declspec(dllexport) int __stdcall MyExportFunction(int iTest);

把"__declspec(dllexport)"放在函數聲明的最前面,連接生成的 DLL 就會導出函
數"_MyExportFunction@4"。

上面的導出函數的名稱也許不是我的希望的,我們希望導出的是原版的"MyExportFunction"。還好,VC 提供了一個預處理指示
符"#pragma"來指定連接選項 (不僅僅是這一個功能,還有很多指示功能) ,如下:

#pragma comment(linker,"/EXPORT:MyExportFunction=_MyExportFunction@4")

這下就天如人願了:)。如果你想指定導出的順序,或者只將函數導出為序號,沒有 Entryname,這個預處理指示符 (確切地說是連接器) 都能夠
實現,看看 MSDN 的語法說明:

/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]

@ordinal 指定順序;NONAME 指定只將函數導出為序號;DATA 關鍵字指定導出項為數據項。

⑨每個編譯程序可以用#pragma指令激活或終止該編譯程序支持的一些編譯功能。例如,對循環優化功能:

#pragma loop_opt(on) // 激活

#pragma loop_opt(off) // 終止

有時,程序中會有些函數會使編譯器發出你熟知而想忽略的警告,如"Parameter xxx is never used in function
xxx",可以這樣:

#pragma warn -100 // Turn off the warning message for warning #100

int insert_record(REC *r)

{ /* function body */ }

#pragma warn +100 // Turn the warning message for warning #100 back
on

函數會產生一條有唯一特徵碼100的警告信息,如此可暫時終止該警告。

每個編譯器對#pragma的實現不同,在一個編譯器中有效在別的編譯器中幾乎無效。可從編譯器的文檔中查看。
⑩#pragm pack()的使用

#pragma pack規定的對齊長度,實際使用的規則是:

? 結構,聯合,或者類的數據成員,第一個放在偏移為0的地方,以後每個數據成員的對齊,按照#pragma pack指定的數值和這
個數據成員自身長度中,比較小的那個進行。

? 也就是說,當#pragma pack的值等於或超過所有數據成員長度的時候,這個值的大小將不產生任何效果。

? 而結構整體的對齊,則按照結構體中最大的數據成員 和 #pragma pack指定值之間,較小的那個進行。

注意:文件使用#pragma pack(n) 改變了預設設置而不恢復,通常可以使用#pragma pack(push, n)和#pragma
pack(pop)進行設置與恢復。

註:關於宏函數的內容在另外的專題。關於宏使用的誤區在描述宏的時候已經在文中提到了,最後再給出一個例子,描述的Side Effect是指宏在展開
的時候對其參數可能進行多次Evaluation(也就是取值)對程序造成的錯誤影響。

假設在一個系統中,有一個32b的寄存器(REG)保存狀態,其中高16b表示一種含義,低16b表示另一種含義(這在程序中經常出現)。現在要把高低
16b分開,不考慮實際中的特殊要求,將代碼寫成:

#define High16bit(REG) (REG>>16)

#define Low16bit(REG) ((REG<<16)>>16)

對於這種寫法完成的功能在大多數情況是足夠了,這里不討論。主要談論這種寫法的負面影響,如果在程序中分別在不同的語句中使用High16bit和
Low16bit,那麼就可能那就是Side effect,特別寄存器REG是狀態寄存器,他的狀態可能隨時變化,那麼引起的問題就是高低16b根本
取的不是同一個時刻狀態寄存器。這種錯誤在程序中找出就比較難了。在這里我把條件弱化了,試想在一個宏體中,如果對參數多次取值也是可能引起問題,那就 更難了。

閱讀全文

與BCB編譯message在哪相關的資料

熱點內容
dvd光碟存儲漢子演算法 瀏覽:757
蘋果郵件無法連接伺服器地址 瀏覽:962
phpffmpeg轉碼 瀏覽:671
長沙好玩的解壓項目 瀏覽:144
專屬學情分析報告是什麼app 瀏覽:564
php工程部署 瀏覽:833
android全屏透明 瀏覽:736
阿里雲伺服器已開通怎麼辦 瀏覽:803
光遇為什麼登錄時伺服器已滿 瀏覽:302
PDF分析 瀏覽:484
h3c光纖全工半全工設置命令 瀏覽:143
公司法pdf下載 瀏覽:381
linuxmarkdown 瀏覽:350
華為手機怎麼多選文件夾 瀏覽:683
如何取消命令方塊指令 瀏覽:349
風翼app為什麼進不去了 瀏覽:778
im4java壓縮圖片 瀏覽:362
數據查詢網站源碼 瀏覽:150
伊克塞爾文檔怎麼進行加密 瀏覽:892
app轉賬是什麼 瀏覽:163