DLL導出函數名稱改編的解決方法

***************************************************

更多精彩,歡迎進入:http://shop115376623.taobao.com

***************************************************


1.DLL編譯后導出函數名稱改變

?

在編寫一個DLL后,為了能被別的程序調用,需要將被使用的函數導出;

但是一般的編譯器都會將到處函數名稱改變;

例如:在VC中新建一個空的win32 dll工程,然后添加下面的文件;

[cpp]?view plaincopy
  1. //dll1.h??
  2. #ifdef?DLL_API?_declspec(dllexport)???
  3. #else??
  4. #define?DLL_API?_declspec(dllexport)??
  5. #endif??
  6. ??
  7. DLL_API?int?add(int?a,?int?b);??

[cpp]?view plaincopy
  1. //dll1.cpp??
  2. ??
  3. #include?"dll1.h"??
  4. ??
  5. DLL_API?int?add(int?a,?int?b)??
  6. {??
  7. ??return?a?+?b;??
  8. }??

?

編譯以后,得到dll1.dll與dll1.lib;使用Dumpbin.exe或者是Depends工具查(dll查看器)看發現,

dll1.dll中的到處函數名稱為:?add@@YAHH@Z?;這個新的函數名稱是C++編譯器對add函數的名稱進行了改變,

而且不同的編譯器的改編規則也不一樣,這就導致在通過add函數名對函數進行調用時無法找到add函數

因為此時add的函數名稱已經被改編;

?

2.限定導出函數名稱

?

為了解決C與C++能在不同編譯器之間正常調用DLL,所以我們希望DLL在編譯過程中不要對函數名稱進行改編;

我們可以在定義導出函數時,加上限定符 extern "C"

我們把上面的例子修改下:

[cpp]?view plaincopy
  1. //dll1.h??
  2. #ifdef?DLL_API?extern?"C"?_declspec(dllexport)???
  3. #else??
  4. #define?DLL_API?extern?"C"?_declspec(dllexport)??
  5. #endif??
  6. ??
  7. DLL_API?int?add(int?a,?int?b);??

?

[cpp]?view plaincopy
  1. //dll1.cpp??
  2. #include?"dll1.h"??
  3. ??
  4. DLL_API?int?add(int?a,?int?b)??
  5. {??
  6. ??return?a?+?b;??
  7. }??

我們再次編譯得到dll1.dll,通過工具查看其到導出函數發現,此時的add函數的導出名稱仍然是add;

這樣我們就可以在其他編譯器上直接通過add調用該函數了;

?

3.__stdcall關鍵字將使限定無效

如果我們在第二個的基礎上給函數加上__stdcall關鍵字,導出函數的名稱將仍然被改編;

如果沒有添加__stdcall關鍵字,那么函數調用約定為C調用約定。如果加了__stdcall標準調用約定,

就是WINAPI調用約定,也就是pascal調用約定,這種約定與C調用約定不一樣。

[cpp]?view plaincopy
  1. //dll1.h??
  2. #ifdef?DLL_API?extern?"C"?_declspec(dllexport)???
  3. #else??
  4. #define?DLL_API?extern?"C"?_declspec(dllexport)??
  5. #endif??
  6. ??
  7. DLL_API?int?__stdcall?add(int?a,?int?b);??

?

[cpp]?view plaincopy
  1. //dll1.cpp??
  2. #include?"dll1.h"??
  3. ??
  4. DLL_API?__stdcall?int?add(int?a,?int?b)??
  5. {??
  6. ??return?a?+?b;??
  7. }??

重新編譯,然后通過工具查看DLL的導出函數,發現名稱為: _add@8;

也就是說如果函數的調用約定發生變化,即使在聲明時使用了 extern "C"限定符,函數名稱仍然會

改編;

C語言與Delphi的調用約定是不一樣的,Delphi使用的是pascal調用約定,如果我們要用C寫一個DLL供Delphi使用,

那么在導出函數時應指定其使用標準的函數調用約定,但此時 導出函數名稱就會被改編;

?

在這種情況下,我們需要通過一個稱為模塊定義文件(DEF)的方法解決名稱被改編的問題;

?

在上面例子的基礎上,我們給這個工程添加一個后綴為def的文件dll1.def;然后添加如下代碼:

[c-sharp]?view plaincopy
  1. //dll1.def??
  2. ??
  3. LIBRARY?"dll1"??
  4. ??
  5. EXPORTS??
  6. add??

此文件中LIBRARY指定動態鏈接庫的內部名稱,該名稱與生成的動態鏈接庫名稱要匹配;

EXPORTS下面就是要導出的函數

如果EXPORTS下的函數個數多時,方式為:

LIBRARY “dlll”

EXPORTS

ADD

SUB

MUL

……

如果導出的函數名稱與源文件中的函數名稱不一樣可以通過下面的語法指定導出函數名稱:

entryname = internalname

?

編譯時,編譯器會按照def中指定的函數名稱導出函數;

?

重新編譯,通過工具查看dll1.dll中的導出函數為add了;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458962.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458962.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458962.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

組合自定義控件的步驟詳解

Android 步驟&#xff1a; 1 自定義組合控件的布局settint_view.xml<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:orientation"vertical"and…

linux如何建立隱藏目錄,【Linux】文件與目錄的默認權限與隱藏權限

01. 文件默認權限&#xff1a;umask文件的權限可以使用chmod來改變&#xff0c;但是我們默認創建文件的權限是什么&#xff1f;那就是與umask這個有關了。下來我們學習這個指令1.1 簡單使用umask[rootiZbp13q6hd8z3xaagcmz6gZ /]# umask0022[rootiZbp13q6hd8z3xaagcmz6gZ /]# u…

Servlet和JSP學習指導與實踐(二):Session追蹤

前言&#xff1a; web應用中經常需要對某些有用的信息進行存儲或者附加一些信息。本文主要介紹session&#xff0c;即“會話”跟蹤的幾種不同方式~ ----------------------------4種管理session的方式&#xff1a; 1.重寫url 通過在請求的url后面追加參數信息進行會話跟蹤。如&…

數據存儲和界面展示(二)

#測試 黑盒測試 測試邏輯業務 白盒測試 測試邏輯方法 根據測試粒度 方法測試&#xff1a;function test 單元測試&#xff1a;unit test 集成測試&#xff1a;integration test 系統測試&#xff1a;system test 根據測試暴力程度 冒煙測試&#xff1a;smoke test 壓力測…

linux在A目錄下創建B文件,Linux課程---5、常用文件命令和目錄命令(創建文件命令)...

Linux課程---5、常用文件命令和目錄命令(創建文件命令)一、總結一句話總結&#xff1a;touch file11、管道符|有什么用&#xff1f;將前一個命令的結果作為后一個命令的輸入&#xff1a;比如查看文件前3行&#xff1a;cat file1 | head -32、linux下如何復制粘貼命令是什么&…

window 系統上傳文件到linux 系統出現dos 格式換行符

Windows里的文件在Unix/Mac下打開的話&#xff0c;在每行的結尾可能會多出一個^M符號&#xff0c;Unix/Mac系統下的文件在Windows里打開的話&#xff0c;所有文字會變成一行&#xff0c;所以為了避免這種情況的發生&#xff0c;我們可以在linux系統內轉換格式 Centos系列可以直…

#pragma once與 #ifndef的區別

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 為了避免同一個文件被include多次 1 #ifndef方式2 #pragma once方式 在能夠支持這…

android學習者優秀網址推薦

非常漂亮的android UI庫集合&#xff0c;別人整理的&#xff0c;如果感覺不錯&#xff0c;趕快收藏吧&#xff01;&#xff01; https://github.com/wasabeef/awesome-android-ui https://github.com/Trinea/android-open-project android中文社區網 http://www.android-studio…

linux while read文件,linux shell腳本用while read逐行讀取文本的問題

問題:我現在是想用一個腳本獲取一定列表服務器的運行時間。首先我建立一個名字為ip.txt的IP列表(一個IP一行)&#xff0c;再建好密鑰實現不用密碼直接登錄。然后寫腳本如下&#xff1a;#!/bin/bashwhile read ips;doecho $ips;done < ip.txt腳本實現了逐行讀取列表中的IP&am…

常用字符串處理函數匯總

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** (一)strcmp函數 strcmp函數是比較兩個字符串的大小,返回比較的結果。一般形式是&…

兼容性記錄-class屬性

getAttribute獲得class屬性時,IE6,IE7的傳參是className,IE7和現代游覽器都是class全部游覽器DOMElement均有的className屬性,其在IE各版本號下的均表現良好返回屬性class值的字符串此外html5中DOMElement有個classList屬性,它返回一個類型為DOMTokenList的對象,它當中有非常多…

magenta內核與linux,谷歌將推出新操作系統Fuchsia:Magenta語言為內核

谷歌現在研發出來并且推出使用的系統有Chrome OS、Android和Chromecasts&#xff0c;這三者在操作系統的市場中占得份額很高&#xff0c;但是好像谷歌對此并不滿意&#xff0c;因為有相關消息顯示&#xff0c;谷歌正在研發新的操作系統Fuchsia&#xff0c;該系統采用Magenta語言…

BZOJ 1968: [Ahoi2005]COMMON 約數研究 水題

1968: [Ahoi2005]COMMON 約數研究 Time Limit: 20 Sec Memory Limit: 256 MB 題目連接 http://www.lydsy.com/JudgeOnline/problem.php?id1968 Description Input 只有一行一個整數 N&#xff08;0 < N < 1000000&#xff09;。 Output 只有一行輸出&#xff0c;為整數M…

VC內存對齊準則(Memory alignment)

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 本文所有內容在建立在一個前提下&#xff1a;使用VC編譯器。著重點在于&#xff1a;VC…

[redis設計與實現][7]基本數據結構——對象

Redis對基礎數據類型進行了封裝&#xff0c;構建出上層的對象系統&#xff0c;這個系統包含&#xff1a;字符串對象、列表對象、哈希對象、集合對象和有序集合對象。 Redis對象結構&#xff1a; [cce lang”c”] typedef struct redisObject { //類型 unsigned type:4; //編碼 …

Linux中samba的權限詳解,活用三種權限 理解Samba的權限控制

在企業內網開發環境方面&#xff0c;文件服務器是一個非常重要的環節。在這當中&#xff0c;Samba服務器由于其權限控制的高度靈活性&#xff0c;在這里撫琴煮酒會進行一些列詳細的說明。之前我們已經介紹了Samba服務器一些入門和基本的更換用戶、端口監聽、列表控制等技巧&…

安卓基礎01

安卓基礎01SDK System images 這是在創建模擬器時需要的system image&#xff0c;也就是在創建模擬器時CPU/ABI項需要選擇的&#xff0c;下載并解壓后&#xff0c;將解壓出的整個文件夾復制或者移動到 your sdk 路徑/system-images文件夾下即可&#xff0c; 如果沒有 system-im…

C++存儲區域基礎概念詳解

*************************************************** 更多精彩&#xff0c;歡迎進入&#xff1a;http://shop115376623.taobao.com *************************************************** 以下詳解來自&#xff1a; http://blog.163.com/zb_075/blog/static/3734032820115110…

創建、修改、刪除表總結

一、創建表 CREATE TABLE <表名> &#xff08;<列名><數據類型>[列級完整性約束條件] [&#xff0c;<列名> <數據類型>[列級完整性約束條件]] … [&#xff0c;表級完整性約束條件]&#xff09;&#xff1b; 如果完整性約束條件涉及到該表的多個…

linux 編譯查看鏈接庫詳情,Linux環境下的編譯,鏈接與庫的使用

鏈接參數控制鏈接器中提供了-dn -dy 參數來控制使用的是動態庫還是靜態庫&#xff0c;-dn表示后面使用的是靜態庫&#xff0c;-dy表示使用的是動態庫例:g -Lpath -Wl,-dn -lx -Wl,-dy -lpthread 這樣如果在path路徑下有libx.so和libx.a這個時候只會用到 libx.a.注意在最后的地…