none
[C++/CLI]#make_publicの使い方について RRS feed

  • 質問

  •  

    現在MFCアプリを.NET Formsアプリに移植しております。

    make_publicを使用して作成したDLLにて、リンカエラーが発生しております。

     

    [開発環境]

    OS:Vista 32bit

    IDE:VC++2008 EE

     

    [プロジェクト構成]

    1.Windows Forms Application(exe)

    2.Class Library(DLL)

      ※1.のexeは2.のDLLを参照しています。

      ※1.、2.ともManaged/Unmanaged(Native)のコードが含まれます。

     

    [エラー内容]

    error LNK2022: metadata operation failed (80131195) : カスタム属性が適合しません

     

    [再現手順]

    1.New Project -> CLR -> Class Libraryを選択して新規DLLプロジェクトを作成する

      (プロジェクト名はlibtest)

     

    2.stdafx.hに以下を記述

    Code Snippet

    #include <windows.h>
    #pragma make_public(RECT)

     

    3.libtest.hに以下を記述

    Code Snippet
     public ref class Class1
     {
      // TODO: Add your methods for this class here.
      static void Do(RECT rRect)
      {
       
      }
     };

     

     

    4.Solution CoinfigurationsでReleaseを選択し、ビルド

    5.以下リンカエラーが発生する

      1>libtest.obj : error LNK2022: metadata operation failed (80131195) : カスタム属性が適合しません: (0x0c00021b)。
      1>Stdafx.obj : error LNK2022: metadata operation failed (80131195) : カスタム属性が適合しません: (0x0c000261)。

     

    [質問内容]

    1.Unmanaged型を引数で渡すのは、言語仕様として問題ありますか?

    2.Unmanaged型を引数で渡す手段は変えずに、本エラーを回避する手段はありますか?


    デバッグビルドでは発生しないため、最適化によるエラーだと考えていますが、

    本件の解決手段をご存知の方、ご回答いただければと思います。

     

    こちらで検討している最終的な解決手段としては、「Unmanaged型はすべてIntPtrによる引き渡し」を考えておりますが、

    修正範囲が膨大のため、可能な限りUnmanaged型のまま引き渡す手段を模索しています。

     

    よろしくお願いします。

    2008年2月10日 0:30

回答

  • C.Johnさん、アドバイス及び推察有難うございます。

     

    >リンクに失敗するものだけ自前の名前空間で再定義してやるといった方法はどうでしょう

    頂いたアドバイスで、検討したいと思います。
    2008年2月16日 10:18

すべての返信

  • 原因の特定はできませんでしたが、とりあえず試してみた事だけ。

     

    ・「構成プロパティ」→「全般」→「プログラム全体の最適化」を「プログラム全体の最適化なし」にするとビルド成功

    ・RECTではなく、POINTなどにするとビルド成功

    ・struct tagRECT型を自分で定義し、メンバは正規のtagRECT型とは変更しておくと「LNK2022: メタデータの操作に失敗しました (8013118D) : 重複する型に、適合しないレイアウト情報があります (tagRECT): (0x02000003)。」のリンカエラーが発生する。

     

    <推定>

    おそらく、RECT型はVCのランタイム(MSVCMRT.lib)側でmake_publicされていて、最適化(リンク時のコード生成)を行うとバッティングするためではないでしょうか。

    質問2は最適化をはずすか、リンクに失敗するものだけ自前の名前空間で再定義してやるといった方法はどうでしょう

    2008年2月15日 13:34
  • 読み返したら少し違う気がしてきたので推測を訂正します。

     

    <推測2>

    おそらく、RECT型はVCのランタイム(MSVCMRT.lib)にRECTの実体が存在しているため、最適化(リンク時のコード生成)を行うと2つのRECTをマージしようとするものの、ランタイム側は普通のRECTでもう一方はmake_publicにより属性がついているため「カスタム属性が適合しません」のエラーが発生する。

    2008年2月15日 16:05
  • C.Johnさん、アドバイス及び推察有難うございます。

     

    >リンクに失敗するものだけ自前の名前空間で再定義してやるといった方法はどうでしょう

    頂いたアドバイスで、検討したいと思います。
    2008年2月16日 10:18