ぬの部屋(仮)
nu-no-he-ya
  •    1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • C++CLIでdll内のクラスを使う時の error C2011: ‘***’ : ‘class’ 型の再定義

    #pragma onceを忘れたとかそんな話ではない。

    すべてCLIで、testclidll.dll内にクラスClass1を作成し、それをexe側に参照を追加してClass1を使おうとしたとき、

     

    error C2011: ‘testclidll::Class1’ : ‘class’ 型の再定義

     

    が発生する

     

    再現手順 (Visual Studio 2017 community)

    問題1

    1.[ファイル] – [新規作成] – [プロジェクト] から、「CLRコンソールアプリケーション」を作成(名前をexe_and_dll_testとする)

    2.[ファイル] – [新規作成] – [プロジェクト] から、「クラスライブラリ」を作成(名前をtestclidllとする)

    3.testclidll.hを以下のようにする

    // testclidll.h
    #pragma once
    using namespace System;
    namespace testclidll {
    
    
      public ref class Class1
      {
        int c;
      public:
        void Set(int d);
        int Get();
    
      };
    }
    

     

    4.testclidll.cppを以下のようにする

    namespace testclidll {
    
      void Class1::Set(int d){
        c = d;
      }
      int Class1::Get(){
        return c;
      }
    }
    

     

    5.exe側を以下のようにする

    #include "stdafx.h"
    using namespace System;
    #include "../testclidll/testclidll.h"
    int main(array<System::String ^> ^args)
    {
    
      testclidll::Class1^ c = gcnew testclidll::Class1;
    
      c->Set(10);
    
      Console::WriteLine(System::String::Format("{0}\n",c->Get()));
        return 0;
    }
    

     

    6.DLLをコンパイルする

    7.ソリューションエクスプローラから、exe側のプロジェクトを右クリックし、[参照…]を選択

     プロパティページから、[共通プロパティ]-[Frameworkと参照]で「新しい参照の追加…」ボタンを押し、コンパイルしたdllを追加する

    8.exe側をコンパイルする

     

    2>e:\mycodes\exe_and_dll_test\exe_and_dll_test\../testclidll/testclidll.h(12): error C2011: ‘testclidll::Class1’ : ‘class’ 型の再定義
    2> e:\mycodes\exe_and_dll_test\debug\testclidll.dll : ‘testclidll::Class1’ の宣言を確認してください。
    2>exe_and_dll_test.cpp(14): error C2027: 認識できない型 ‘testclidll::Class1’ が使われています。
    2> e:\mycodes\exe_and_dll_test\debug\testclidll.dll : ‘testclidll::Class1’ の宣言を確認してください。
    2>exe_and_dll_test.cpp(14): error C2227: ‘->Set’ : 左側がクラス、構造体、共用体、ジェネリック型へのポインターではありません。
    2>exe_and_dll_test.cpp(18): error C2027: 認識できない型 ‘testclidll::Class1’ が使われています。
    2> e:\mycodes\exe_and_dll_test\debug\testclidll.dll : ‘testclidll::Class1’ の宣言を確認してください。
    2>exe_and_dll_test.cpp(18): error C2227: ‘->Get’ : 左側がクラス、構造体、共用体、ジェネリック型へのポインターではありません。

     

    解決策1

    まず、C/C++ではdllをリンクするときにも必ずヘッダファイルをincludeしなければならないが、.NETではdllが情報を持っている(?)ので、そこへさらにインクルードをかけると定義が二重に行われる(のだと思う)。従って、

    #include "stdafx.h"
    using namespace System;
    //#include "../testclidll/testclidll.h" //このincludeはしてはいけない
    int main(array<System::String ^> ^args)
    {
    
      testclidll::Class1^ c = gcnew testclidll::Class1;
    
      c->Set(10);
    
      Console::WriteLine(System::String::Format("{0}\n",c->Get()));
        return 0;
    }
    

     

    問題2

    再現手順

    1. testclidll.hを、以下のように修正する

    // testclidll.h
    #pragma once
    using namespace System;
    namespace testclidll {
    
      enum ReturnT{ //型を追加
        True,False,
      };
    
      public ref class Class1
      {
        int c;
      public:
        void Set(int d);
        int Get();
    
      ReturnT isOdd(); //メンバが奇数かどうかを返す関数を追加。戻り値はユーザー定義型のReturnT
    
      };
    }
    

     

    2.testclidll.cppを以下のように修正する

    // これは メイン DLL ファイルです。
    #include "stdafx.h"
    #include "testclidll.h"
    namespace testclidll {
    
      void Class1::Set(int d){
        c = d;
      }
      int Class1::Get(){
        return c;
      }
    
      //メンバが奇数かどうかを返す関数の定義
      ReturnT Class1::isOdd(){
    
        if( c % 2 != 0 )
          return True;
    
        return False;
    
      }
    }
    

     

    3.exe側を以下のように修正する

    #include "stdafx.h"
    using namespace System;
    //#include "../testclidll/testclidll.h"
    int main(array<System::String ^> ^args)
    {
    
      testclidll::Class1^ c = gcnew testclidll::Class1;
    
      c->Set(10);
      
      testclidll::ReturnT t = c->isOdd();//奇数かどうかの判定を追加
    
      Console::WriteLine(System::String::Format("{0}\n",c->Get()));
        return 0;
    }
    

     

    4.testclidllをコンパイルする

     

    5.exe側をコンパイルする

     

    コンバイルエラー

    2>exe_and_dll_test.cpp(16): error C2039: ‘ReturnT’ : ‘testclidll’ のメンバーではありません。
    2>exe_and_dll_test.cpp(16): error C2065: ‘ReturnT’ : 定義されていない識別子です。
    2>exe_and_dll_test.cpp(16): error C2146: 構文エラー : ‘;’ が、識別子 ‘t’ の前に必要です。
    2>exe_and_dll_test.cpp(16): error C2065: ‘t’ : 定義されていない識別子です。

     

    これは、クラスの情報は参照したdllの中にあるが、enumのような定数の情報は入っていない(?)ので、定義がないと怒られる。そこで、testclidll.hのincludeを復活させてみる。

    #include "stdafx.h"
    using namespace System;
    #include "../testclidll/testclidll.h" //やっぱりいるのか?
    int main(array<System::String ^> ^args)
    {
    

     

    1>e:\mycodes\exe_and_dll_test\exe_and_dll_test\../testclidll/testclidll.h(14): error C2011: ‘testclidll::Class1’ : ‘class’ 型の再定義
    1> e:\mycodes\exe_and_dll_test\debug\testclidll.dll : ‘testclidll::Class1’ の宣言を確認してください。
    1>exe_and_dll_test.cpp(14): error C2027: 認識できない型 ‘testclidll::Class1’ が使われています。
    1> e:\mycodes\exe_and_dll_test\debug\testclidll.dll : ‘testclidll::Class1’ の宣言を確認してください。
    1>exe_and_dll_test.cpp(14): error C2227: ‘->Set’ : 左側がクラス、構造体、共用体、ジェネリック型へのポインターではありません。
    1>exe_and_dll_test.cpp(16): error C2027: 認識できない型 ‘testclidll::Class1’ が使われています。
    1> e:\mycodes\exe_and_dll_test\debug\testclidll.dll : ‘testclidll::Class1’ の宣言を確認してください。
    1>exe_and_dll_test.cpp(16): error C2227: ‘->isOdd’ : 左側がクラス、構造体、共用体、ジェネリック型へのポインターではありません。
    1>exe_and_dll_test.cpp(18): error C2027: 認識できない型 ‘testclidll::Class1’ が使われています。
    1> e:\mycodes\exe_and_dll_test\debug\testclidll.dll : ‘testclidll::Class1’ の宣言を確認してください。
    1>exe_and_dll_test.cpp(18): error C2227: ‘->Get’ : 左側がクラス、構造体、共用体、ジェネリック型へのポインターではありません。

     

    当然のように最初のエラーが再発する。

     

    解決策2

    enumの定義を別のヘッダファイルへ移動する

    testclidllプロジェクト内、defvalheader.hを追加

    namespace testclidll {
    
      enum ReturnT{
        True,False,
      };
    }
    

    それに伴い、dll本体側であるtestclidll.hからenumの定義を消し、includeにする

    // testclidll.h
    #pragma once
    #include "defvalheader.h" //ReturnTの定義を読み込む
    using namespace System;
    namespace testclidll {
    
      public ref class Class1
      {
        int c;
      public:
        void Set(int d);
        int Get();
    
        ReturnT isOdd();
    
      };
    }
    

     

    exe側では、testclidll.hではなく、defvalheader.hを読み込む

    #include "stdafx.h"
    using namespace System;
    #include "../testclidll/defvalheader.h"
    int main(array<System::String ^> ^args)
    {
    
      testclidll::Class1^ c = gcnew testclidll::Class1;
    
      c->Set(10);
      
      testclidll::ReturnT t = c->isOdd();
    
      Console::WriteLine(System::String::Format("{0}\n",c->Get()));
        return 0;
    }