将字符串数组从COM传递到C#

将字符串数组从COM传递到C#,c#,c++,visual-c++,com-interop,safearray,C#,C++,Visual C++,Com Interop,Safearray,我需要通过类似COM的接口访问COM dll中的C#方法。其中一个方法要求将字符串数组作为输入传递 我正在创建一个安全阵列并将其传递给COM互操作。但是,这似乎不起作用,因为我在互操作层中看到了一个异常。(System.Runtime.InteropServices.SafeArrayTypeMismatchException) 显然,人们期望的类型似乎有所不同 在此处粘贴代码: 要调用的C#方法: C++代码调用相同: int\u tmain() { TCHAR*文件名[128]={TEXT(

我需要通过类似COM的接口访问COM dll中的C#方法。其中一个方法要求将字符串数组作为输入传递

我正在创建一个安全阵列并将其传递给COM互操作。但是,这似乎不起作用,因为我在互操作层中看到了一个异常。(System.Runtime.InteropServices.SafeArrayTypeMismatchException)

显然,人们期望的类型似乎有所不同

在此处粘贴代码:

要调用的C#方法: C++代码调用相同:
int\u tmain()
{
TCHAR*文件名[128]={TEXT(“C:\\Program Files\\IBM\\RTC.NET”),
文本(“C:\\KIRAN\\Work\\RFT”),文本(“.\\bin\\Debug”)};
SAFEARRAY*pSA=CreateSafeStringArray(3,文件名);
_tprintf(TEXT(“%d”),pIManaged->DoIt3(3,pSA));
安全阵列存储器(pSA);
}
静态SAFEARRAY*CreateSafeStringArray(长元素,TCHAR*元素[])
{
SAFEARRAYBOUND saBound[1];
saBound[0]。cElements=NeElements;
saBound[0].lLbound=0;
SAFEARRAY*pSA=SafeArrayCreate(VT_变体,1,SABOND);
如果(pSA==NULL)
{
返回NULL;
}
对于(int ix=0;ix

欢迎提出任何想法/建议。

对于BSTR字符串数组,您可以直接在数组上设置BSTR值,也可以使用ATL/MFC CString:

...
psa = SafeArrayCreate( VT_BSTR, 1, saBound);
HRESULT hr = SafeArrayLock( psa );
//TODO: test for hr success

if (pSA == NULL)
{
    return NULL;
}

for (int ix = 0; ix < nElements; ix++)
{
    long rgIndicies[1];
    rgIndicies[0] = ix + saBound[0].lLbound;
    CString tempstr(elements[ix]);

    ((BSTR*)psa->pvData)[ix] = tempstr.AllocSysString();
    _tprintf(TEXT("%d"), hr);
}

hr = SafeArrayUnlock( psa );
//TODO: test for hr success
...
。。。
psa=安全阵列创建(VT_BSTR,1,saBound);
HRESULT hr=安全气囊(psa);
//TODO:人力资源成功测试
如果(pSA==NULL)
{
返回NULL;
}
对于(int ix=0;ixpvData)[ix]=tempsr.AllocSysString();
_tprintf(文本(“%d”),hr);
}
hr=安全锁(psa);
//TODO:人力资源成功测试
...

我想出来了!以下代码起作用:

static SAFEARRAY *CreateSafeStringArray(long nElements, TCHAR *elements[])
{
SAFEARRAYBOUND saBound[1];

saBound[0].cElements = nElements;
saBound[0].lLbound = 0;

SAFEARRAY *pSA = SafeArrayCreate(VT_BSTR, 1, saBound);

if (pSA == NULL)
{
    return NULL;
}

for (int ix = 0; ix < nElements; ix++)
{
    BSTR pData = SysAllocString(elements[ix]);

    long rgIndicies[1];

    rgIndicies[0] = saBound[0].lLbound + ix;

    HRESULT hr = SafeArrayPutElement(pSA, rgIndicies, pData);

    _tprintf(TEXT("%d"), hr);
}

return pSA;
}
静态SAFEARRAY*创建SafeStringArray(长元素,TCHAR*元素[])
{
SAFEARRAYBOUND saBound[1];
saBound[0]。cElements=NeElements;
saBound[0].lLbound=0;
SAFEARRAY*pSA=SafeArrayCreate(VT_BSTR,1,saBound);
如果(pSA==NULL)
{
返回NULL;
}
对于(int ix=0;ix

谢谢你的建议

如何为ComObject生成运行时可调用的包装器是c#代码?很不清楚如何调用c#方法。但是您创建了一个对象[],而不是字符串[]。将VTH.BSTR传递给SAFARRERACREATE(),并相应地调整代码的其余部分。不确定C++,但为了得到VBA客户端调用一个C.C.CW,我得到的唯一方法是声明字符串数组参数为“代码> REF:<代码>公共长DOIT3(int nFiels,REFString []文件名);<代码>@Joe这是因为VBA客户端总是以VT_byref的形式传递变量参数谢谢,yms!我会试试的。但是,这种方法似乎是通过操纵内部场来实现的。是否有一种标准的方法来执行此操作--可能是,我传递给SafeArrayPutElement()的参数是错误的。
...
psa = SafeArrayCreate( VT_BSTR, 1, saBound);
HRESULT hr = SafeArrayLock( psa );
//TODO: test for hr success

if (pSA == NULL)
{
    return NULL;
}

for (int ix = 0; ix < nElements; ix++)
{
    long rgIndicies[1];
    rgIndicies[0] = ix + saBound[0].lLbound;
    CString tempstr(elements[ix]);

    ((BSTR*)psa->pvData)[ix] = tempstr.AllocSysString();
    _tprintf(TEXT("%d"), hr);
}

hr = SafeArrayUnlock( psa );
//TODO: test for hr success
...
static SAFEARRAY *CreateSafeStringArray(long nElements, TCHAR *elements[])
{
SAFEARRAYBOUND saBound[1];

saBound[0].cElements = nElements;
saBound[0].lLbound = 0;

SAFEARRAY *pSA = SafeArrayCreate(VT_BSTR, 1, saBound);

if (pSA == NULL)
{
    return NULL;
}

for (int ix = 0; ix < nElements; ix++)
{
    BSTR pData = SysAllocString(elements[ix]);

    long rgIndicies[1];

    rgIndicies[0] = saBound[0].lLbound + ix;

    HRESULT hr = SafeArrayPutElement(pSA, rgIndicies, pData);

    _tprintf(TEXT("%d"), hr);
}

return pSA;
}