gpt4 book ai didi

c++ - 将值 C#/COM 返回到 C++ 客户端?

转载 作者:太空宇宙 更新时间:2023-11-04 12:09:02 25 4
gpt4 key购买 nike

我们有一个客户从他们的 C++ 客户端调用的旧 C++ COM .dll。

我们正在尝试用 .NET 编写的新 COM 注册文件替换旧的 .dll。

C++ 客户端可以调用我们的新 .dll,但在调用我们的特定方法后崩溃。

似乎我们在变量“outNoOfChildren”或下面的 outChildList 数组中返回了一些错误信息。

(客户端中的错误消息为:“捕获到未知异常。测量的 child 数量:-2147467259 限制:= 2",它期望我们试图返回 2。)

奇怪的是,我们新的 .NET .dll 中的方法调用似乎可以从我们拥有的另一个测试客户端 (VB6) 运行。

这是我们试图替换的 C++ .dll 中的函数:

STDMETHODIMP marcomBase::XgetChildren(VARIANT inUser,
VARIANT inId,
VARIANT *outNoOfChildren,
VARIANT *outChildList,
VARIANT *outErrMsg,
VARIANT *status)
long stat= 1;
char user[255+1];
char id[255+1];
long noOfChildren = 0;
char errMsg[255+1] = "";
_bstr_t temp_bstr;
long inparamType;
long dumInt;
SAFEARRAY *pArray;
long ix[2];
VARIANT var;
SAFEARRAYBOUND rgsabound[2];
ChildT childList;
ChildT *childListTemp = NULL;
ChildT *childListTempNext = NULL;

childList.nextChild = NULL;

getInParam( inUser, &inparamType, user, &dumInt);
if (inparamType != VT_BSTR)
{
strcpy(errMsg, "Parameter 1 incorrect, type must be VT_BSTR");
stat = 0;
}

if (stat == 1)
{
getInParam( inId, &inparamType, id, &dumInt);
if (inparamType != VT_BSTR)
{
strcpy(errMsg, "Parameter 2 incorrect, type must be VT_BSTR");
stat = 0;
}
}

if (stat == 1)
{
stat = barApiObj.getChildren(user, id, &noOfChildren, childList, errMsg);
}

outNoOfChildren->vt = VT_I4;
outNoOfChildren->lVal = noOfChildren;

rgsabound[0].lLbound = 1;
rgsabound[0].cElements = noOfChildren;
rgsabound[1].lLbound = 1;
rgsabound[1].cElements = 3;

pArray = ::SafeArrayCreate(VT_VARIANT, 2, rgsabound);
outChildList->vt = VT_ARRAY|VT_VARIANT;
outChildList->parray = pArray;

ix[0] = 1;

childListTemp = childList.nextChild;

while (childListTemp != NULL)
{
temp_bstr = childListTemp->child;
var.vt = VT_BSTR;
var.bstrVal = temp_bstr.copy();
ix[1] = 1;
::SafeArrayPutElement(pArray, ix, &var);

temp_bstr = childListTemp->prodNo;
var.vt = VT_BSTR;
var.bstrVal = temp_bstr.copy();
ix[1] = 2;
::SafeArrayPutElement(pArray, ix, &var);

temp_bstr = childListTemp->rev;
var.vt = VT_BSTR;
var.bstrVal = temp_bstr.copy();
ix[1] = 3;
::SafeArrayPutElement(pArray, ix, &var);

ix[0] = ix[0] + 1;

childListTempNext = childListTemp->nextChild;
delete childListTemp;
childListTemp = childListTempNext;
}

temp_bstr = errMsg;
outErrMsg->vt = VT_BSTR;
outErrMsg->bstrVal = temp_bstr.copy();

status->vt = VT_I4;
status->lVal = stat;

return S_OK;
}

这是我们编写的 .NET .dll:

.NET 接口(interface):

...
[DispId(12)]
[Description("method XgetChildren")]
object XgetChildren(object inUser, object inId, out object outNoOfChildren, out object outChildList, out object outErrMsg);
...

.NET 类

public object XgetChildren(object inUser, object inId, out object outNoOfChildren, out object outChildList, out object outErrMsg)
{
outNoOfChildren = 0;
outChildList = null;
outErrMsg = "";

List<IndividualInfo> children = null;
try
{
PrevasMesExternalServiceClient client = getClient();
children = client.GetChildren(new SerialNo() { Number = inId.ToString() });
}
catch (Exception ex)
{
return Constants.STATUS_FAIL;
}

int[] myLengthsArray = { children.Count, 3 }; //Length of each array
int[] myBoundsArray = { 1, 1 }; //Start index of each array

Array myArray = Array.CreateInstance(typeof(string), myLengthsArray, myBoundsArray); //Create 1-based array of arrays

for (int i = 0; i < children.Count; i++)
{
myArray.SetValue(Utils.getStrValue(children[i].SerialNumber, Constants.pmesIDNO_LENGTH), i+1, 1);
myArray.SetValue(Utils.getStrValue(children[i].ProductNumber, Constants.pmesPRODUCTNO_LENGTH), i+1, 2);
myArray.SetValue(Utils.getStrValue(children[i].Revision, Constants.pmesRSTATE_LENGTH), i+1, 3);
}

outChildList = myArray;
outNoOfChildren = children.Count;

return Constants.STATUS_OK;
}

更新:原始的 C++ .dll 在 OLE/COM 对象查看器中看起来像这样:

    [id(0x0000000c), helpstring("method XgetChildren")]
HRESULT XgetChildren(
[in] VARIANT inUser,
[in] VARIANT inId,
[out] VARIANT* outNoOfChildren,
[out] VARIANT* outChildList,
[out] VARIANT* outErrMsg,
[out, retval] VARIANT* status);

在注册我们新的 .NET .dll 后,它在 OLE/COM 对象查看器中看起来像这样:

    [id(0x0000000c), helpstring("method ")]
HRESULT XgetChildren(
[in] VARIANT inUser,
[in] VARIANT inId,
[out] VARIANT* outNoOfChildren,
[out] VARIANT* outChildList,
[out] VARIANT* outErrMsg,
[out, retval] VARIANT* pRetVal);

更新 2:我开始怀疑错误可能不在“outNoOfChildren”中,而是在数组“outChildList”中。我已经更新了问题并为此修改了代码示例。

非常感谢任何想法!

最佳答案

Measured: -2147467259 Limits: = 2"

这是一个神奇的数字。将其转换为十六进制,您将得到 0x80004005。那是一个错误代码,臭名昭著的 E_FAIL 或“未指定的错误”。所以在我们看不到的点中的某个地方,您将错误返回值解释为数字。可能是 vtError 类型的变体并忽略变体类型。这就是问题的全部结论,请检查代码中的错误处理。

关于c++ - 将值 C#/COM 返回到 C++ 客户端?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10621148/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com