5

これを尋ねる前に、このやや似た質問を参照しましたが、問題を解決できません

多くのソリューションを備えた古いアプリケーションを見ています。問題は、ソリューションの 1 つ (たとえば S) で発生しています。状況は次のとおりです。

  • S 内のプロジェクト (P1 など) にはすべての C/C++ ファイルがあり、C# 関数を呼び出す必要があります
  • P1 には .c ファイルも含まれているため、それで/clrオプションを使用することはできません
  • P1 の .c ファイルを .cpp ファイルとしてコンパイルすると、多くのエラーが生成されます。そのレガシー .c ファイルのソースを変更するつもりはありません。
  • そこで、有効にして別のプロジェクト (P2 など) を/clr作成し、関数宣言用のヘッダー ファイルと関数定義用の .cpp ファイルを作成しました。C# 呼び出しはその下で行われます。P2 は正常にコンパイルされます
  • P1 は .dll であり、P2 はスタティック ライブラリとして作成されることに注意してください。
  • P2 は、P1 の「フレームワークと参照」の下に記載されています。

そして警告:

警告 LNK4098: defaultlib 'MSVCRT' は他のライブラリの使用と競合します。/NODEFAULTLIB:ライブラリを使用

これらすべてで、P1 で 3 つのリンカー エラーが発生します。

エラー LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) libcmtd.lib(typinfo.obj) で既に定義されています

エラー LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) libcmtd.lib(typinfo.obj) で既に定義されています

エラー LNK1169: 1 つ以上の多重定義シンボルが見つかりました

このエラーは、この Web サイトを含む多くのオンライン フォーラムで入手できます。しかし、どういうわけか、これらのオプションを試した後、修正できません(.NETフレームワークは初めてです)。
重要な点は、P2 から C# コードを削除しても、同じエラーが表示されることです。

それを修正する正しい方法は何ですか?

更新

P2 には、関数宣言を含む 1 つのヘッダー ファイルと、C# メソッドへの 1 行の呼び出しである関数定義を含む 1 つのソース ファイルが含まれています。例えば

void Class::foo () {  // A static function inside Class
  std::string x = marshal_as<std::string>(C#_function);
  // ...
}

P2 が新たに追加されてコンパイルされます/clr(P2 を削除すると、ソリューションが正常にコンパイルされます)。
オプション付きで P1 と P2 の両方をコンパイルしてい/MD[d]ます。そして、上記のエラーは P1 によってスローされます。

P2 をスタティック ライブラリ (.lib) からダイナミック リンク ライブラリ (.dll) にすると、上記のエラーはなくなります。そして、foo未定義の参照のために、新しいリンカーエラーが発生します。

エラー LNK2019: 未解決の外部シンボル "public: void __cdecl Class::foo()" が関数 {P1 の関数} で参照されています

4

3 に答える 3

5

StackOverflow の内外で多くの試行錯誤とインターネット検索を行い、最終的にこの問題を解決することができました。少なくともリンカー エラーはなくなりました。他に何が表示されるかはわかりませんが、これは良い兆候です。
以下に、可能な限り多くのことを文書化しようとします。

言い換えれば、質問:

同じプロジェクトの下にある 2 つの dll をリンクする方法は/clrありclrますか?

実際の問題の概要:

  • ソリューションの 1 つで、C# モジュールを呼び出さなければならない要件が発生するまで、すべてが正常に機能しています。
  • C# コード (またはマネージ コード) を呼び出すには、プロジェクトがプロジェクトである必要があり /clrます。
  • /clrすべての .cpp コードを含み、.c コードを含まないプロジェクトは、
  • 私の場合、ソリューションのメイン プロジェクトには .c ファイルが含まれていました。.cpp オプションでコンパイルしようとすると、多くのエラーが発生し、従来の理由でそのファイルを変更できません
  • したがって、最適なオプションは、インターフェイス メソッドとその実装 (C# または C++/CLI を呼び出す) をそれぞれ含む .h ファイルと .cpp ファイルを使用して新しいプロジェクトを作成することです。

ここまでは問題ありませんが、新しいプロジェクト (P2) の関数定義が元のプロジェクト (P1) とリンクされていない場合に問題が発生します。さまざまなリンカー エラーが発生します。

解決:

手順は、初心者ユーザー (私のような) 向けの VC++2010 を使用しています。

P1 の構成:

  • ソリューション S を右クリックしAdd -> New Project -> Other languages -> VC++ -> CLR empty project、名前を付けます (たとえば、P2)。プロジェクトの適切なセクションにヘッダー ファイルと .cpp ファイルを追加します。
  • これにより、自動的にProperties -> Configuration Properties -> C/C++ -> Code Generation -> Runtime Library to Multi threaded DLL: /MD[d];が設定されます。どれが不可欠です
  • 元のプロジェクト P1 の場合、適切なインクルード パスを下に追加しますProperties -> Configuration Properties -> C/C++ -> General -> Additional Include Directories。P1 のソース ファイルのどこにでも P2 の新しいヘッダー ファイルをインクルードできるように
  • 再びプロジェクト P1 に移動するProperties -> Common Properties -> Framework and Reference -> Add New Referenceと、そこに P2 が表示されるはずです。追加するだけ

P2 の構成:

  • それがなくてもビルドが成功するため、最初のステップはオプションですが、私は文書化しています。Properties -> Common Properties -> Framework and References -> Add New Reference -> <Select the C# or whatever external DLL you would want to call from P2>
  • 新しいプロジェクト P2 の場合、次のように構成を設定しますDLLProperties -> Configuration Properties -> General -> Project Defaults -> Configuration Type -> Dynamic Library (DLL)
  • プロジェクト P2 にとって意味がある場合は、同じページで を設定しOutput DirectoryIntermediate DirectoryP1 のそれと同期 (まったく同じではありません) にする必要があります。
  • 再びプロジェクト P2 に移動しProperties -> Configuration Properties -> Linker -> General -> Ignore Import Library -> Noます。P1もそうだったのでこれにしました
  • ここで最も重要な部分: P2 の新しいヘッダー ファイル内に追加したクラスが何であれ、言及する必要があります __declspec(dllexport)(または__declspec(dllimport)、確かではありませんが、両方とも機能します)。この重要な情報は、この質問この質問から得ました

そして、上記の手順でビルドは成功しました!
おそらく見逃されているものがある可能性があり、そのために実行時の問題に直面しています。ただし、少なくとも、同じソリューションの下で、 の有無にかかわらず 2 つの DLL プロジェクトをリンクすることができました/clr

于 2013-08-19T17:05:39.613 に答える