none
DLLとVBの返り値でboolが反対になる RRS feed

  • 質問

  • 開発環境
    WinXP Pro
    Microsoft Visual Studio 2005 Professional
    Version 8.0.50727.762  (SP.050727-7600)
    Microsoft .NET Framework
    Version 2.0.50727
    Microsoft Visual Basic 2005  
    Microsoft Visual C++ 2005  
    Microsoft Visual Studio 2005 Professional Edition - 日本語 Service Pack 1 (KB926602)  

    DLLからの返り値でboolの値が反対になります。

    確認のためにDLL側のソースに値を確認する行を追加しています。
    デバッグで見ているとDLL側ではfalseになっているのですがVBで変数に返された値がTrueになっていました。
    よろしくお願いいたします。

    -------------------------------

    xxx_Dll.cpp
    __declspec(dllexport) bool __stdcall xxx_IsGray(void* obj)
    {
    	xxxData* pThis = (xxxData*)obj;
    	bool b1 = pThis->IsGray();
    	return pThis->IsGray();
    }
    
    xxx_Dll.h
    __declspec(dllexport) bool __stdcall xxx_IsGray(void* obj);
    
    xxxSDK.vb
    Declare Function IsGray Lib "xxx.dll" Alias "xxx_IsGray" ( _
            ByVal obj As IntPtr) As Boolean
    Form1.vb
    ...
    bolIP1 = IsGray(cImageData)
    ...
    2006年12月20日 4:22

すべての返信

  • 一応、bool型を使わないとどうなりますか?
    (Win32API等は全てBOOL型(int型)を使っていますし)

    DLL型をBOOLに変更して
    VB側もBooleanでなくIntegerで受けるようにしてみては。
    (非0ならばBooleanのTrue、0ならBooleanのFalseという風に扱う)

    追記編集
    DLL側がBOOLであれば、VB側はBooleanでも大丈夫なようです。
    2006年12月20日 4:34
  • 蒼の洞窟 さま 回答ありがとうございます。

    回答をいただき色々調べて見ました。

    VB側のBooleanはfalse=0 true=0以外(-1)となっていました。
    DLL側のboolはfalse=0 true=1になっていました。

    ロジック的にはDLLとVBの受け渡しでtrueが違うようですが受け渡し的には問題が無いようです。
    でも、うまく受け渡しが出来ません。

    ベタですが下記のようにすると受け渡しがうまくいくようです。
    boolを直接返すとだめでキャストをかけるとうまくいくような変な状態です。
    もう少し調べてみます。

    bool b = pThis->IsGray();
     int i = (int)b;
     return b;

    2006年12月20日 8:49
  • C++のbool型は1バイトらしいです。
    それをSystem.Boolean型(4バイト?)で受けるのが不味いのかも。
    マーシャラが何をやっているのか定かでないので断定できませんけれども。
    # 1バイトってことは VB側で System.Byte で受けるとどうなるかなぁ。

    DLLの型は純粋なCの型にしておくのが無難でしょう。
    つまり bool型は使わない。(C99からは_Bool ってのがあるが、、、)


    >boolを直接返すとだめでキャストをかけるとうまくいくような変な状態です。
    戻り値の型をBOOLにして、そのまま bool の値を返してみてはどうでしょうか?


    >int i = (int)b;
    なぜこれでうまくいくのか?
    DLLが微妙な状態になっているんじゃないかなぁ。一度リビルドしたほうがよいかも。
    (微妙な状態→変数の値を保持しているメモリがずれちゃっているとか。ヘッダファイルを変更するとよく起こる)

    2006年12月20日 8:59
  • >C++のbool型は1バイトらしいです。
    >それをSystem.Boolean型(4バイト?)で受けるのが不味いのかも。
    >マーシャラが何をやっているのか定かでないので断定できませんけれども。
    ># 1バイトってことは VB側で System.Byte で受けるとどうなるかなぁ。
    >
    >DLLの型は純粋なCの型にしておくのが無難でしょう。
    >つまり bool型は使わない。(C99からは_Bool ってのがあるが、、、)

    C++のbool型は1バイトなんですね。
    下記のように変更してみました。一応うまく動きますが問題は無いのでしょうか。
    boolをintに変えてみました。
    VB側はBoolean型で変更はしていません。

    __declspec(dllexport) int __stdcall xxx_IsGray(void* obj)
    {
    xxxData* pThis = (xxxData*)obj;
     return (int)pThis->IsGray();
    }

    2006年12月20日 9:32
  • bool は Windows の DLL 呼び出しなんかの仕組みが成立した後に
    C++ に採用された型なんで、通常、Windows での DLL インターフェイス
    に真理値型を利用したい場合は bool ではなく BOOL を用います。

    つーことで、BOOL を使ってください。

    # 小文字の bool は C++ のプリミティブな型ですが、
    # 大文字の BOOL は int の typedef です。

     

    2006年12月20日 15:14
  • System.Boolean を Declare で扱う場合には、MashalAsAttribute 属性を指定した方が良いかと。

    今回は戻り値が (BOOL ではなく) bool 型なので、 『As <MarshalAs(UnmanagedType.U1)> Boolean』とか。

    2006年12月28日 6:38