VisualStodio.netで クラスをdllで作成して、
そのクラスを使用できるようにしたいのですが、クラスを作成する方法
と使用する方法がわかりません。
#ifdef CLASS_EXPORTS
#define CLASS_API __declspec(dllexport)
#else
#define CLASS_API __declspec(dllimport)
#endif
#include <dinput.h>
#pragma comment (lib,dinput8.lib)
class CLASS_API InputBase
{
class CLASS_API InputMouse : public InputBase
{
GUID Gu;
InputMouse()
{
Gu = GUID_SysMouse;
}
}
こんな感じで定義しているのですが、ビルドすると”外部シンボル GUID_SysMouse は未
解決です”
などといわれてしまいます。
もし、コンパイルが成功しても使用方法がわかりません。
通常の関数ならGetProcAddressで取得できるようですが、クラスや変数なども
同じように使用するのでしょうか?
まず、目的をはっきりさせてください。
「何のために」クラスを DLL 内に置きたいのですか?
書き込みからは、それすらわかっていないような印象を受けます。
> ”外部シンボル GUID_SysMouse は未解決です”などといわれてしまいます。
このエラーと、クラスを DLL 内に置くことは関係ありません。
まずは KAB-studio あたりで、クラスを DLL に置く方法を確実に学び、DirectInput な
り何なりはそれからにしたほうがいいと思います。
KAB-studio
http://www.kab-studio.biz/
Codian(KAB-studio内)
http://www.kab-studio.biz/Programing/Codian/
こちらの「DLL を作ろう!」あたりをよくお読みください。
ついでに、示されたコードはなかなか無茶苦茶です。
本当にプログラム中でもこう書いているのなら、GUID_SysMouse がどうこう以前の問題
です。
C++ について、しっかり学ばれることをお勧めします。
>ついでに、示されたコードはなかなか無茶苦茶です。
>本当にプログラム中でもこう書いているのなら、GUID_SysMouse がどうこう以前の問題
>です。
すみません、どのあたりが無茶苦茶なのでしょうか?
> class CLASS_API InputBase
> {
クラス定義が閉じられていません
> class CLASS_API InputMouse : public InputBase
> {
> GUID Gu;
> InputMouse()
> {
> Gu = GUID_SysMouse;
> }
> }
コンストラクタが private です。このクラスのインスタンスは、このクラスの中からし
か作成できません(承知してやってるなら構いませんが)。
しかし、個人的には承知の上でコンストラクタを private にしている場合でも、明示的
に private 指定することをおすすめします・
>クラス定義が閉じられていません
>コンストラクタが private です。このクラスのインスタンスは、このクラスの中からし
>か作成できません(承知してやってるなら構いませんが
この状態なら コンパイルもとおりませんね。
実際のソースでは 定義は閉じていますし
コンストラクタはpublicでやっています。
”外部シンボル GUID_SysMouse は未解決です”
といわれていたものは、 dllを作成する部分とdllを使用する部分を
同じソリューションでやっていたために起きていたようです。
二つのソリューションとして分けたら、このエラーはなくなりました。
dllを作成するほうでエラーがなくなったので、使用するほうにヘッダとdllをもっていって
InputMouse を宣言したら、
未解決の外部シンボル __declspec(dllimport) public: __thiscall
InputMouse::InputMouse(void) (__imp_??0DInputMouse@@QAE@XZ) が関数 public:
long __thiscall CMainDlg::OnInitDialog(unsigned int,unsigned int,long,int &)
(?OnInitDialog@CMainDlg@@QAEJIIJAAH@Z) で参照されました。
というエラーが表示されました
コンストラクタを書いているし、なぜエラーがでるのかわかりません。
class CLASS_API InputMouse を class InputMouse に変更したらエラーはなくなり
ました。
> この状態なら コンパイルもとおりませんね。
> 実際のソースでは 定義は閉じていますし
> コンストラクタはpublicでやっています。
でしょうね。ですから一応
> 本当にプログラム中でもこう書いているのなら
と書いておいたわけですが。
> 使用するほうにヘッダとdllをもっていって
LIB が必要なんじゃないですか?
>LIB が必要なんじゃないですか?
Libを持っていったらコンパイルがとおりました。
ありがとうございます。
教えていただいたHPを見てみると、Libファイルを使用しないやり方の
場合は、関数しか使用できないみたいですね。
ということは関数を使用してクラスのポインタを作成するのが一般的なのでしょうか?
とりあえず、いろいろ試してみたいとおもいます。
いろいろ試してみました。
関数で クラスのポインタを取得するようにしました。
extern C CLASS_API InputMouse * CreateInputMouse()
{
OutputDebugString(CreateInputMouse\n);
return new InputMouse();
}
この取得したクラスポインタを使用しメンバ関数を呼ぼうとおもいましたが、
なぜか
未解決の外部シンボル __declspec(dllimport) public: void __thiscall
InputMouse::test(void) (__imp_?test@InputMouse@@QAEXXZ) が関数 public: long
__thiscall CMainDlg::OnInitDialog(unsigned int,unsigned int,long,int &)
(?OnInitDialog@CMainDlg@@QAEJIIJAAH@Z) で参照されました。
Debug/DInputTool.exe : fatal error LNK1120: 外部参照 1 が未解決です。
というエラーが表示されてしまい使用できませんでした。
Virtualで宣言してあったメンバ関数は呼ぶことができました。
なぜこのようなことになっているのでしょうか?
1>未解決の外部シンボル
>__declspec(dllimport) public: void __thiscallInputMouse::test(void)
> (__imp_?test@InputMouse@@QAEXXZ) が関数
2>public: long__thiscall CMainDlg::OnInitDialog(unsigned int,unsigned
int,long,int &)
3>(?OnInitDialog@CMainDlg@@QAEJIIJAAH@Z) で参照されました。
>Debug/DInputTool.exe :
4>fatal error LNK1120: 外部参照 1 が未解決です。
>InputMouse::test
お前さん 自分で質問していてエラー意味わかってないだろ
分解してじっくり読むと
InputMouse クラスのメンバ関数「test」が
CMainDlgクラスの関数「OnInitDialog」で参照されたことを示しています
何言いたいかといえばあなたが提示したソースコードには、関数「test」が
無いためまたは、関数「OnInitDialog」のソースコードが示されておらず
関係のなさそうなソースコードしか提示されていないので
誰も答えられないということです
まずはエラーコード「LNK1120」をMSDNから拾う勉強からはじめてください
> __imp_?test@InputMouse@@QAEXXZ
とか
> ?OnInitDialog@CMainDlg@@QAEJIIJAAH@Z
とか
訳分からない(よく見れば分からないこともないんですが)文字列を見やすくするツー
ルというのが VisualStudio に添付されています。
undname というツールですので、もしよかったら使ってみてください。
VS.NET 2003 ならスタートメニューに「VS.NET 2003 コマンドプロンプト」ってのがあ
るのでこれを起動してから undname 。
2002 以前にはこのコマンドプロンプトは無かったと思いますが…VCVARS32.BAT から起
動すればできると思います。たぶん。
まぁ、CMainDlg::OnInitDialog で InputMouse::test を呼ぼうとしてるけど、LIB ファ
イルが無いから InputMouse がどんなものかわからずにエラー、てことでしょうね。
なぜ LIB ファイルを使いたくないのか分かりませんが、使わないのであれば関数しか使
えませんというのは理解してらっしゃるようなのでもう一言。
関数しか使えないということは、たとえ関数でクラスのインスタンスを作成しようと
も、そのインスタンスが使えないということです。
どうしても LIB ファイルを使わないのであれば、クラスのメソッドを呼び出す関数を個
別に作らねばならないかと思います。
微妙に訂正
> LIB ファイルが無いから InputMouse がどんなものかわからずに
ヘッダファイルがあるんだから INputMouse クラスがどんなものかはわかってますね。
LIB ファイルの役割は…そのクラスの実体が DLL の中にありますよ、ということを教え
ることでしょうか。
ヘッダファイルにあるのはクラスの宣言だけで、LIB がないと定義がどこにあるのかわ
からないわけですね。…たぶん。
>たとえ関数でクラスのインスタンスを作成しようと
>も、そのインスタンスが使えないということです。
>どうしても LIB ファイルを使わないのであれば、クラスのメソッドを呼び出す関数を個
>別に作らねばならないかと思います。
現在このようになっています
CreateInputMouse *Input =
(CreateInputMouse*)this->m_Module.GetProcAddress(CreateInputMouse);
InputMouse *pIMouse = Input();
hRet = pIMouse->Create(g_hInst, this->m_hWnd);
pIMouse->test(); <-virtual宣言したら呼べるようになりました。
コンパイルが成功して関数も呼べているようですが、
やってはいけないということなのでしょうか?
それと、インスタンスが使用できないのであれば、
CreateInputMouse *Input =
(CreateInputMouse*)this->m_Module.GetProcAddress(CreateInputMouse);
InputMouse *pIMouse = Input();
このあと
TEST *pTest = (TEST*)this->m_Module.GetProcAddress(Test);
pTest(pIMouse);
というような関数を呼ぶ方法も駄目なんですよね?
このようになってますって言われても、他の部分が分からないのでなんともコメントで
きません。
CreateInputMouse の定義とか Input 関数とか InputMouse の定義とか m_Module と
か。
現在は、 GetProcAddress で CreateInputMouse という関数を取得し
その関数を使用して InputMouseというクラスを作成しています。
pIMouse->testでメンバ関数を呼んでいます。
//dll作成側
#ifdef CLASS_EXPORTS
#define CLASS_API __declspec(dllexport)
#else
#define CLASS_API __declspec(dllimport)
#endif
extern C CLASS_API DInputMouse * CreateInputMouse()
{
return new InputMouse();
}
class CLASS_API InputMouse
{
public:
InputMouse()
{
}
~InputMouse()
{
}
virtual void test();
}
void InputMouse::test()
{
OutputDebugString(testが呼ばれました);
}
//使用する側
CreateInputMouse *Input =
(CreateInputMouse*)this->m_Module.GetProcAddress(CreateInputMouse);
InputMouse *pIMouse = Input();
pIMouse->test();
>たとえ関数でクラスのインスタンスを作成しようと
>も、そのインスタンスが使えないということです。
>どうしても LIB ファイルを使わないのであれば、クラスのメソッドを呼び出す関数を個
>別に作らねばならないかと思います。
インスタンス作成が駄目で関数しか使用してはいけないとしたら
私が現在やっている方法は、関数経由でインスタンスを作成し、そのインスタンスから関
数を呼んでいるので別な方法にしないといけないということなんですよね?
実際、どのような方法を使えばよいのでしょうか?