1. 程式人生 > >VS2015用C++建立的動態庫匯出函式名亂碼原因分析

VS2015用C++建立的動態庫匯出函式名亂碼原因分析

        在上一篇部落格【在VS2015中用C++建立動態庫並用C#呼叫】中提到,在C# DllImport匯入C/C++編寫的動態庫時函式,要加上CallingConvention = CallingConvention.Cdecl來指定入口點的呼叫約定。這是因為C/C++編寫的動態庫預設的入口點約定為_cdecl,而VS預設呼叫動態庫時的約定為_winapi。

        本文將重點介紹下這些入口點的呼叫約定,並以此來說明函式名亂碼的真正原因,並且會在下一篇部落格中詳細說明如何建立一個可以被其它語言呼叫的動態庫。

(1)按照【在VS2015中用C++建立動態庫並用C#呼叫】博文中1到8步建立測試專案,但是步驟8中的DLLTest.h中新增

函式Test1和Test2的匯出形式前,不要加EXTERN_C。


(2)使用Dependency Walker檢視匯出的動態庫DLL


從上圖中可以看到匯出的函式名都是亂碼,此時可以在亂碼上右擊選擇Undecorate C++ Functions,如下圖:


此時函式名會自動變為你想要的函式名,如下圖


(4)下面詳細講解下函式名亂碼的原因

           C++編譯時函式名修飾約定規則:    

            __stdcall呼叫約定:  

            1、以"?"標識函式名的開始,後跟函式名;    

            2、函式名後面以"@@YG"標識引數表的開始,後跟引數表;

            3、引數表以代號表示: 

                  X--void 
                  D--char 
                  E--unsigned char 
                  F--short 
                  H--int 
                    I--unsigned int 
                   J--long 
                  K--unsigned long 
                  M--float 

                  N--double 

                _N--bool 
                ....    
                PA--表示指標,後面的代號表明指標型別,如果相同型別的指標連續出現,以"0"代替,一個"0"代表一次重複; 

           4、引數表的第一項為該函式的返回值型別,其後依次為引數的資料型別,指標標識在其所指資料型別前;

           5、引數表後以"@Z"標識整個名字的結束,如果該函式無引數,則以"Z"標識結束。

                 其格式為"[email protected]@YG*****@Z"或"[email protected]@YG*XZ",例如    
                 int Test1(char *var1, unsigned long)[email protected]@[email protected]

                 void Test2()-----"[email protected]@YGXXZ" 

           __cdecl呼叫約定:    
           規則同上面的_stdcall呼叫約定,只是引數表的開始標識由上面的"@@YG"變為"@@YA"。

           __fastcall呼叫約定:    
           規則同上面的_stdcall呼叫約定,只是引數表的開始標識由上面的"@@YG"變為"@@YI"。

(5)由上面可以看出C/C++匯出的動態庫DLL預設的入口點呼叫約定為__cdecl呼叫約定,所以C#在呼叫時需加CallingConvention =           CallingConvention.Cdecl來指定入口點的呼叫約定

(6)通過在匯出函式前加入EXTERN_C,可以將匯出的函式名固定為你想要的函式名,更改入口點約定,讓匯出的動態庫可以被其它語言呼叫,             請瀏覽下篇部落格。

相關推薦

VS2015C++建立動態匯出函式亂碼原因分析

        在上一篇部落格【在VS2015中用C++建立動態庫並用C#呼叫】中提到,在C# DllImport匯入C/C++編寫的動態庫時函式,要加上CallingConvention = Ca

python呼叫C動態匯出函式的返回值為指標型別時,在64位python環境下被截斷解決方法

          class my_void_p(c_void_p):               pass                      def sslog_create_instance():               #直接指定 restype=c_void_p在64位上還是會發生地址截

Java調c程序動態詳細案例

mic fan 調用 c程序 案例 href java pid blank 1n閡嚎o指N階墑06灰tjhttp://huiyi.docin.com/arg9509 N19u4wTfnd塵2http://shufang.docin.com/fbqja96992 84稭棧

UE4C++建立動態陣列

建立一個數組 TArray<int32> IntArray; 通過同一個元素填充初始化 IntArray.Init(10, 5); 等同於// IntArray == [10, 10, 10, 10, 10] 增加新元素 //

c++檢視動態函式地址

我們知道在生成動態庫時,如果使用.def檔案.那麼可以在.def中定義函式地址即例: add @1這種方式.但畢竟這是一種取巧的方式,如果你想獲得任何一個動態庫中函式地址,那麼我這邊可以提供兩個方法.(1)使用vs自帶的功能我用的是VS2005開啟工具選項,下面有Visual

CMake建立動態和靜態(轉)

五,靜態庫與動態庫構建 讀者雲,太能羅唆了,一個Hello World就折騰了兩個大節。OK,從本節開始,我們不再折騰Hello World了,我們來折騰Hello World的共享庫。 本節的任務:1,建立一個靜態庫和動態庫,提供HelloFunc函式供其他程式程式設計使用

編譯.so動態隱藏函式

     在我們提供給別人使用的動態連結庫so檔案時,其內部實現函式的名稱,特別是一些關鍵名稱我們是不希望別人見到然後反向的,這時候一般有兩種處理方式:一是把程式中關鍵詞修改了再編譯,比較蠢笨;二是通過編譯的方式將字符隱藏,gcc編譯器提供了這個選項,即在編譯選項中加入-fvisibility=hidden選

Windows下DEV C++建立靜態動態

如何在DEV下建立屬於自己的靜態和動態庫呢?(2018.6.6)一、新建專案: 二、在庫裡面加入你的函式:(編譯) 三、編譯後到工程目錄下檢視是否產生了字尾位.a的檔案(與你的專案名是一致的) 四、使用這個靜態連結庫:1.首先新建一個.h檔案到你的專案裡面,.h主要是宣告你剛

C# 調 C++/CLI (托管模式c++) 的動態(DLL)

C++/CLI C# Dll調用 1.創建C++/CLI的動態庫 添加類 右鍵生成後即可生成 CLI_Dll.dll2.創建C#窗口應用程序,引用CLI_Dll.dll,然後就可以像是調用C#生成的的dll調用CLI_Dll.dll。C# 調用 C++/CLI (托管模式c++) 的動態庫(D

C語言動態建立方法,以及和python混合程式設計

這篇小結是2016年暑假在新疆出差階段所寫,因為專案需要所以研究了一下。 如有錯誤,歡迎互相交流。 不同編譯器實現python呼叫C語言動態庫方法小結 Windows平臺下Visual Studio 2010編譯器建立動態庫,並呼叫 第一步:建立動態dll動態庫

動態匯出宣告 : extern "C" __declspec(dllexport) 與 __declspec(dllexport)

最近在做專案,在動態載入動態庫後,使用GetProcAddress( HMODULE hModule, LPCWSTR lpProcName)獲取匯出的函式的地址時,發現不能獲得函式地址。 通過檢查發現是宣告動態庫匯出的定義不同導致: 在使用extern "C" __dec

控制linux動態連結匯出函式

開發十年,就只剩下這套架構體系了! >>>   

C#+NPOI動態 對Word的簡單編輯

眾裡尋他千百度,終回首,就在燈火闌珊處。 在很多人部落格上看見基於NPOI動態庫對word進行讀寫,但是沒有自己想要的效果(很多部落格都是對word中的表格做操作,這很正常,NPOI的官方使用文件從頭到尾的都是在講對Excel的操作),於是乎自己摸索了一個。在這裡覺得最最最重要的東

Linux下C程式動態的生成和呼叫

Linux下C程式動態庫的生成和呼叫 文章目錄 Linux下C程式動態庫的生成和呼叫 1 動態庫的打包和呼叫 2 靜態庫打包和呼叫 3 常用命令 4 gcc 和 g++ 區別 5 編譯和連結的理解

C++載入動態的形式來實現封裝

目錄結構 └── test ├── CMakeLists.txt ├── base.h //設定介面 ├── drive.cpp //具體實現 └── main.cpp

Linux下怎麼建立動態和靜態

前言 linux下的生成的動態庫和靜態庫沒有windows下方便 linux下gcc編譯預設動態連結和release 程式執行後呼叫動態庫 動態庫: 程式在執行的時候才去連結動態庫的程式碼,多個程式

Linux動態載入函式dlopen原始碼梳理(二)

中大概梳理了整個流程,還有_dl_map_object_from_fd(),以及link_map結構沒有進行分析,在這裡對這兩部分進行分析 由於_dl_map_object_from_fd()比較長,整個函式的程式碼就放到最後作為附錄,前面部分來一點點進行梳理。 一、

VS2015中匯入/建立靜態並使用靜態【VS+Qt專案開發系列】

本專案示例原始碼已經上傳,歡迎點選下載~注:靜態庫——在連結步驟中,聯結器將從庫檔案取得所需的程式碼,複製到生成的可執行檔案中,這種庫稱為靜態庫,其特點是可執行檔案中包含了庫程式碼的一份完整拷貝;缺點就是被多次使用就會有多份冗餘拷貝。即靜態庫中的指令都全部被直接包含在最終生成

c# 建立支援多語言的應用程式 資原始檔 resx

網際網路無國界,越來越多的應用程式必須面對全球使用者了,如何設計一個支援多國語言的應用程式呢? 在.net2.0 中,m$ 為我們提供了一種簡單方便的方法, 使用資原始檔 1.新建一個 Winform 應用程式, 新建一 Form ,名為 Form1,新增兩個按鈕 bt

C++編寫動態.so或者.dll的陷阱

一、介面不變就可以不需要重新編譯? 對於很多庫的實現者可能會有這樣的認識“介面不變就可以不需要重新編譯”,其實這句話是有前提的,前提是實現的動態庫有足夠的相容性和魯棒性。尤其是C++實現的動態庫,C++只對語言層規則做了規定,沒有二進位制級別的任何規定。 COM本質論裡面的