75

C++ で記述された dll があります。この dll を C# コードで使用する必要があります。検索した結果、P/Invoke を使用すると必要な関数にアクセスできることがわかりましたが、これらの関数はクラスで定義されており、非静的プライベート メンバー変数を使用しています。したがって、関数を適切に使用するには、このクラスのインスタンスを作成できる必要があります。インスタンスを作成できるように、このクラスにアクセスするにはどうすればよいですか? これを行う方法を見つけることができませんでした。

C++ dll は私のコードではないことに注意してください。

4

6 に答える 6

96

C#コードでC++クラスを直接使用する方法はありません。PInvokeを間接的に使用して、タイプにアクセスできます。

基本的なパターンは、クラスFooのすべてのメンバー関数に対して、メンバー関数を呼び出す関連する非メンバー関数を作成することです。

class Foo {
public:
  int Bar();
};
extern "C" Foo* Foo_Create() { return new Foo(); }
extern "C" int Foo_Bar(Foo* pFoo) { return pFoo->Bar(); }
extern "C" void Foo_Delete(Foo* pFoo) { delete pFoo; }

これで、これらのメソッドをC#コードにPInvokingすることができます。

[DllImport("Foo.dll")]
public static extern IntPtr Foo_Create();

[DllImport("Foo.dll")]
public static extern int Foo_Bar(IntPtr value);

[DllImport("Foo.dll")]
public static extern void Foo_Delete(IntPtr value);

欠点は、渡すのが面倒なIntPtrになることですが、より使いやすいモデルを作成するために、このポインターの周りにC#ラッパークラスを作成するのはやや簡単なことです。

このコードを所有していない場合でも、元のDLLをラップし、小さなPInvokeレイヤーを提供する別のDLLを作成できます。

于 2008-11-24T18:54:54.817 に答える
33

C++ クラスをマーシャリングし、PInvoke を使用する

C++ コード ,ClassName.h

class __declspec(dllexport) CClassName
{
 public:
    CClassName();
    ~CClassName();
    void function();

};

C++ コード、ClassName.cpp

CClassName::CClassName()
{
}

CClassName::~CClassName()
{
}

void CClassName::function()
{
    std::cout << "Bla bla bla" << std::endl;

}

C++ コード、呼び出し元関数の ClassNameCaller.h ファイル

#include "ClassName.h"      

#ifdef __cplusplus
extern "C" {
#endif

extern __declspec(dllexport) CClassName* CreateClassName();

extern __declspec(dllexport) void DisposeClassName(CClassName* a_pObject);

extern __declspec(dllexport) void function(CClassName* a_pObject);


#ifdef __cplusplus
}
#endif

C++ コード、呼び出し元関数の ClassNameCaller.cpp ファイル

#include "ClassNameCaller.h"


CClassName* CreateClassName()
{
    return new CClassName();
}

void DisposeClassName(CClassName* a_pObject)
{
    if(a_pObject!= NULL)
    {
        delete a_pObject;
        a_pObject= NULL;
    }
}

void function(CClassName* a_pObject)
{
    if(a_pObject!= NULL)
    {
        a_pObject->function();
    }
}

C# コード

[DllImport("ClassNameDll.dll")]
static public extern IntPtr CreateClassName();

[DllImport("ClassNameDll.dll")]
static public extern void DisposeClassName(IntPtr pClassNameObject);

[DllImport("ClassNameDll.dll")]
static public extern void CallFunction(IntPtr pClassNameObject);

//use the functions
IntPtr pClassName = CreateClassName();

CallFunction(pClassName);

DisposeClassName(pClassName);

pClassName = IntPtr.Zero; 
于 2016-04-12T12:59:49.077 に答える
5

これは、VBからC ++クラスメソッドを呼び出す方法のサンプルです。C#の場合は、ステップ4でサンプルプログラムを書き直すだけです

于 2008-11-24T19:05:53.813 に答える
3

これを行う方法は、アンマネージC++DLLの周りにシンマネージC++ラッパーを作成することです。マネージラッパーには、.NETアプリケーションに必要なインターフェイスを公開するアンマネージコードをラップする「プロキシ」クラスが含まれています。これは少し二重の作業ですが、通常の環境では非常にシームレスな操作が可能です。一部の状況(ASP.NETなど)では、依存関係によって状況が複雑になりますが、おそらくそれに遭遇することはありません。

于 2008-11-25T09:30:14.363 に答える
3

これを処理し、必要なインターフェイスを公開する中間DLL(おそらくC ++で)を作成する必要がある場合があります。DLLは、サードパーティのDLLのロード、このC ++オブジェクトのインスタンスの作成、および設計したAPIを介した必要に応じたメンバー関数の公開を担当します。次に、P / Invokeを使用してAPIを取得し、オブジェクトをクリーンに操作します。

注:DLLのAPIの場合、モジュール境界の問題を防ぐために、データ型をプリミティブ(long、int、char *など)に制限してみてください。

于 2008-11-24T18:56:28.933 に答える
2

JaredParに同意します。マネージコードでアンマネージクラスのインスタンスを作成することはできません。

もう1つのことは、マネージC ++でDLLを再コンパイルしたり、それからCOMコンポーネントを作成したりできる場合は、はるかに簡単です/

于 2008-11-24T18:58:05.717 に答える