C#でC++を呼び出すDLLの簡単な分析(二)--管理dllを生成する

4609 ワード

操作を書く前に、やはり管理と非管理C++の違いを要約して言ったほうがいいですが、実は私も管理C++の特徴を深く理解したことがありません.その最大の特徴は、システムが関連するコード資源をデバッグして回収することができ、C#の特性と同じで、プログラムスタイルがC++に似ているだけです.そのため、これはC#と管理C++が完璧に結合できることを決定した.管理C++で生成されたdllとC#で生成されたdllには違いはないが、管理C++という怪物が生まれたのは、マイクロソフトがC#を極力崇拝しているためであり、異なる言語間の相互作用を両立させなければならないからだ.
では、次はまじめに過程を書きます.まず目的を示します:私の手にはC++が書いたクラス(ClassA)があり、C#の下でこのクラスを呼び出したいのですが、C#はdllimportのような簡単な方法で非管理C++dllの中のクラスを取得することはありません.私の解決策は、管理C++のdllを生成することです.管理コードと非管理コードは1つのファイルで混成できないので、ClassAを管理C++の手段でカプセル化し、C#呼び出しのためにdllを生成しなければなりません.
私のところは回りくどいかもしれませんが、次のチュートリアルを見てください.分かります.
一、CLRクラスライブラリ工事を創立する
実は、私はこれらのステップを無視したいと思っています.1枚の図で説明できる問題は多くありません.どうせCLRクラスライブラリプロジェクトを構築して、その名前は暫定的にManageClassと呼ばれています.これは工事名です.混同しないでください.以下の図では、注意事項は何もありません.(文句を言って、どうして51 CTOは編集の中で画像を縮小することができなくて、PSは面倒です)
二、管理されていないC++の例
私の手には非管理C++で書かれたクラスNativeClassがあります.それ自体は別の非管理C++プロジェクトに属しています.今、私は直接このクラスのファイルを本プロジェクトのディレクトリにコピーします.簡単に言えば、このクラスはヘッダファイルに接続されています.他の比較的大きなクラスであれば、NativeClassを必要とします.hの中の#includeからの他のファイルも一緒にこの新しいプロジェクトディレクトリの下にコピーして、それからこれらのファイルをVSのリソースマネージャの下に追加して、下図のように:
上の図ではNativeClassを除きます.hファイルは私が追加したもので、他は工事が持参したもので、その中でManageClassです.h及びManageClass.cppはdllを生成するために使用されるもので、しばらくは気にしないで、NativeClassを見てみましょう.hの内容:
#pragma once
class _declspec(dllexport) NativeClass
{
private:
                                                                                                                                                                                                                                                                                                                                                                                                                          
    int nCount;
public:
    NativeClass(void)
    {
        this->nCount = 0;
    }
    ~NativeClass(void)
    {
    }
    int GetCount(void)
    {
        return this->nCount;
    }
    void Increase(void)
    {
        this->nCount++;
    }
    void Clear(void)
    {
        this->nCount = 0;
    }
};

類の内容は私が直視することに忍びないほど簡単で、類の頭のようですdeclspec(dllexport)フィールドは実は要らないでください.ただ削除するのがおっくうです.
三、管理C++を装わない内容
このステップはとても肝心で、なぜこのようなステップがあるのか、管理C++と非管理C++が混同することができないため、そこで私は管理コードを上のNativeClass類をパッケージして、もともと規範的に言えば私は関数の声明と実現を別々に書くべきで、しかし私はまた怠けたことを認めて、ManageClassだけです.hの中で修正して、ManageClassを使っていませんが.cppですが、どうしてもこのファイルを削除しないでください.そうしないとdllを生成できません.私のパッケージコードは次のとおりです.
// ManageClass.h
#pragma once
#include "NativeClass.h"
using namespace System;
namespace ManageClass {
    public ref class NativeClassEx
    {
        // TODO:           。
    private:
        NativeClass * m_pnClass;
    public:
        NativeClassEx(void)
        {
            this->m_pnClass = new NativeClass();
        }
        ~NativeClassEx(void)
        {
            delete this->m_pnClass;
        }
        int GetCount(void)
        {
            return this->m_pnClass->GetCount();
        }
        void Increase(void)
        {
            this->m_pnClass->Increase();
        }
        void Clear(void)
        {
            this->m_pnClass->Clear();
        }
    protected:
        !NativeClassEx(void)
        {
            delete this->m_pnClass;
        }
    };
}

上のコードを理解していないと言わないでください.豆腐を探して頭をぶつけることをお勧めします.
四、管理C++のdllを生成する
実はここまで来たら終わりです.直接コンパイルすると、工事外のデバッグフォルダにManageClassが生成されます.dllです.必ずはっきり見てください.パッケージされた後、私の新しいクラス名はNativeClassExです.使用時に注意してください.
五、プロジェクトテストdll
C++を管理するdllを呼び出すのはC#を呼び出すdllと何の違いもありません.新しいテストエンジニアリング(WinFormのフォームエンジニアリングを使用しています)を作成します.名前はDllTestで、ソリューションエクスプローラで生成したばかりのManageClassです.dllを参照に追加し、using ManageClassを使用します.その後、テストコードはいくつかの言葉で使用できます.
NativeClassEx testCalss = new NativeClassEx();
Debug.WriteLine("GetCount : " + testCalss.GetCount().ToString());
testCalss.Increase();
testCalss.Increase();
testCalss.Increase();
Debug.WriteLine("GetCount : " + testCalss.GetCount().ToString());
testCalss.Clear();
Debug.WriteLine("GetCount : " + testCalss.GetCount().ToString());

コンパイルして、出力ウィンドウを見て、クラスは完璧に実行できます.
六、注意事項
1、C#は管理C++と大きく互換性があるにもかかわらず、基本タイプ以外の位置合わせの問題に注意しなければならない.構造体、stringクラスなど、入口パラメータは基本タイプ以外は使わないほうがいい.この点は私の前の文章を参考にしてください.
2、私は管理C++で私をカプセル化してOpenCVクラスを书くことを试みて、クラスの中で更にOpenCVのdll(つまりC#が管理dllを呼び出して、管理dllが非管理dllを呼び出します)を呼び出して、コンパイルは通じて、しかし実际に运行するのはだめで、中にどんな问题があるかはしばらく分かりません;
3、このような方法でクラスを呼び出す必要はありません.C#でdllを呼び出す関数が最も保障されています.
4、サンプルプロジェクトはここでダウンロードしてください.dllをコンパイルしてから、参照が追加されていることを確認してください.CPUタイプの選択に関するwarningがあるかもしれません.皆さん、自力で更生してください.
転載先:https://blog.51cto.com/joeyliu/1297961