none
DLL内に作ったクラスのメンバ関数の利用方法を教えてください。 RRS feed

  • 質問

  • どうも、こんにちわ。

    VC++の初心者です。

     

    質問したい内容は、件名に記した通りです。

    環境は、

    WinXP

    VS 2005 ver.8

    VC++

    です。

     

    Win32コンソールアプリケーション/DLLを選択。
    プロジェクト名は、MyDll としました。

    ■MyDll.hに
    追加するクラスを宣言しました。

    //追加コード
    class MyClass1{
     char sDat1[80];
    public:
     MyClass1(char *s1);
     MyClass1();
     ~MyClass1();
     void SetAdd(int a, int b, int *c);
    };

    ■MyDll.cpp
    追加クラスの実装

    //追加コード
    MyClass1::MyClass1(char *s1)
    {
     lstrcpy(sDat1, s1);
     MessageBox(NULL, sDat1, "MyClass1のコンストラクタ", MB_OK);
    }
    MyClass1::MyClass1()
    {
     sDat1[0] = '\0';
     MessageBox(NULL, sDat1, "MyClass1のコンストラクタ", MB_OK);
    }
    MyClass1::~MyClass1()
    {
     MessageBox(NULL, sDat1, "MyClass1のデストラクタ", MB_OK);
    }
    void MyClass1:Tongue TiedetAdd(int a, int b, int *c)
    {
     *c = a + b;
    }

    ☆上の文字化けしたメンバ関数の名前は、SetAdd()です。

     

    これでビルドをしまして、
    MyDll.dll と MyDll.lib の生成に成功しました。

    ■次にWin32コンソールアプリケーション/Windowsアプリケーションを選択。
    プロジェクト名は、UseDll としました。

    ■UseDll.cppのコード一部
    // UseDll.cpp : アプリケーションのエントリ ポイントを定義します。
    //

    #include "stdafx.h"
    #include "UseDll.h"   //☆★☆追加コード
    #include "MyDll.h"   //☆★☆追加コード
    #pragma comment(lib, "MyDll.lib") //☆★☆追加コード

    __declspec(dllimport) void SetAdd(int, int, int *); //☆★☆追加コード

    ///////////////////////////////////////////////////


    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
      UNREFERENCED_PARAMETER(hPrevInstance);
      UNREFERENCED_PARAMETER(lpCmdLine);

     

      // TODO: ここにコードを挿入してください。
      //☆★☆記述箇所はここからです。

      MyClass1 ob1;
      int suu1 = 0;
      ob1.SetAdd(100, 200, &suu1);

      return 0;

      //☆★☆記述箇所は、ここまで。

      MSG msg;
      HACCEL hAccelTable;

    上記のように追加して、DLLにあるメンバ関数を
    活用しようとしているのですが、うまく行かない次第です。

    クラスのメンバ関数宣言がエラー箇所でして、

    UseDll.obj : error LNK2019: 未解決の外部シンボル "public: __thiscall MyClass1::~MyClass1(void)" (??1MyClass1@@QAE@XZ) が関数 _wWinMain@16 で参照されました。
    UseDll.obj : error LNK2019: 未解決の外部シンボル "public: void __thiscall MyClass1:Tongue TiedetAdd(int,int,int *)" (?SetAdd@MyClass1@@QAEXHHPAH@Z) が関数 _wWinMain@16 で参照されました。
    UseDll.obj : error LNK2019: 未解決の外部シンボル "public: __thiscall MyClass1::MyClass1(void)" (??0MyClass1@@QAE@XZ) が関数 _wWinMain@16 で参照されました。
    \UseDll\Debug\UseDll.exe : fatal error LNK1120: 外部参照 3 が未解決です。

    が出力されます。

     

    DLLの関数呼び出し方法は、わかったのですが、
    クラスのメンバ関数呼び出しとなると、その方法を模索中の状態です。

     

    ご教授のほど、よろしくお願いします。

    2007年5月10日 9:17

回答

  • クラスの場合、クラスごとエクスポートする必要があります。

    SetAddはMyClass1のメンバ関数(メソッド)ですので、
    >__declspec(dllimport) void SetAdd(int, int, int *); //☆★☆追加コード
    はまったくもって意味を持ちません。
    →不要

    MSDN
    http://msdn2.microsoft.com/ja-jp/library/a90k134d(VS.80).aspx

    関数のときと同様、__declspecをclassキーワードの直後に指定します。
    コード書くのは面倒ですので、Googleとかで、「クラス __declspec DLL」等をキーワードに
    検索してみてください。
    2007年5月10日 9:44

すべての返信

  • クラスの場合、クラスごとエクスポートする必要があります。

    SetAddはMyClass1のメンバ関数(メソッド)ですので、
    >__declspec(dllimport) void SetAdd(int, int, int *); //☆★☆追加コード
    はまったくもって意味を持ちません。
    →不要

    MSDN
    http://msdn2.microsoft.com/ja-jp/library/a90k134d(VS.80).aspx

    関数のときと同様、__declspecをclassキーワードの直後に指定します。
    コード書くのは面倒ですので、Googleとかで、「クラス __declspec DLL」等をキーワードに
    検索してみてください。
    2007年5月10日 9:44
  • 早速のご回答、ありがとうございます。

     

    ご教授くださった内容を試してみたのですが、なかなかうまく行きません。

    ■MyDll.hで、

    class __declspec(dllexport) MyClass1{

     

    とコードを修正しました。

    ビルドは成功しました。

     

    ■次にUseDll.cppの方で、

    __declspec(dllimport) MyClass1{
    public:
     MyClass1(char *s1);
     MyClass1();
     ~MyClass1();
     void SetAdd(int a, int b, int *c);
    };

    とコードを修正しました。

    ビルドすると、

    usedll.cpp(13) : warning C4091: '__declspec(dllimport)' : 変数が何も宣言されていないときは、'MyClass1' の左辺を無視します。
    usedll.cpp(13) : error C2143: 構文エラー : ';' が '{' の前にありません。
    usedll.cpp(13) : error C2447: '{' : 対応する関数ヘッダーがありません (旧形式の仮引数リスト?)

    と3つのエラーが出ます。

     

    ■MainDllの所で、オブジェクト宣言をして、メンバ関数を呼んでいます。

     

     MyClass1 obj1;
     int suu1 = 0;

     obj1.SetAdd(100,200, &suu1);

     

     この状態で、あれこれと模索しています。

     問題解決の方法、ご教授のほど、よろしくお願いします。

     

     

    2007年5月10日 10:56
  •  

    おかげさまで、なんとかうまくDLL内のクラスのメンバ関数を呼び出すことができました。

    的確なアドバイス、ありがとうございました。

     

    UseDll.cppのコードで

    __declspec(dllimport) MyClass1;

     

    と修正しまして、成功した次第です。

     

    余分にメンバ関数を再定義してしまったのが悪かったようです。

     

    これでなんとか、DLLでクラスを扱えそうです。

     

    毎度毎度、明解なご指摘、恐れ入ります。

    ありがとうございました。

    2007年5月10日 11:51
  • >__declspec(dllimport) MyClass1{
    classが頭に抜けているけど。


    というか、DLLの関数やクラスを使いたい場合、一般的にはDLL側で作成したヘッダファイルを
    インクルードして使えるように記述すするのですが、参考にされている本にはそこらへんを
    触れていないでしょうか?

    http://msdn2.microsoft.com/ja-jp/library/8fskxacy(VS.80).aspx
    のコードを使わせてもらうと

    MyDll.hでは

    #ifdef _EXPORTING
       #define CLASS_DECLSPEC    __declspec(dllexport)
    #else
       #define CLASS_DECLSPEC    __declspec(dllimport)
    #endif

    class CLASS_DECLSPEC MyClass1{
    // 省略


    として、MyDll.cppでは

    #define _EXPORTING
    #include "MyDll.h"
    // 省略


    として、DLLを作成します。
    そして、DLLを使う側では、

    #include "MyDll.h"
    #pragma comment(lib, "MyDll.lib") // コンパイルオプションでも指定可
    // 省略

    とします。
    2007年5月10日 11:57