六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

BCB編寫DLL終極手冊

[摘要]一. 編寫 DLL File/New/Dll 生成 Dll 的向導,然后可以添加導出函數和導出類 導出函數:extern "C" __declspec(dllexport) ExportType FunctionName(Parameter) 導出類:class __de...
一. 編寫 DLL
  File/New/Dll 生成 Dll 的向導,然后可以添加導出函數和導出類
  導出函數:extern "C" __declspec(dllexport) ExportType FunctionName(Parameter)
  導出類:class __declspec(dllexport) ExportType ClassName{...}
  例子:(說明:只是生成了一個 DLL.dll )

#include "DllForm.h"  // TDllFrm 定義

USERES("Dll.res");
USEFORM("DllForm.cpp", DllFrm);

class __declspec(dllexport) __stdcall MyDllClass { //導出類
    public:
       MyDllClass();
       void CreateAForm();
       TDllFrm* DllMyForm;
};

TDllFrm* DllMyForm2;
extern "C" __declspec(dllexport) __stdcall void CreateFromFunct();//導出函數

//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
    return 1;
}
//---------------------------------------------------------------------------

MyDllClass::MyDllClass()
{
}

void MyDllClass::CreateAForm()
{
    DllMyForm = new TDllFrm(Application);
    DllMyForm->Show();
}
//---------------------------------------------------------------------------
void __stdcall CreateFromFunct()
{
    DllMyForm2 = new TDllFrm(Application);
    DllMyForm2->Show();
}


二. 靜態調用 DLL
使用 $BCB path\Bin\implib.exe 生成 Lib 文件,加入到工程文件中
將該文件拷貝到當前目錄,使用 implib MyDll.lib MyDll.dll 生成
// Unit1.h // TForm1 定義
#include "DllForm.h" // TDllFrm 定義
//---------------------------------------------------------------------------

__declspec(dllimport) class __stdcall MyDllClass {
    public:
        MyDllClass();
        void CreateAForm();
        TDllFrm* DllMyForm;
};
extern "C" __declspec(dllimport) __stdcall void CreateFromFunct();

class TForm1 : public TForm{...}


// Unit1.cpp // TForm1 實現
void __fastcall TForm1::Button1Click(TObject *Sender)
{ // 導出類實現,導出類只能使用靜態方式調用
    DllClass = new MyDllClass();
    DllClass->CreateAForm();    
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{ // 導出函數實現
    CreateFromFunct();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
    delete DllClass;
}

三. 動態調用 DLL
// Unit1.h
class TForm1 : public TForm
{
...
private: // User declarations
void (__stdcall *CreateFromFunct)();
...
}

// Unit1.cpp // TForm1
HINSTANCE DLLInst = NULL;
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    if( NULL == DLLInst ) DLLInst = LoadLibrary("DLL.dll"); //上面的 Dll
    if (DLLInst) {
        CreateFromFunct = (void (__stdcall*)()) GetProcAddress(DLLInst,
                                                    "CreateFromFunct");
        if (CreateFromFunct) CreateFromFunct();
        else ShowMessage("Could not obtain function pointer");
    }
    else ShowMessage("Could not load DLL.dll");
}

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
    if ( DLLInst ) FreeLibrary (DLLInst);
}
  
四. DLL 作為 MDIChild (子窗體) 【只編寫動態調用的例子】
    實際上,調用子窗體的 DLL 時,系統只是檢查應用程序的 MainForm 是否為 fsMDIForm 的窗體,這樣只

要把調用程序的 Application 的 Handle 傳遞給 DLL 的 Application 即可;同時退出 DLL 時也要恢復

Application

// MDIChildPro.cpp // Dll 實現 CPP
#include "unit1.h" // TForm1 定義
TApplication *SaveApp = NULL;
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
    if ( (reason==DLL_PROCESS_DETACH) && SaveApp )
        Application = SaveApp ; // 恢復 Application
    return 1;
}

extern "C" __declspec(dllexport) __stdcall void TestMDIChild(    //1024X768
    TApplication* mainApp,
    LPSTR lpCaption)
{
    if ( NULL == SaveApp ) // 保存 Application,傳遞 Application
    {
        SaveApp = Application;
        Application = mainApp;
    }
    // lpCaption 為子窗體的 Caption
    TForm1 *Form1 = new TForm1 ( Application, lpCaption );
    Form1->Show();
}
注:上面的程序使用 BCB 3.0 編譯成功

五. BCB 調用 VC 編寫的 DLL
  1. 名字分解:
    沒有名字分解的函數
        TestFunction1 // __cdecl calling convention
        @TestFunction2 // __fastcall calling convention
        TESTFUNCTION3 // __pascal calling convention
        TestFunction4 // __stdcall calling convention
    有名字分解的函數
        @TestFunction1$QV // __cdecl calling convention
        @TestFunction2$qv // __fastcall calling convention
        TESTFUNCTION3$qqrv // __apscal calling convention
        @TestFunction4$qqrv // __stdcall calling convention
    使用 extern "C" 不會分解函數名

    使用 Impdef MyLib.def MyLib.DLL 生成 def 文件查看是否使用了名字分解

  2. 調用約定:
    __cdecl 缺省
      是 Borland C++ 的缺省的 C 格式命名約定,它在標識符前加一下劃線,以保留
    它原來所有的全程標識符。參數按最右邊參數優先的原則傳遞給棧,然后清棧。
        extaern "C" bool __cdecl TestFunction();
      在 def 文件中顯示為
        TestFunction @1
      注釋: @1 表示函數的順序數,將在“使用別名”時使用。

    __pascal Pascal格式
      這時函數名全部變成大寫,第一個參數先壓棧,然后清棧。
        TESTFUNCTION @1 //def file

    __stdcall 標準調用
      最后一個參數先壓棧,然后清棧。
        TestFunction @1 //def file

    __fastcall 把參數傳遞給寄存器
      第一個參數先壓棧,然后清棧。
        @TestFunction @1 //def file

  3. 解決調用約定:
      Microsoft 與 Borland 的 __stdcall 之間的區別是命名方式。 Borland 采用
    __stdcall 的方式去掉了名字起前的下劃線。 Microsoft 則是在前加上下劃線,在
    后加上 @ ,再后跟為棧保留的字節數。字節數取決于參數在棧所占的空間。每一個
    參數都舍入為 4 的倍數加起來。這種 Miocrosoft 的 DLL 與系統的 DLL 不一樣。

  4. 使用別名:
      使用別名的目的是使調用文件 .OBJ 與 DLL 的 .DEF 文件相匹配。如果還沒有
    .DEF 文件,就應該先建一個。然后把 DEF 文件加入 Project。使用別名應不斷
    修改外部錯誤,如果沒有,還需要將 IMPORTS 部分加入 DEF 文件。
        IMPORTS
        TESTFUNCTIOM4 = DLLprj.TestFunction4
        TESTFUNCTIOM5 = DLLprj.WEP @500
        TESTFUNCTIOM6 = DLLprj.GETHOSTBYADDR @51
      這里需要說明的是,調用應用程序的 .OBJ 名與 DLL 的 .DEF 文件名是等價的,
    而且總是這樣。甚至不用考慮調用約定,它會自動匹配。在前面的例子中,函數被
    說明為 __pascal,因此產生了大寫函數名。這樣鏈接程序不會出錯。

  5. 動態調用例子
VC DLL 的代碼如下:
extern "C" __declspec(dllexport) LPSTR __stdcall BCBLoadVCWin32Stdcall()
{
static char strRetStdcall[256] = "BCB Load VC_Win32 Dll by __stdcall mode is OK!";

return strRetStdcall;
}

extern "C" __declspec(dllexport) LPSTR __cdecl BCBLoadVCWin32Cdecl()
{
static char strRetCdecl[256] = "BCB Load VC_Win32 Dll by __cdecl mode is OK!";

return strRetCdecl;
}

extern "C" __declspec(dllexport) LPSTR __fastcall BCBLoadVCWin32Fastcall()
{
static char strRetFastcall[256] = "BCB Load VC_Win32 Dll by __fastcall mode is OK!";

return strRetFastcall;
}

     其實動態調用與調用 BCB 編寫的 DLL 沒有區別,關鍵是查看 DLL 的導出函數名字
     可以使用 tdump.exe(BCB工具) 或者 dumpbin.exe(VC工具) 查看
     tdump -ee MyDll.dll >1.txt (查看 1.txt 文件即可)
     由于 VC6 不支持 __pascall 方式,下面給出一個三種方式的例子
void __fastcall TForm1::btnBLVCWin32DynClick(TObject *Sender)
{
    /*cmd: tdbump VCWin32.dll >1.txt
Turbo Dump  Version 5.0.16.4 Copyright (c) 1988, 1998 Borland International
                    Display of File VCWIN32.DLL

EXPORT ord:0000='BCBLoadVCWin32Fastcall::'
EXPORT ord:0001='BCBLoadVCWin32Cdecl'
EXPORT ord:0002='_BCBLoadVCWin32Stdcall@0'
    */
    if ( !DllInst )
        DllInst = LoadLibrary ( "VCWin32.dll" );
    if ( DllInst )
    {
        BCBLoadVCWin32Stdcall = (LPSTR (__stdcall *) () )
            GetProcAddress ( DllInst, "_BCBLoadVCWin32Stdcall@0" ); //VC Dll
            // GetProcAddress ( DllInst, "BCBLoadVCWin32Stdcall" ); //BCB Dll
        if ( BCBLoadVCWin32Stdcall )
        {
            ShowMessage( BCBLoadVCWin32Stdcall() );
        }
        else ShowMessage ( "Can't find the __stdcall Function!" );

        BCBLoadVCWin32Cdecl = (LPSTR (__cdecl *) () )
            GetProcAddress ( DllInst, "BCBLoadVCWin32Cdecl" );
        if ( BCBLoadVCWin32Cdecl )
        {
            ShowMessage( BCBLoadVCWin32Cdecl() );
        }
        else ShowMessage ( "Can't find the __cdecl Function!" );

        //Why?不是 'BCBLoadVCWin32Fastcall::',而是 '@BCBLoadVCWin32Fastcall@0'?
        BCBLoadVCWin32Fastcall = (LPSTR (__fastcall *) () )
            //GetProcAddress ( DllInst, "BCBLoadVCWin32Fastcall::" );
            GetProcAddress ( DllInst, "@BCBLoadVCWin32Fastcall@0" );
        if ( BCBLoadVCWin32Fastcall )
        {
            ShowMessage( BCBLoadVCWin32Fastcall() );
        }
        else ShowMessage ( "Can't find the __fastcall Function!" );
    }
    else ShowMessage ( "Can't find the Dll!" );
}

  6. 靜態調用例子
     靜態調用有點麻煩,從動態調用中可以知道導出函數的名字,但是直接時(加入 lib 文件到工程文件)

Linker 提示不能找到函數的實現
     從 4 看出,可以加入 def 文件連接
     (可以通過 impdef MyDll.def MyDll.dll 獲得導出表)
     建立與 DLL 文件名一樣的 def 文件與 lib 文件一起加入到工程文件
     上面的 DLL(VCWIN32.dll) 的 def 文件為(VCWIN32.def):
LIBRARY     VCWIN32.DLL

IMPORTS
    @BCBLoadVCWin32Fastcall     = VCWIN32.@BCBLoadVCWin32Fastcall@0
    _BCBLoadVCWin32Cdecl        = VCWIN32.BCBLoadVCWin32Cdecl
    BCBLoadVCWin32Stdcall       = VCWIN32._BCBLoadVCWin32Stdcall@0

對應的函數聲明和實現如下:
extern "C" __declspec(dllimport) LPSTR __fastcall BCBLoadVCWin32Fastcall();
extern "C" __declspec(dllimport) LPSTR __cdecl BCBLoadVCWin32Cdecl();
extern "C" __declspec(dllimport) LPSTR __stdcall BCBLoadVCWin32Stdcall();

void __fastcall TfrmStatic::btnLoadDllClick(TObject *Sender)
{
    ShowMessage ( BCBLoadVCWin32Fastcall() );
    ShowMessage ( BCBLoadVCWin32Cdecl() );
    ShowMessage ( BCBLoadVCWin32Stdcall() );
}
注意:在 BCB 5.0 中,可能直接按下 F9 是不能通過 Linker 的,請先 Build 一次
注:上面的程序使用 BCB 5.0 與 VC6.0 編譯成功


主站蜘蛛池模板: 婷婷四房综合激情五月性色 | 午夜精品久视频在线观看 | 酥酥影院一级毛片在线看 | 日韩一卡 二卡 三卡 四卡 免费视频 | 婷婷中文| 深夜视频在线看 | 在线观看亚洲免费 | 五月亭亭激情五月 | 四虎精品影院永久在线播放 | 日本成年人免费看 | 日韩 欧美 中文 | 欧美综合一区 | 日韩中文字幕精品免费一区 | 色噜噜亚洲 | 日韩欧美一及在线播放 | 亚洲欧美日韩国产 | 野草影院手机在线观看免费6 | 日美一级毛片 | 手机看片91精品一区 | 日本七大伦理经典在线观看 | 日韩18在线观看地址 | 网址在线观看 | 日韩一级淫片 | 色橹 | 午夜视频在线观看完整高清在线 | 天天躁狠狠躁夜夜躁2021 | 欧美在线观看视频网站 | 色综合合久久天天给综看 | 色综合网天天综合色中文男男 | 日日草夜夜操 | 亚洲视频一区二区在线观看 | 四虎必出精品亚洲高清 | 视频精品一区二区 | 色姣姣狠狠撩综合网 | 日日干天天爽 | 性做久久久久久久免费看 | 真实的国产乱xxxx | 人妖欧美一区二区三区四区 | 亚洲欧美日本韩国综合在线观看 | 四虎免费在线观看视频 | 香蕉久久夜色精品国产小说 |