DLLからC++のオブジェクトをエクスポートして、アプリケーション側で使用する方法です。
DLLからC++のオブジェクトをエクスポートには、いくつかの制限があります。
新規ダイナミックライブラリの画面が表示されるので、次のように選択します。
ソースの種類「C++」
マルチスレッド「チェックしない」
VC++スタイルのDLL「チェックしない」
「OK」ボタンを押します。
以上で、プロジェクトが作成されます。
エクスポートするクラスを作成します。
//抽象基底クラス
#include <string>
class TPerson
{
public:
virtual void STDMETHODCALLTYPE SetName(const char* Name) = 0;
virtual const char* STDMETHODCALLTYPE GetName() const = 0;
};
//派生クラス
class TStudent : public TPerson
{
public:
TStudent(const char* Name) : FName(Name) {}
void STDMETHODCALLTYPE SetName(const char* Name) { FName = Name; }
const char* STDMETHODCALLTYPE GetName() const { return FName.c_str(); }
private:
std::string FName;
};
オブジェクトの生成と破棄を行う関数を作成します。
extern "C" TPerson* STDMETHODCALLTYPE __declspec(dllexport) CreatePerson()
{
return new TStudent("Taro");
}
extern "C" void STDMETHODCALLTYPE __declspec(dllexport) DeletePerson(TPerson* Person)
{
delete Person;
}
全体のソースコードは次のようになります。
#include <windows.h>
#include <string>
//抽象基底クラス
class TPerson
{
public:
virtual void STDMETHODCALLTYPE SetName(const char* Name) = 0;
virtual const char* STDMETHODCALLTYPE GetName() const = 0;
};
//派生クラス
class TStudent : public TPerson
{
public:
TStudent(const char* Name) : FName(Name) {}
void STDMETHODCALLTYPE SetName(const char* Name) { FName = Name; }
const char* STDMETHODCALLTYPE GetName() const { return FName.c_str(); }
private:
std::string FName;
};
//オブジェクトの生成を行う関数
extern "C" TPerson* STDMETHODCALLTYPE __declspec(dllexport) CreatePerson()
{
return new TStudent("Taro");
}
//オブジェクトの破棄を行う関数
extern "C" void STDMETHODCALLTYPE __declspec(dllexport) DeletePerson(TPerson* Person)
{
delete Person;
}
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
今回は簡単な動的なロードの方法で作成します。
DLLのオブジェクトの定義を作成します。
class TPerson
{
public:
virtual void STDMETHODCALLTYPE SetName(const char* Name) = 0;
virtual const char* STDMETHODCALLTYPE GetName() const = 0;
};
DLLの関数の定義を作成します。
typedef TPerson* (STDMETHODCALLTYPE *TCreatePerson)();
typedef void (STDMETHODCALLTYPE *TDeletePerson)(TPerson* Person);
DLLの読み込みには、LoadLibrary()関数を使用します。
HMODULE hLibModule = LoadLibrary("Project1.dll");
DLLの破棄には、FreeLibrary()関数を使用します。
FreeLibrary(hLibModule);
DLLの関数のアドレスの取得します。
TCreatePerson CreatePerson = reinterpret_cast<TCreatePerson>(GetProcAddress(hLibModule, "CreatePerson"));
TDeletePerson DeletePerson = reinterpret_cast<TDeletePerson>(GetProcAddress(hLibModule, "DeletePerson"));
オブジェクトを作成して、使用します。
TPerson* person = CreatePerson();
std::puts(person->GetName()); //=> Taro
person->SetName("Jiro");
std::puts(person->GetName());//=> Jiro
全体のソースコードは次のようになります。
#pragma hdrstop
#include <tchar.h>
#include <windows.h>
#include <iostream>
class TPerson
{
public:
virtual void STDMETHODCALLTYPE SetName(const char* Name) = 0;
virtual const char* STDMETHODCALLTYPE GetName() const = 0;
};
typedef TPerson* (STDMETHODCALLTYPE *TCreatePerson)();
typedef void (STDMETHODCALLTYPE *TDeletePerson)(TPerson* Person);
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hLibModule = LoadLibrary("Project1.dll");
TCreatePerson CreatePerson = reinterpret_cast<TCreatePerson>(GetProcAddress(hLibModule, "CreatePerson"));
TDeletePerson DeletePerson = reinterpret_cast<TDeletePerson>(GetProcAddress(hLibModule, "DeletePerson"));
TPerson* person = CreatePerson();
std::puts(person->GetName()); //=> Taro
person->SetName("Jiro");
std::puts(person->GetName()); //=> Jiro
DeletePerson(person);
FreeLibrary(hLibModule);
return 0;
}
Borland C++Builder 6実用プログラミング―オブジェクトとその再利用の方法
C++BuilderによるDLL、VCLパッケージ、COM/ActiveXの利用方法が解説されています。
DLLの利用方法についても、Variant配列やSafeArrayを受け渡しする方法やBDEデータベースハンドルを共有する方法など、非常に専門的な内容を取り扱っています。