6

関数 CreateRisk をエクスポートする C++ で記述された DLL があります。この関数は、次のようにインターフェイス ポインターを返します。

extern "C"
{
    __declspec(dllexport) IRisk* __stdcall CreateRisk()
    {
        return new  Risk();


    }
}

IRisk は IUnknown から派生し、独自のメソッド Calculate を持っています。

class IRisk: public IUnknown                               
{
public:
    virtual int __stdcall Calculate(int i,double s) = 0;  
};

クラス Risk は、IRisk インターフェイスを実装します (実装はここでは省略されています)。

私が望むのは、C# で関数 CreateRisk を呼び出し、IRisk への参照を取得することです。

C# でラッパー インターフェイスを定義しました

    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]        
    public interface IRisk
    {
        [PreserveSig]                                            
        int Calculate(int i,double s);
    }

そして、C#にdllエントリを追加しました

    [DllImport("Risk.dll")]
    extern static IntPtr CreateRisk();

C# で CreateRisk を呼び出して、IntPtr の値の型を取得できます。C# で Calculate メソッドを呼び出せるように、IntPtr を c# IRisk インターフェイスにマーシャリングする方法はありますか?

Marshal.GetIUnknownForObjectInContext,Marshal.GetObjectForIUnknown を試しましたが、役に立ちませんでした。

COM コンポーネントを作成すればそれができることはわかっています。ただし、COM コンポーネントをシステムに登録する必要があります。これらの問題を回避し、C# で C++ dll によってエクスポートされたインターフェイスを直接使用できるようにしたいと考えています。

PS:

以下は、私の Risk クラスの実装です。

class IRisk : public IUnknown                               
{
public:
    virtual int __stdcall Calculate(int i,double y ) = 0;  
};

class Risk:public IRisk
{
    int count;
public:
    Risk();
    virtual int __stdcall Calculate( int i ,double y);
    virtual ULONG __stdcall AddRef();
    ULONG __stdcall Release();
    HRESULT __stdcall QueryInterface(const IID& riid,void **ppvObject);
};

Risk::Risk(){
    count=0;
}

ULONG __stdcall Risk::AddRef()
{
    return ++count;
}
ULONG __stdcall Risk::Release()
{
    return --count;
}
HRESULT __stdcall Risk::QueryInterface(const IID& riid,void **ppvObject) {
    *ppvObject=this;
    AddRef();
    return S_OK;
}
int __stdcall Risk::Calculate(int i ,double y) {
    return (int)(i+y);
}
4

2 に答える 2

2

以下が機能します。

[DllImport("Risk.dll")]
extern static IRiskAssessment CreateRisk();

インターフェイスにGUIDを追加する必要があります。

[Guid("your GUID goes here")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]        
public interface IRiskAssessment
{
    [PreserveSig]                                            
    int Calculate(int i,double s);
}

明らかに、C ++コードで使用されたものと同じGUIDをC#コードで使用する必要があります。

アップデート

C ++ COMオブジェクトの実装を見ると、明らかな障害はにありQueryInterfaceます。S_OKすべてのGUIDに戻る必要はありません。S_OK実装するインターフェースに対してのみ戻ります。他の人のために戻りE_NOINTERFACEます。

于 2012-12-06T11:09:25.843 に答える
1

私があなたなら、SWIGを使用して C++ コード用の C# インターフェイスを生成し、多くの問題を解決します。また、アセンブリをmixed-modeでコンパイルするか、マネージ アセンブリとしてコンパイルする必要があると思います。

于 2012-12-06T10:56:48.627 に答える