2016-11-10 10 views
0

C#のラッパーを作成しようとしているサードパーティのDLLがありますが、動作するC++のサンプルコードがあります。 DLL内のメソッドを使用すると、エラーが発生します。C#のメソッドをC#から呼び出し、ヘッダファイルのみを使用します。

'scard-com.dll'というDLLで 'scan'というエントリポイントを見つけることができません。

は私の問題を指摘して助けてください:ここでは

はサンプルC++アプリ私のC#プロジェクトで

interface ISCard_CardReaderDevices : IUnknown { 
virtual UINT __stdcall scan(void) = 0; 
virtual UINT __stdcall getDeviceCount(void) = 0; 
virtual const CHAR * __stdcall getDeviceName(UINT id) = 0; 
virtual const CHAR * __stdcall getSerialName(UINT id) = 0; 
virtual ISCard_CardReader * __stdcall connectById(UINT id) = 0; 
virtual ISCard_CardReader * __stdcall connectByName(const CHAR *name) = 0; 
virtual ISCard_CardReader * __stdcall connectBySerial(const CHAR *serial) = 0; 
virtual BOOL __stdcall disconnect(ISCard_CardReader *reader) = 0; 
virtual ISCard_SecMsg * __stdcall attachSecMsg(ISCard_CardReader *reader) = 0; 
virtual void __stdcall detachSecMsg(ISCard_SecMsg *secMsg) = 0; 
virtual ISCard_Script * __stdcall attachScript(ISCard_CardReader *reader) = 0; 
virtual void __stdcall detachScript(ISCard_Script *script) = 0; 
virtual ISCard_IsoCard * __stdcall attachIsoCardByReader(ISCard_CardReader *reader) = 0; 
virtual ISCard_IsoCard * __stdcall attachIsoCardBySecMSG(ISCard_SecMsg *secMsg) = 0; 
virtual void __stdcall detachIsoCard(ISCard_IsoCard *isocard) = 0; 
virtual ISCard_MTCOS * __stdcall attachMTCOSByReader(ISCard_CardReader *reader) = 0; 
virtual ISCard_MTCOS * __stdcall attachMTCOSBySecMSG(ISCard_SecMsg *secMsg) = 0; 
virtual void __stdcall detachMTCOS(ISCard_MTCOS *os) = 0; 
virtual ISCard_IcaoConverter * __stdcall attachIcaoConverter(void) = 0; 
virtual void __stdcall detachIcaoConverter(ISCard_IcaoConverter *icaoconv) = 0; 
virtual ISCard_ImageConverter * __stdcall attachImageConverter(void) = 0; 
virtual void __stdcall detachImageConverter(ISCard_ImageConverter *imgconv) = 0; 
#ifdef MULTIAPP_EXT 
virtual ISCard_IDLConverter * __stdcall attachIDLConverter(void) = 0; 
virtual void __stdcall detachIDLConverter(ISCard_IDLConverter *idlconv) = 0; 
virtual ISCard_sscdConverter * __stdcall attachSSCDConverter(void) = 0; 
virtual void __stdcall detachSSCDConverter(ISCard_sscdConverter *sscdconv) = 0; 
virtual ISCard_eHealthConverter * __stdcall attacheHealthConverter(void) = 0; 
virtual void __stdcall detacheHealthConverter(ISCard_eHealthConverter *eHealthconv) = 0; 
#endif // MULTIAPP_EXT 
}; 

で使用される.hファイルの一部であり、私はこのクラスを追加しました:

public class SCardWrapper 
{ 
    [DllImport("scard-com.dll", CallingConvention = CallingConvention.Cdecl)] 
    public static extern uint scan(); 

// And call it like this: 

public int listReaders() 
    { 
     try 
     { 
      uint numreaders = scan(); 
      if (numreaders < 1) 
      { 
       return 0; 
      } 
      for (int i = 0; i < numreaders; i++) 
      { 
       IntPtr iDevice = getDeviceName(uint.Parse(i.ToString())); 
       String sDevice = Marshal.PtrToStringAuto(iDevice); 
       Debug.WriteLine(string.Format("{0} : " + sDevice, i)); 
      } 
      return int.Parse(numreaders.ToString()); 
     } 
     catch 
     { 
      return -1; 
     } 
    } 
} 

しかし、scan()メソッドに当たれば、私は上記のエラーを受け取ります。どんな助けもありがとう!

+1

投稿したヘッダーの部分には「スキャン」はありません。 – Chris

+0

DLL名の中の "COM"という単語は注目に値します。ヘッダーの宣言と同じように、COMインターフェイスです。いいえ、これらの関数はエクスポートされません。タイプライブラリへの参照を追加するだけです。通常はDLL自体に埋め込まれていますので、Project> Add Reference> Browseボタンを押してscard-com.dllを選択してください。 –

+0

申し訳ありませんが、間違ったインターフェースの説明を追加しました。編集した投稿が正しいものを表示しています。 – Thys

答えて

0

ようなscan宣言:

public class SCardWrapper 
{ 
    [DllImport("scard-com.dll", CallingConvention = CallingConvention.Cdecl)] 
    public static extern uint scan(); 
} 

はDLL scard-com.dllから名前scanで機能するために結合されます。 scard-com.dll DLLインターフェイスでこの機能をチェックしてください。これを行うには、Dependency Walkerを使用できます。

scanあなたのDLLにはmangledという名前を付けることができます。この場合、アンマネージコードにextern "C"と定義するか、PInvoke宣言にEntryPoint = "mangled_scan_name"を追加します。

ところで、scanは上記interface ISCard_CardReaderの一部ではありません。しかし、それがクラスのメソッドである場合は、CallingConvention = CallingConvention.Cdeclが間違っています。

1

P/Invokeはであり、実際にはをサポートしています。 Cスタイルの関数ではなく、インターフェイス上のメソッドを呼び出そうとしています。

あなたが望む結果を得ることができるいくつかのハッキングがありますが、通常はC#プロジェクトから使用できるC++/CLI interopライブラリを作成するのが最善の方法です。

また、一般に、ヘッダーファイルではネイティブライブラリを適切に呼び出すには不十分です。あなたはドキュメントが必要です - 文字列バッファの大きさはどれくらいですか?誰がメモリの割り当て/解放を担当しますか?バッファのサイズが十分でないとどうなりますか?エラー状態?もしあなたがドキュメントを持っていなければ、できることはほとんどありませんが、リバースエンジニアリングを楽​​しんでください:)

関連する問題