2017-08-29 8 views
0

タイトルが示すように、C++からC#コードを呼び出す際に問題があります。コンテキストのビット:C#にAPI呼び出し(APIのC++バージョンには存在しません)があり、これをはるかに大きなC++プロジェクトに統合する必要があります。C++(COM)でのC#コードの使用Dllのインポートが正常に機能しない

私はthis SO post以上を読んでおり、COMメソッドで最も進展しました。

私のC#dllは*をコンパイルします。適切なC++プロジェクトディレクトリに結果のDLLとTLBファイルをコピーした後、私は管理者が同じC++プロジェクトディレクトリに促して実行CMD開く:

regasm MyFirstDll.dll /codebase /tlb 

(*私はクラスライブラリ、アセンブリ名としてそれをコンパイルします。 MyFirstDll、Default namespace:MyMethods、Assembly Information ... - >アセンブリのCom-Visibleをチェックし、COM- interopのためのBuild-> Registerもチェックされています)。

オブジェクトブラウザを使用して、私は、適切なargsと署名を持つメソッドと同様に定義しました。 Screenshot of it showing up in Object Browser

私が経験している問題は、メソッド呼び出しであり、クラスではありません。メソッドがオブジェクトブラウザに表示されていても、自分のコードではオブジェクトのメソッドとして認識されません。

クラス "ATL :: _ NoAddRefReleaseOnCComPtr" ここ
を "追加" 何のメンバーを持っていない私のコードです:

MyFirstDll C#プロジェクト:

using System; 
using System.Runtime.InteropServices; 
// 

namespace MyMethods 
{ 
    // Interface declaration. 
    [Guid("8a0f4457-b08f-4124-bc49-18fe11cb108e")] 
    [ComVisible(true)] 
    [InterfaceType(ComInterfaceType.InterfaceIsDual)] 
    public interface Easy_Math 
    { 
     [DispId(1)] 
     long Add(long i, long j); 
    }; 
} 
namespace MyMethods 
{ 
    [Guid("0cb5e240-0df8-4a13-87dc-50823a395ec1")] 
    [ComVisible(true)] 
    [ClassInterface(ClassInterfaceType.None)] 
    [ProgId("MyMethods.AddClass")] 
    public class AddClass: Easy_Math 
    { 
     public AddClass() { } 
     [ComVisible(true)] 

     public long Add(long i, long j) 
     { 
      return (i + j); 
     } 
    } 
} 

NateMath.h:

#include <atlcomcli.h> 
#import "MyFirstDll.tlb" 

class NateMath 
{ 
public: 
    NateMath(void); 
    ~NateMath(void); 
    long Add(long a, long b); 

private: 
    CComPtr<MyFirstDll::AddClass> adder; 
}; 

NateMath.cpp:

#include "stdafx.h" 
#include <atlcomcli.h> 
#import "MyFirstDll.tlb" 
#include "NateMath.h" 

NateMath::NateMath(void) 
{ 
    CoInitialize(NULL); 
    adder.CoCreateInstance(__uuidof(MyFirstDll::AddClass)); 
} 

NateMath::~NateMath(void) 
{ 
    CoUninitialize(); 
} 
long NateMath::Add(long a, long b) { 
    return adder->Add(a,b); 
} 

"add adder-> Add(a、b)"(NateMath.cpp)のAdd(a、b)が "ATL :: _ NoAddRefReleaseOnCComPtr"クラスで赤色で表示される問題は、 "Add"というメンバがありません

+1

'CComPtr 'の代わりに 'CComPtr 'を使ってみてください。 –

+0

@HansPassantそれは知っておきたいことです!残念なことにC#AddClass (int i、int j)のコードを追加すると、同じエラーが表示されます:( –

+0

@MichaelGunterクラスの代わりにCComPtrをインターフェイスに使用すると、クラスの実装を呼び出す方法をどのように知ることができますか?方法? –

答えて

0

これは、インターフェイスの代わりにCComPtrでクラス名を使用しようとしているためです。 COMでは、すべてのメソッドがインターフェイスで定義され、インターフェイスを実装するクラスでは定義されません。

で表されるGUIDによって識別されるYourClassのインスタンスを作成することが目的であるため、CoCreateInstance(__uuidof(YourClass))にすることができます。しかし、C++のYourClassは、uuidを読むことができるように存在するダミー構造体です。#importから生成されたC++のYourClassの定義は空で、常に空です。

これを修正するには、CComPtr<YourInterface>を使用してください。これは、そのインタフェースを介して参照されているオブジェクトと通信したいことをC++に伝えます。 CComPtrCComQIPtrへの型引数は、常にがCOMインターフェイスでなければならないことを覚えておく必要があります。 COMインターフェイスは、明示的に定義されたインターフェイスでも、.NETによって自動的に生成される「クラスインターフェイス」でもかまいません。クラス・インタフェースの

スピーキング:あなたはClassInterfaceType.AutoDual代わりのNoneを使用していた場合、あなたはCComPtr<_YourClass>を使用することもできました(先頭にアンダースコアに注意してください - YourClassがクラスになるのに対し_YourClassは、クラスのインタフェースである私はそれやってお勧めします。しかし、あなたが既に持っているやり方で。

+0

それは間違っています、彼はインターフェイスを明示的に宣言することによって正しく行いました。彼はそれを使うのを忘れてしまった。 #importが自動生成するスマートポインタ型を使用するための推奨事項を含めるべきでしょう。この場合、「Easy_MathPtr」という名前を付けるべきです。 –

+0

@HansPassantああ、ありがとう。私は、クラスインタフェースが 'YourClass'ではなく' _YourClass'であることを忘れていました。 'CComPtr'と' _com_ptr'を使用する限り、これは完全に消費する開発者の責任です。彼らが既存のATLプロジェクトでこれを消費している場合、生成された '_com_ptr'を' CComPtr'よりも優先する理由はありません。実際、そうすることは、対処する余分な例外タイプ( '_com_error')があることを意味します。 –

関連する問題