dllの使用方法

[戻る]
ある 2008/02/18(月) 18:06:30
皆様初めまして。

うまい題をつけられずすいません。
VC++にて、
.dllと.idlをもらっていて、その中の処理を呼び出したいのだが、うまくいかないという
内容です。
ネットやMSDNで色々調べたんですが、私の理解力では解決できませんでした。
お力お貸しください。

----------
試み1
  .idlをコンパイルしてできたヘッダファイルを見ていると、(下に抜粋しました)
  以下のような処理で呼び出すのだと思ったのですが、GetProcAddress()がうまく行きま
せんでした。
  -Source-------------
    IKeyVerification *xKeyVerif;

    HMODULE hDll = LoadLibrary(TEXT("KeyVerification.dll"));
    xKeyVerif = GetProcAddress( hDll,"IKeyVerification")
    xKeyVerif->Verify(addr, usr, &result);
  -Source-------------

  そこでdllをdumpbinしてみると、以下の関数しか無いようです。
    DllCanUnloadNow、DllGetClassObject、DllRegisterServer、DllUnRegisterServer
  これは、GetProcAddress()で指定できる関数がこれだけという意味ですよね?

----------
試み2
  DllGetClassObject()でアドレスを取り出すのかと思って、以下のような試みもしてみ
ましたが、
  コンパイルはexternが有るので通りますが
  リンクでCLSID_KeyVerificationとIID_IKeyVerificationが見つからずにうまく行きま
せん。
    FARPROC func = GetProcAddress(hDllLib, "DllGetClassObject");
    ((DllGetClassObject)func)(CLSID_KeyVerification, IID_IKeyVerification, 
(void**)&xKeyVerif);



環境はWinXP VC++2005です。



-idlからできたヘッダファイル----------------------
  typedef interface IKeyVerification IKeyVerification;
  typedef class KeyVerification KeyVerification;

  #include "oaidl.h"
  #include "ocidl.h"

  extern "C"{

    void * __RPC_USER MIDL_user_allocate(size_t);
    void __RPC_USER MIDL_user_free( void * ); 

    EXTERN_C const IID IID_IKeyVerification;

        MIDL_INTERFACE("D3B3117D-7834-4A67-B25B-6D7178FF2CA7")
        IKeyVerification : public IDispatch
        {
        public:
            virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Verify( 
                /* [in] */ BSTR ADDR,
                /* [in] */ BSTR USR,
                /* [retval][out] */ VARIANT_BOOL *Result) = 0;
            
        };

    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE 
IKeyVerification_Verify_Proxy( 
        IKeyVerification * This,
        /* [in] */ BSTR ADDR,
        /* [in] */ BSTR USR,
        /* [retval][out] */ VARIANT_BOOL *Result);


    void __RPC_STUB IKeyVerification_Verify_Stub(
        IRpcStubBuffer *This,
        IRpcChannelBuffer *_pRpcChannelBuffer,
        PRPC_MESSAGE _pRpcMessage,
        DWORD *_pdwStubPhase);


    EXTERN_C const IID LIBID_KEYVERIFICATIONLib;
    EXTERN_C const CLSID CLSID_KeyVerification;

    class DECLSPEC_UUID("342B4981-D0AB-48FF-B8BA-E012D780AE0B")
    KeyVerification;

    /* Additional Prototypes for ALL interfaces */

    unsigned long             __RPC_USER  BSTR_UserSize(     unsigned long *, 
unsigned long, BSTR * ); 
    unsigned char * __RPC_USER  BSTR_UserMarshal(  unsigned long *, unsigned 
char *, BSTR * ); 
    unsigned char * __RPC_USER  BSTR_UserUnmarshal(unsigned long *, unsigned 
char *, BSTR * ); 
    void                      __RPC_USER  BSTR_UserFree(     unsigned long *, 
BSTR * ); 
  }
-idlからできたヘッダファイル----------------------

wclrp ( 'o') 2008/02/18(月) 21:53:20
説明ないのかよ!
説明なしヘッダファイルなしで使えって不親切だな。

COMっぽいな。
dllをインストールしたい場所において登録してないのか。
regsvr32で登録。

IID_IKeyVerificationはD3B3117D-7834-4A67-B25B-6D7178FF2CA7じゃないのかな。

#import 使っても駄目?
うまくいけば楽になると思う。

俺はあまりCOM使わないから詳しくは知らない。

通りすがり 2008/02/19(火) 09:37:49
知らない事にまで、口出す必要は…

シャノン 2008/02/19(火) 09:43:24
CoInitialize();

IKeyVerification * pkv = NULL;
CoCreateInstance( CLSID_KeyVerification, NULL, CLSCTX_INPROC_SERVER, 
IID_IKeyVerification, reinterpret_cast< void ** >( &pkv );

pkv->Verify( ... );

pkv->Release();
CoUninitialize();

こんな要領で使います。
エラー処理は省いているので、適宜補ってください。

シャノン 2008/02/19(火) 09:43:50
間違えた。

誤:CoInitialize();
正:CoInitialize( NULL );

ある 2008/02/20(水) 09:37:09
シャノンさんありがとうございました。
お教え頂いた手順でやってみましたがうまくいきません。

importを追加してコンパイル・リンクはOKなのですが、
実行するとpkv->Verifi()のラインで不正終了になってしまいます。
試しにpkv->Verifi()をコメントアウトしてpkv->Release()だけにしても同じく死亡しま
す。

CoCreateInstance()の返値pkvはNULLでは無いのですが、
ブレイクして値を見ると、
pkv 0x0012f7e0 →IDispatch{...} →IUnknown{...} →__vfptr 0x00000000 →[0]
CXX0030:エラーです:式を評価できません (以下0〜3まで同じ)
となっていて、うまく取り出せていないみたいです。

もうしばらくお付き合い頂けたら助かります。

----------
//#include "KeyVerification_h.h"
#import "KeyVerification.dll" no_namespace named_guids raw_interfaces_only

void func()
{
  VARIANT_BOOL xResult;
  CoInitialize(NULL);

  IKeyVerification *pkv = NULL;
  CoCreateInstance(CLSID_KeyVerification, NULL, CLSCTX_INPROC_SERVER, 
    IID_IKeyVerification, reinterpret_cast< void ** >(&pkv));
  if(pkv = NULL) {
    AfxMessageBox(TEXT("とりだせない"));
    return;
  }
  pkv->Verify(TEXT("00aA80DB34B3"),TEXT("EFBE62CBC1F312AE"),&xResult);

  pkv->Release();
  CoUninitialize();
}
----------

シャノン 2008/02/20(水) 09:51:07
そのコードは本当にコピペですか? 書き写しミスがありませんか?
であれば、

> CoCreateInstance()の返値pkvはNULLでは無いのですが、

CoCreateInstance 直後が NULL でなくとも、

> if(pkv = NULL) {

ここで NULL にしてしまっています。

あと、CoCreateInstance が成功したかどうかは、戻り値で判断するようにしましょう。

tetrapod 2008/02/20(水) 09:52:41
>   if(pkv = NULL) {
=ではなくて==だと思うが typo かな?それともほんとうにこうなっている?

ある 2008/02/20(水) 13:16:05
すいません、ifの=はカキコミでのtypoです。
 今度はソースそのままコピペします。

以下のように返値で判断するように修正したところ、
CoCreateInstance()がNULLを返してきていたみたいです。

何でNULLになるのか、これから自分でも調べてみます。
 とりあえずimportのdllのパスをCのルートにコピーしてトライしましたがダメでしたx。


----------
#import "c:\KeyVerification.dll" no_namespace named_guids raw_interfaces_only

void func()
{
  VARIANT_BOOL xResult;
  HRESULT xxx;
  CoInitialize( NULL );
  IKeyVerification *pkv = NULL;

  xxx = CoCreateInstance(CLSID_KeyVerification, NULL, CLSCTX_INPROC_SERVER, 
          IID_IKeyVerification, reinterpret_cast< void ** >( &pkv));
  if( !SUCCEEDED(xxx)) {
    AfxMessageBox(TEXT("とりだせない"));
    return;
  }
  pkv->Verify(TEXT("00aA80DB34B3"),TEXT("EFBE62CBC1F312AE"),&xResult);
  if (xResult) {
    AfxMessageBox(TEXT("あ"));
  }
  else {
    AfxMessageBox(TEXT("い"));
  }

  pkv->Release();
  CoUninitialize();
----------

シャノン 2008/02/20(水) 13:49:44
> 以下のように返値で判断するように修正したところ、
> CoCreateInstance()がNULLを返してきていたみたいです。

そのときの戻り値の値は何ですか?

ちなみに、SUCCEEDED の反対で FAILED というマクロもあります。

wclrp ( 'o') さんの書き込みにありますが、
> regsvr32で登録。
は行ってますか?

PATIO 2008/02/20(水) 14:47:31
> wclrp ( 'o') さんの書き込みにありますが、
>> regsvr32で登録。
> は行ってますか?

COMを使うならこれ大事です。
COM周りの勉強も少しはした方が良いと思いますよ。
作るまで行かなくても使える位にはなっておいた方が良いです。

ある 2008/02/22(金) 09:23:36
[[解決]]
レス遅くなりましてすいません。

結局regsvr32の登録がされていませんでした。
 (色々試している間に、外してしまっていたらしい)

皆様色々アドバイスありがとうございました。
今回は「とりあえず動く物を」という事で、下調べや勉強不足のまま
始めてしまっていました。

これから、これまでのトラブル部分を再勉強します(x

古いスレッドには追加発言できません。