3

ユーザー定義の構造をVB6アプリケーションからC++DLLに渡す方法を理解しようとしています。

これが私のVB6コードのサンプルです:

Private Type ObjetVB  
    Rank As Integer
    Id As String
End Type  

Private Declare Sub testLObj Lib "D:\TestDLL.dll" (Tab_Obj() As ObjetVB)
Private Declare Sub testObj Lib "D:\TestDLL.dll" (ByRef Obj As ObjetVB)

Private Sub Command1_Click()
    Dim elements(1 To 4) As ObjetVB, i As Long

    For i = 1 To 4
        elements(i).Rank = i
        elements(i).Id = "Pouet"
    Next

    testLObj elements()
End Sub

Private Sub Command2_Click()
    Dim ObjCrash As ObjetVB

    ObjCrash.Rank = 1
    ObjCrash.Id = "Pouet"

    testObj ObjCrash

End Sub

そして私のC++コードのサンプル:

struct ObjetVB
{
    short Rank;
    char* Id;
};

void videFichier()
{
    ofstream fichier("../../../log.txt", ios::out | ios::trunc);
    if(fichier)
    {    
        fichier.close();
    }
}    

int Log(ObjetVB ObjInput)  
{
    ofstream fichier("../../../log.txt", ios::out | ios::app);
    if(fichier)
    {
        fichier << ObjInput.Rank << endl << "Id : " << ObjInput.Id << endl << endl;
        fichier.close();
    }
    return 0;
}

void __stdcall testObj (ObjetVB* ObjInput)  
{
    videFichier();
    log(*ObjInput);
}

void __stdcall testLObj (SAFEARRAY **Tab_Obj)
{
    ObjetVB *elt;
    HRESULT ret;
    unsigned long i;
    videFichier();

    if ((ret = SafeArrayAccessData(*Tab_Obj,(void **) &elt))==S_OK)
    {
        for (i = 0; i < (*Tab_Obj)->rgsabound->cElements; i++)
        {
            Log(elt[i]);
        } 
        SafeArrayUnaccessData(*Tab_Obj);
    }
}

私の問題は、「Command2」をクリックすると、ログファイルが次のようになることです。

1  
Id : Pouet  

一方、「Command1」をクリックすると、次のようになります。

1
Id : P

2
Id : P

3
Id : P

4
Id : P

単一のアイテムを渡すと、C++DLLが「char*Id」を文字のチェーンとして認識するのに、アイテムの配列を使用すると、最初の文字へのポインターとして認識されるように見えるのはなぜですか?

そして、最も注目すべきことに、どうすればそれを修正できますか?c++構造体でchar*の代わりにLBSTRを使用しようとしましたが、修正されませんでした。また、VB6文字列を初期化する前に、「elements(i).Id = String(255、vbNullChar)」を追加しようとしましたが、どちらかが役立つことがわかります。

いつものように、読んで助けようとしてくれた皆さんに感謝したいと思います。

ちなみに、英語は私にとって外国語なので、ほぼ理解できるといいのですが、そうでない場合はもちろんお詫びします。

編集 :

それが役立つかどうかはわかりませんが、Mark Bertenshawが提案したことを試した後、これも試しました:VB6で:

Id As String * 10  

C ++の場合:

char Id[10];  

これはこの奇妙な結果をもたらしました:

Objet : 
32
Id : P

Objet : 
1
Id :  

Objet : 
32
Id : P

Objet : 
2
Id :  
4

2 に答える 2

2

ここで何が起こっているかというと、VB は「役に立ち」、ID の 2 バイトの Unicode 文字列 (BSTR) を 1 バイトの ANSI 文字列 (char*) に自動的に変換します。ただし、VB Type を配列に入れると、文字列で何をしているのか完全にはわかりません。

1 つの可能性は、ObjetVB 構造体のパッキングが問題を引き起こしていることです。次のように定義してみてください。

Private Type ObjetVB
   Id As String        ' 4 bytes
   Rank As Integer     ' 2 bytes
End Type   

struct ObjetVB
{
    char* Id;          // 4 bytes
    short Rank;        // 2 bytes
}
于 2012-06-28T15:23:41.957 に答える
2

VB6 は、char 配列ではなく BSTR を返します。たとえば、BSTR はワイド文字でいっぱいになります。標準のローマ字の場合、2 バイトのエンコードは ASCII と同じだと思いますが、2 番目のバイトが 0 であるため、文字列の長さがゼロのように見えます。

char* の代わりに wchar_t* を使用すると、すべてが機能しているように見えます。wchar_t と BSTR が同じサイズであることを保証できないため、これは最善の方法ではありません。

ConvertBSTRToString関数を使用することをお勧めします。

于 2012-06-28T14:13:47.343 に答える