고객이 C++ 클라이언트에서 호출 한 오래된 C++ COM .dll이 있습니다.C#/COM에서 C++ 클라이언트로 값을 반환 하시겠습니까?
우리는 이전 .dll을 .NET으로 작성된 새로운 COM 등록 된 것으로 바꾸려고합니다.
C++ 클라이언트는 새로운 .dll을 호출 할 수 있지만 특정 메서드를 호출하면 충돌이 발생합니다.
"outNoOfChildren"변수 또는 아래의 outChildList 배열에서 잘못된 것을 반환하는 것으로 보입니다.
은 (클라이언트에 오류 메시지가 읽습니다 : "알 수없는 예외가 잡힌 차일의 수 측정 :. -2147467259 제한 : = 2"., 그것은이 기대 우리가 반환하려고하는)이상한 일이다 새로운 .NET .dll의 메서드 호출은 우리가 가지고있는 다른 테스트 클라이언트 (VB6)에서 작동하는 것 같습니다.
.NET 인터페이스 :
이것은 우리가 쓴 .NET의 .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;
}
:
이
우리가 대체하려고하는 것을 .DLL ++은 C의 기능입니다...
[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;
}
업데이트 :
[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);
: 우리의 새로운 .NET 그것이 OLE/COM 개체 뷰어에서 다음과 같습니다 .DLL 등록하면
[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);
: 원래 C++ .DLL은 OLE/COM 개체 뷰어에서 다음과 같습니다
업데이트 2 : 오류가 "outNoOfChildren"에 없지만 "outChildList"배열에있을 것으로 의심되기 시작했습니다. 질문을 업데이트하고 이에 대한 코드 샘플을 수정했습니다.
많은 아이디어가 감사합니다!
상태 매개 변수는 어떻게 되었습니까? –
알아두기 마지막 매개 변수는 함수의 반환 값입니다. – Poppert
.NET .dll로 스와핑하기 전후에 OLE/COM Object Viewer에서 어떻게 표시되는지 질문이 업데이트되었습니다. 나는 C# 함수 반환 값이 "[out, retval] VARIANT *"로 번역 된 것으로 가정하고 그 것이 좋습니다. 하지만 C++ 스 니펫에는 상태 매개 변수와 S_OK의 반환이 모두 이상하다고 보입니다. – Poppert