2015年11月15日 星期日

hello world之 在windows建立dll檔

前言

使用dll檔,有兩種,一種是要用lib加入編譯的,一種不用。
在此,是介紹不用的那種。
另外,這次的dll包裝是包裝成c語言的呼叫型式。

使用工具: visual studio 2005
環境: Windows 8

開始囉!

要準備兩個專案檔,一個是dll檔,一個是執行檔
dll檔為外掛程式,執行檔為核心程式,核心程式初始化時,dll檔就可以載進來當作是核心程式的外掛。

先說說dll檔

新增專案[1]
Project type: Win32 Console Application
Application type: DLL
Additional options: Empty project

dll_hello_world.h
這是用來設定共用介面的檔案,必須要加到核心程式的專案中,一起編譯。
extern "C" __declspec(dllexport) 
const char* HelloWorld();

dll_hello_world.cpp
 #include "dll_hello_world.h"  

__declspec(dllexport)
const char* HelloWorld()
{
return "hello world";
}

再看看執行檔

新增專案[1]
Project type: Win32 Console Application
Application type: Console Application
Additional options: Empty project

這段程式碼,是參考[1]修改而來的,對於dll檔,我又再包了一層dll檔的類別。
每一步的行為都進行了分類,方便讀者對於dll檔的行為做區分。

main.cpp
#include "dll_hello_world.h"
#include <exception>
#include <string>
#include <iostream>
#include <Windows.h>

class DllFile
{
typedef const char *(*CreateCallBack)();
CreateCallBack call_function;
HINSTANCE dll_core;
public:
DllFile(const std::string &dll_filename)
try
{
dll_core = LoadLibrary(dll_filename.data()); //[2]
if (dll_core == 0)
{
throw std::exception("load Dll not success.");
}
}
catch(std::exception &e)
{
FreeLibrary(dll_core);
throw ;
}
catch(...)
{
FreeLibrary(dll_core);
throw std::exception("initial DLL false.");
}

~DllFile()
{
FreeLibrary(dll_core);
}

const char* CallFunction(const std::string &symbolname)
{
call_function = (CreateCallBack)GetProcAddress(dll_core, symbolname.data());
if (call_function != 0)
{
return call_function();
}
else
{
FreeLibrary(dll_core);
throw std::exception("can not function of DLL.");
}
}
};


int main()
{
try
{
DllFile demo_file("dllfile.dll");
std::cout << demo_file.CallFunction("HelloWorld") << std::endl;
}
catch(std::exception &e)
{
std::cout << "ERROR:" << e.what() << std::endl;
}
system("PAUSE");

return 0;
}

可能會遇到的問題


  • 問題: error C2664: 'LoadLibraryW' : cannot convert parameter 1 from 'const char *' to 'LPCWSTR'
    解法: 設定專案檔的字集為Use Multi-Byte Character Set(不要用Unicode)

程式碼

放在: github (已固定版本)

參考資料

[1] [C++ 小學堂] 如何建立 export 的 dll 與如何動態呼叫 export 的 dll
[2] (原创)一个简洁通用的调用DLL函数的帮助类
[3] Error C2664 LoadLibraryW cannot convert parameter to LPCWSTR

沒有留言:

張貼留言