㈠ 一個C++項目, 已有一些靜態庫(.lib)和所有的函數聲明(.h),怎麼生成一個動態庫(dll)
link /lib /list xxx.lib
可以列出這個lib文件里的所有obj文件
link /lib /extract:xxx.obj xxx.lib
可以從lib里拆解出一個obj文件
配合/nologo參數和for命令
把裡面的obj文件全部拆出來
for /f "delims=" %a in ('link /lib /list /nologo xxx.lib') do link /lib /extract:"%a" xxx.lib
然後根據.h文件自己寫個def文件,用link重新鏈接一下就行了。
def文件還是要自己寫的……
或者你看看能不能用mpbin把lib導出的函數名字都列出來,然後處理一下做成def文件
㈡ 「自定義函數在調用之前,必須進行函數聲明,否則編譯會出錯」這句話為什麼是錯誤的
這句話是錯誤的,只有定義在調用之後的函數才需要聲明,如果定義在調用之前的函數,無需聲明,例子1,定義在調用之後,必須聲明:
main(){
int f();//這個聲明是必須的
printf("%d",f());
}
int f(){return 1;}
例子2,定義在調用之前,無需聲明:
int f(){return 1;}
main(){
/*int f();//這個聲明不需要*/
printf("%d",f());
}最後,這個其實是歷史遺留問題,以前的效率較低,編譯器多次掃描源程序麻煩,現代編譯器為了實現優化,都會反復多次掃描源程序。
㈢ 請問C語言中所謂的函數聲明是指什麼為什麼要進行聲明什麼叫做函數聲明
舉個例子來說明吧
void foo();
int main()
{
foo();
}
void foo()
{
;
}
以上代碼中,第一句就是所謂函數聲明。
其實直接用函數定義也就是void foo(){;}替代第一句也是可以的,不過函數的聲明讓你可以在定義它的代碼段之前使用它。
比如以上的例子中,在編譯進行到main函數中的foo調用的時候,foo函數還是沒有定義的,但我們通過foo的聲明告訴了編譯器:foo是一個函數的名字,這個函數有著怎樣怎樣的參數表等等。
㈣ linux c動態鏈接庫 函數名稱怎麼聲明
出現該錯誤的原因為編譯時只變編譯了源文件的一部分,故在鏈接時無法從編譯好的目標代碼中找到print函數,所以出錯。 根據你的源文件結構,個人推薦先單獨編譯源文件為多個object文件,再統一鏈接。 方法如下 gcc -c main.c # -c參數的作用是讓g...
㈤ 在 c++ 程序中調用被 c 編譯器編譯後的函數,為什麼要加 extern "c" 聲明
C++為了處理函數重載需要把參數信息寫入到函數名,這導致編譯後的函數名和源文件中的不同。而C中沒有這個機制。當在C++中聲明來自C的函數原型或者在C++中為C寫函數實現的時候,必須加上extern "C"表示這個函數要保留原有的函數名(同時也會禁用函數重載)。
㈥ c++動態鏈接的聲明和實現函數 怎麼做成動態鏈接庫
動態鏈接庫的使用方法,動態鏈接庫的動態調用(也叫顯式調用)可以運用了,但是靜態調用(也叫隱式調用)這種很少見。
(一)先回顧一下,動態鏈接庫和靜態鏈接庫
靜態鏈接庫:lib中的函數不僅被連接,全部實現都被直接包含在最終生成的EXE文件中,只是實現是不可見的。
動態鏈接庫:dll不必被包含在最終的EXE中,靜態調用時僅把函數名或者變數名或者類名鏈接到EXE文件中,而這些東西的實體都只有在運行時才從動態庫中導入到可執行文件中,動態調用的時候EXE文件執行時可以直接動態地引用和卸載DLL文件。
同時,靜態鏈接庫中不能再包含其他的動態鏈接庫或靜態庫,而動態鏈接庫中可以包含其他的動態或靜態庫。
(二)回顧一下VC++支持的DLL:
DLL的編制與具體的編程語言及編譯器無關,動態鏈接庫隨處可見,VC++支持三種DLL:非MFC動態庫、MFC規則DLL和MFC擴展DLL。DLL導出函數(或變數、類)可供應用程序調用;DLL內部函數只能在DLL程序內使用,應用程序無法調用它們。
(三)導出函數的聲明方式:
一種在函數聲明類型和函數名之間加上「_declspec(dllexport)」。
另外一種採用模塊定義(.def)文件聲明,需要在庫工程中添加模塊文件,格式如下:
LIBRARY 庫工程名稱
EXPORTS 導出函數名
(四)DLL的調用方式:
靜態調用中,由編譯系統完成對DLL的載入和應用程序結束時DLL的卸載。
動態調用中,由編程者用API函數載入和卸載DLL(DLL載入—DLL函數地址獲取—DLL釋放)方式。
接下來寫個例子把上面提到的理論都實踐一遍。
一、 函數----創建動態鏈接庫(MFC規則DLL)
1. New--projects--MFC AppWizard(dll)--Regular DLL using shared MFC DLL //取名為MFC_dll
2. def文件中添加:函數名(Add_new)
3. h文件中添加:外部函數聲明//求和函數,函數名為Add_new
extern "C" __declspec(dllexport) int __stdcall Add_new(int a,int b);
4. cpp文件中添加: 外部函數實現
extern "C" __declspec(dllexport) int __stdcall Add_new(int a,int b)
{
return a+b;
}
5. build--set active configuration--win32 release--ok
6. 生成
7. 根目錄下release文件夾中dll,lib與根目錄下h文件即為所需
二、 函數----調用動態鏈接庫(把MFC_dll.dll和MFC_dll.lib拷到工程所在目錄)
//靜態調用(.h可以寫到.cpp文件中)
1. new--projects--win32 console application--an empty project
2. 添加h文件:(test.h)
#pragma comment(lib,"MFC_dll.lib") //告訴編譯器DLL相對應的lib文件所在路徑和文件名
extern "C" _declspec(dllimport) int _stdcall Add_new(int a,int b);//聲明導入函數
3. 添加cpp文件:(main.cpp)
#include "test.h"
int main()
{
cout<<Add_new(10,3);
return 0;
}
//動態調用
#include <stdio.h>
#include <windows.h>
typedef int (* lpAddFun)(int ,int);//定義一個與Add_new函數接受參數類型和返回值均相同的函數指針類型
int main()
{
HINSTANCE hDll;//句柄
lpAddFun addFun;//函數指針
hDll=LoadLibrary("dllTest.dll");//動態載入DLL模塊句柄
if(hDll)
{
addFun=(lpAddFun) GetProcAddress(hDll,"Add_new");//得到所載入DLL模塊中函數的地址
if(addFun)
{
int result=addFun(2,3);
printf("%d",result); } FreeLibrary(hDll);//釋放已經載入的DLL模塊
}
return 0;
}
三、 變數----創建動態鏈接庫(非MFC DLL)
1. new---projects---win32 dynamic-link library----an empty project(Sample)
2. 添加sample.h
#ifndef SAMPLE_H
#define SAMPLE_H
extern int dllGlobalVar;
#endif
3. 添加 sample.cpp
#include "sample.h"
#include <windows.h>
int dllGlobalVar;
bool APIENTRY DllMain(HANDLE hMole,DWORD ul_reason_for_call,LPVOID lpReserved)
//windows在載入DLL時,需要一個入口函數,就如同控制台或DOS程序需要main函數、win32程序需要winmain函數一樣。所以引入一個不做任何操作的預設DllMain的函數版本。是DLL的內部函數。
有一點要注意,如果看到此類宏定義
#ifdef KSCANBAR_EXPORTS
#define KSCANBAR_API __declspec(dllexport)
#else
#define KSCANBAR_API __declspec(dllimport)
#endif
是因為這樣定義一般出現在含有多個項目的解決方案中,這樣可以使從 DLL 導出更簡單的宏的標准方法。此 DLL 中的所有文件都是用命令行上定義的 KSCANBAR_EXPORTS符號編譯的。在使用此 DLL 的任何其他項目上不應定義此符號。這樣,源文件中包含此文件的任何其他項目都會將KSCANBAR_API 函數視為是從 DLL 導入的,而此 DLL 則將用此宏定義的符號視為是被導出的。