C ++ DLL只读取safearray中包含的字符串的第一个char

时间:2012-06-28 13:59:10

标签: c++ string dll vb6 safearray

我正在试图弄清楚如何将用户定义的结构从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 ++结构中使用LBSTR而不是char *,它没有修复它,我还尝试添加“elements(i).Id = String(255,vbNullChar)”berfore初始化VB6字符串,但它没有'证明是有帮助的。

像往常一样,我要感谢你们所有人在阅读和尝试帮助的时候。

旁注:英语对我来说是一种外国语言,所以我希望我几乎可以理解,当然,如果情况并非如此,我会道歉。

修改:

我不知道它是否有所帮助,但在尝试了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 :  

2 个答案:

答案 0 :(得分:2)

VB6返回BSTR而不是char数组。一个BSTR将充满广泛的字符。对于标准罗马字母,我认为2字节编码与ASCII相同,但第二个字节为0,因此您的字符串看起来长度为零。

你可以使用wchar_t *而不是char *,你会发现一切似乎都有效。这不是最好的方法,因为你无法保证wchar_t和BSTR的大小相同。

您最好的选择是使用ConvertBSTRToString功能。

答案 1 :(得分:2)

这里发生的是VB正在“有用”,并自动将ID中的2字节Unicode字符串(BSTR)转换为1字节的ANSI字符串(char *)。但是,当您将VB Type放入数组时,我并不完全确定它对字符串的作用。

一种可能性是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
}