魚骨頭的雲端圖書館's Archiver

mhfo 發表於 2014-3-6 10:21

C DLL引用參考

C++ 的話,在主程式中加入 DLL 的 .h,然後把 DLL 的 .lib 加到專案引入的 static library中。
這樣主程式中才會有該 DLL 的 call symbol。

若你不想綁死的話,則可以用 LoadLibrary() 載入 DLL,再使用 GetProcAddress() 來取得函式指標,再透過它來呼叫。
不過 GetProcAddress() 只適合 API 型的函式(印象中)。

------------------------------------------------------------------

但是這個是靜態的,找了google老半天也沒有找到有關於動態的方法,有的話也是適用於API 型的函式!並沒找到class的。
題外話不知道微軟的工程師有沒有用過class+動態的方法!
謝謝!!

------------------------------------------------------------------

不是很明白你所謂的「靜態」, 「動態」的意思.

不管是 static library 或是 dynamic-link library 的專案, 它們都會產生一個 .lib 檔. 不同的是 .lib 檔的內容. static library 的 .lib 檔裏的是函式的定義. 在 build exe 專案的時候, linker 會把 static library 裏的函式定義複製到 exe 裏.

DLL 的專案會產生兩個檔: .lib 及 .dll. 所有的定義是放在 .dll 裏. 而 .lib 本身所含的是 export 函式在哪個 .dll 的訊息.

呼叫函式的 DLL 有兩種方法: Load-time dynamic linking, 及 run-time dynamic linking. 這個是在 exe 的專案裏設定的.

如果某個 DLL 是設定為 load-time dynamic linking, linker 會在 exe 裏加入一些訊息, 在一開始執行 exe 的時候去搜尋並載入該 DLL.

如果不用 load-time dynamic linking, 你必須在程式裏呼叫 DLL 裏的函式前用 LoadLibrary[Ex]() 載入 DLL, 然後用 GetProcAddress() 來得到函式的位址, 最後用 function pointer 的方式來呼叫函式.

要用 load-time dynamic linking 至少有兩個方法:
1. 在 exe 專案的 properties 裏, 在 linker 的設定內加入 DLL 所產生的 .lib 檔名.
2. 在 exe 專案裏的原始碼檔內加入:
  #pragma comment(lib, "〔.lib 檔名〕")

你一開始貼的程式不太對:
>MYDLL.h
>class __declspec(dllexport) file

MYDLL.h 一定會用在兩個地方: 產生 DLL 的專案, 及使用 DLL 的專案.

產生 DLL 的專案裏, 要用 __declspec(dllexport).
使用 DLL 的專案裏, 要用 __declspec(dllimport).

如果你不想維修兩個頭檔, 最好就是用 preprocessor 來定義. 比方說:

〔MYDLL.h〕
  #if defined(_MYDLL)
  #if defined(_MYDLL_IMPL)
  #define MYDLL_DECLSPEC __declspec(dllexport)
  #else
  #define MYDLL_DECLSPEC __declspec(dllimport)
  #endif
  #endif

  class MYDLL_DECLSPEC file
  {
    ...
  };

在產生 DLL 的專案裏, 在 project properties 裏定義 _MYDLL 及 _MYDLL_IMPL 這兩個 preprocessor 符號.

在使用 DLL 的專案裏, 在 project properties 裏定義 _MYDLL 這個符號.

-----------------------------------------------------------------------
你一開始貼的程式不太對:
>MYDLL.h
>class __declspec(dllexport) file
因為我想動態應該不需要用到__declspec(dllimport)

〔MYDLL.h〕
  #if defined(_MYDLL)
  #if defined(_MYDLL_IMPL)
  #define MYDLL_DECLSPEC __declspec(dllexport)
  #else
  #define MYDLL_DECLSPEC __declspec(dllimport)
  #endif
  #endif

所以沒有那麼定義!
感謝大大!!

-------------------------------------------------------------

GetProcAddress
[url]http://msdn.microsoft.com/zh-tw/library/64tkc9y5[/url](VS.80).aspx

GetProcAddress function
[url]http://msdn.microsoft.com/en-us/library/ms683212[/url](VS.85).aspx

HowTo: LoadLibrary and GetProcAddress?
[url]http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/Q_21865192.html[/url]

這幾篇參考看看囉...

---------------------------------------------------------------------
//-------- FooInterface.h --------//
#ifndef FOOINTERFACE_H
#define FOOINTERFACE_H

class IFoo
{
public:
int GetNumber() = 0;
void SetNumber( int & ) =0;
};

#endif // FOOINTERFACE_H


//-------- FooClass.h --------//
#ifndef FOOCLASS_H
#define FOOCLASS_H

#include "FooInterface.h"

class Fooclass :public ifoo
{
public:
        FooClass();
const int& GetNumber();
void SetNumber( int & );
private:
int number;
};

#endif         // FOOCLASS_H


//-------- FooClass.cpp --------//

FooClass::FooClass()
{
        number = 0;
}

int FooClass::GetNumber()
{
        return number;
}

void FooClass::SetNumber(int &arg)
{
        number = arg;
}

//-------- DllExports.h --------//
#ifndef DLLEXPORTS_H
#defind DLLEXPORTS_H

#ifdef __dll__
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif         // __dll__

#include "FooClass.h"


extern "C"
void* IMPEXP CreateFooClassInstance();


#endif // DLLEXPORTS_H

//-------- DllMain.cpp --------//
#define __dll__
#include "DllExports.h"

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

void* IMPEXP CreateFooClassInstance();
{
        return static_cast< void* > (new FooClass);
}


//-------- ExeMain.cpp --------//
#include "FooInterface.h"
#include <windows.h>
#include <iostream.h>
#include <conio.h>


int main(int argc, char* argv[])
{
        HINSTANCE hdll = NULL;
        IFoo* piFoo = NULL;
typedef void* (*pvFunctv)();
        pvFunctv CreateFoo;


        hdll = LoadLibrary("DllMain.dll"); // load the dll
        CreateFoo = static_cast < fpFunctv> ( // get the function pointer
        GetProcAddress( hdll, "_CreateFooClassInstance" ) );

        piFoo = static_cast< piFoo* > ( CreateFoo() ); // get pointer to object

        piFoo->gtSetNumber(8); // start using the object
        cout << "Foo::number is epual to: "
        << piFoo-> GetNumber()
        << endl;
....}
>此篇有幫助嗎?
有幫助,謝謝大大!

感覺起來好像變得更繁瑣了,不知道有什麼方法能簡化它?

頁: [1]

Powered by Discuz! Archiver 7.0.0  © 2001-2009 Comsenz Inc.