通过COM将字符串数组从c#发送到c ++

时间:2013-03-19 11:54:24

标签: c# c++ arrays string com

我尝试通过com interop将数组从c#发送到c ++。

这是c#Code

public void SendArraytoCPlusPlus()
{
    GGXForVBA.GeoAtlas GA = new GGXForVBA.GeoAtlas();
    string[] arr = new string[3];
    arr[0] = "One";
    arr[1] = "Two";
    arr[2] = "Five";
    GA.GetArrayVar(arr);
}

这是c ++代码

void GeoAtlas::GetArrayVar(VARIANT& arr)
{ 
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    SAFEARRAY* pSafeArray = arr.parray;
    long lStartBound = 0;
    long lEndBound = 0;
    SafeArrayGetLBound(pSafeArray,1,&lStartBound);
    SafeArrayGetUBound(pSafeArray,1,&lEndBound);
    LPCSTR * arrayAccess = NULL;

    SafeArrayAccessData( pSafeArray , (void**)&arrayAccess);
    for(int iIndex = lStartBound; iIndex <= lEndBound; iIndex ++)
    {   
        LPCTSTR myString = (LPCTSTR)arrayAccess[iIndex];
        AfxMessageBox(myString);        
    }  
}

这是idl

[id(23)] void GetArrayVar(VARIANT arr);

问题是,消息框只显示字符串的第一个字母,即“O”。 'T','F'。我想读整个字符串。有什么建议吗?

4 个答案:

答案 0 :(得分:0)

这是基于您发送Unicode / UTF8字符串但消息框需要ANSI C字符串的事实。尝试在发送之前将字符串转换为ASCII。在这里查看编码类http://msdn.microsoft.com/en-us/library/system.text.encoding.aspx

您可能希望尝试将它们作为字节数组发送。

var bytes = Encoding.ASCII.GetBytes("one");

答案 1 :(得分:0)

您应该传递SAFEARRAY而不是VARIANT:

[id(23)] void GetArrayVar([in] SAFEARRAY(BSTR) arr);

在实施中,像这样访问它:

void GeoAtlas::GetArrayVar(SAFEARRAY* arr)
{
    CComSafeArray<BSTR> sa;
    sa.Attach(arr);

    for (int i = sa.GetLowerBound(); i <= sa.GetUpperBound(); ++i)
    {
        AfxMessageBox(sa[i]);
    }

    sa.Detach();
}

答案 2 :(得分:0)

发送方看起来很好。在接收方试试这个。

[id(1), helpstring("method SetArrayVar")] HRESULT SetArrayVar([in] VARIANT varMachineList);

STDMETHODIMP GeoAtlas::SetArrayVar(VARIANT arr)
{
    long lower, upper;
    SafeArrayGetLBound(pSafeArray, 1, &lower);
    SafeArrayGetUBound(pSafeArray, 1, &upper);
    DWORD dwItems = upper - lower + 1;
    resize(dwItems);

    SAFEARRAY* pSafeArray = arr.parray;
    BSTR* pBstr;
    if ( SUCCEEDED(SafeArrayAccessData(pSafeArray, (LPVOID*) &pBstr)) )
    {
        iterator it = begin();
        for ( long i=lower; i<=upper; i++, pBstr++, it++ )
        {
            USES_CONVERSION;
            *it = OLE2CT(*pBstr);
            // Here you gets array elements and use it
        }
    }

    // release the data block
    SafeArrayUnaccessData(pSafeArray);
}

答案 3 :(得分:0)

不确定,但看起来你有Unicode / MBCS不匹配。

托管部分创建一个UTF-16编码字符串数组,而非托管部分似乎是使用多字节字符集编译的。因此,在看到第一个空字符(实际上只是UTF-16字符的第二个字节)时,您的MBCS代码认为它已到达字符串的末尾。

一种解决方案是将C ++项目中的字符集设置更改为Unicode并重建。

另一个是改变代码:

...
LPCWSTR * arrayAccess = NULL; // change LPCSTR -> LPCWSTR
...

for(int iIndex = lStartBound; iIndex <= lEndBound; iIndex ++)
{   
    bstr_t myString = arrayAccess[iIndex];
    AfxMessageBox(myString);        
} 

bstr_t将使用BSTR正确初始化,但它也提供转换为const char*,因此调用AfxMessageBox即可。