web-dev-qa-db-ja.com

C#からC ++ / CLIのクラスにアクセスするにはどうすればよいですか?

Cで記述された別のプログラムのデータ出力を解析して表示するGUIツールをC#で記述しています。データを解析するには、いくつかのCヘッダーファイルで指定されているデータ構造を知る必要があります。したがって、これらのCヘッダーファイルをC#プロジェクトに組み込む必要があります。私の質問は次のとおりです。

1)調査の結果、ソリューションで新しいC++/CLIプロジェクトを作成し、Cヘッダーファイルをこの新しいプロジェクトにインポートし、データのシンラッパーとして機能するC++/CLIクラスを作成するのが最善の方法であると結論付けました。 Cヘッダーファイルで定義された構造は、C#コードからC++/CLIラッパークラスを参照します。これが最善のアプローチですか、それともより良い方法がありますか?

2)参照の問題が発生しました。これが問題を説明するための私の簡略化されたコードです:

C++/CLIプロジェクトの元のCヘッダー

#define ABC  0x12345

C++/CLIプロジェクトのラッパークラス

#include "my_c_header.h"

namespace C_Wrappers {
    public ref class MyWrapper {
        public:
            property unsigned int C_ABC {
                unsigned int get() { return ABC; }
            }
    }
 }

C#プロジェクトのユーザークラス

using C_Wrappers;
using System;

namespace DataViewer {
    public partial class MainForm : Form {
        private  MyWrapper myWrapper = new MyWrapper();
        public MainForm() {
            Console.WriteLine(myWrapper.C_ABC.ToString());
        }
    }
 }

C#プロジェクトで、C++/CLIプロジェクトへの参照を追加しました(右クリック> [参照の追加]を使用)。ビルド中に、C#プロジェクトでエラーが発生しました:「タイプまたは名前空間 'C_Wrappers'が見つかりませんでした(usingディレクティブまたはアセンブリ参照がありませんか?)」

やるべきことはすべてやったと思った。このエラーを修正するにはどうすればよいですか?

12
Thomas Nguyen

私自身のソリューションでは、4つのプロジェクトがありました。

  1. C++プロジェクトとテストコード
  2. C++ DLL projectこれは最初のプロジェクトからDLLダイナミックリンクを使用したソース
  3. wrapper projectは、C++/CLIを使用する唯一のアダプターであり、生のC++をラップします。
  4. C#WPFプロジェクトは私のグラフィカルインターフェイスでした。

これが上記のリンクの私の翻訳です。

C++ DLLプロジェクト

C++コードをDLL libに作成します。

  1. Visual Studio内で、ファイル>新規>プロジェクトに移動し、Win32プロジェクトを選択します。 )[Visual C++]タブから。
  2. プロジェクトとソリューションの両方の名前を選択すると、ソリューションにはすべてのプロジェクトが含まれます。
  3. Win32アプリケーションのアシスタント内で、nextをクリックし、[〜#〜] dll [〜#〜]を確認します。 ボックス、次に空のプロジェクトをクリックし、完了

Project creationProject assistant

追加するコード

これは、dllのC++ヘッダーです(多くのものを除いたもの)。

Token.h

#pragma once
#define DLLEXP   __declspec( dllexport )

DLLEXP void pop_back(std::string& str);

DLLEXP std::string testReturnString();

DLLEXP int getRandomNumber();

CPP内で変更するものは何もありません。

プロジェクトをビルドします。C#プロジェクトのデバッグディレクトリに含めるDLLとLIBファイルが必要です。

C++/CLIラッパー

このプロジェクトは、前のプロジェクトのネイティブコードとGUIのマネージコード間のインターフェイスとして機能します。

  1. 新しいプロジェクト(Visual C++ではクラスライブラリ)(この例では「ラッパー」と呼ばれます)をソリューションに追加します
  2. 追加のインクルードディレクトリを使用して、ネイティブプロジェクトへのパスを追加します
  3. 新しいプロジェクトの参照としてネイティブプロジェクトを追加します(r右クリック>参照...>新しいリンクの追加
  4. プロパティ>リンカー>入力で、ネイティブdllの名前をDLLの遅延ロード(この例ではComputations.dll)フィールドに入力します

C++/CLIコード

私のラッパーは、このようなクラスにすぎません(私自身のコードを除く)。

Wrapper.h

#include "Token.h" // include your C++ header

#include <string>
#include <iostream>

namespace Wrapper {

    // noticed the ref?
    public ref class TokenAnalyzer
    {

    public:
        TokenAnalyzer(){
        };

        void Init();
            // use the C++/CLI type, like String^ (handles)
        System::String^ ProcessLine(int lineNbr, System::String^ line);
    };
}

#include "stdafx.h"を含める必要があることを除いて、CPP内で特別なことは何もありません。

また、C#デバッグディレクトリ内に含めるDLLに組み込む必要があります。

SOのどこかで見つけた便利な関数ですが、どこに必要か覚えていません。C++/CLI文字列ハンドルをC++標準文字列に変換します。

std::string MarshalString (String ^ s) {
        using namespace Runtime::InteropServices;
        const char* chars = 
            (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
        std::string os = chars;
        Marshal::FreeHGlobal(IntPtr((void*)chars));
        return os;
    }

C#プロジェクト

ソリューションに新しいプロジェクトを追加します(C#Windowsフォームまたは[〜#〜] wpf [〜#〜 ]またはあなたが望むものなら何でも!)そしてそれをスタートアッププロジェクトとして設定します(右クリック>スタートアッププロジェクトとして設定します )。

  1. 新しいプロジェクトの参照としてC++/CLIプロジェクトを追加します
  2. ソースコード形式でディレクティブusing Wrapper;を追加します

次のように使用します。

/// Store the C++/CLI Wrapper object.</summary>
private Wrapper.TokenAnalyzer mTokenAnalyzer = new TokenAnalyzer();

更新2016/05/06

Ashwin 時間をかけて サンプルプロジェクトブログ投稿チュートリアル を作成しました。これはさらに役立つ可能性があります。

23
Emile Bergeron

私にとって、 this 同様の質問に対する答えは、C#での同じエラーを解決しました。

(つまり、C++\CLIプロジェクトにラッパーヘッダーファイルがありましたが、.cppファイルも含めるのを忘れていました(#include "stdafx.h"と#include "Wrapper.hの2行しかないにもかかわらず) "))

5
Bartel