NET Interop层和COM之间会发生什么?
作者:互联网
我在C#.NET项目中使用COM.
但是,我调用的方法之一无法正常工作.
所以我很好奇我的.NET代码,Interop层和COM之间发生了什么.
我知道tlbimp.exe会为COM组件生成元数据包装,并且可以在对象浏览器中看到这些生成的方法.
我可以查看/调试这些包装方法之一时会发生什么情况吗?
我将数组传递给下面的方法,并期望将填充该数组,但是不会填充该数组.
我正在调用以下tlbimp.exe生成的方法,结果异常:
int GetTags(System.Array buffer)
Member of CServer.IUser
方法IDL:
[id(0x000000d5)]
HRESULT GetTags(
[in] SAFEARRAY(long) buffer,
[out, retval] long* retval);
.NET代码调用此方法:
Array tagsArray = Array.CreateInstance(typeof(int), tagsLength);
userWrapper.GetTags(tagsArray);
我称之为的其他COM方法工作正常.但是,当我调用任何将Array作为参数的方法时,它无法按预期工作.
我假设COM interop编组器会发生一些有趣的事情.
因此,我想知道在调用GetTags()方法后是否可以看到正在发生的情况.
我也阅读了以下here.
“如果您对COM Interop编组器不满意,则可以通过非常大且有用的System :: Runtime :: InteropServices命名空间来“覆盖”它的几乎每个方面”
如何实现以上目标?
编辑:添加一个有效的Delphi测试脚本
procedure TComTestForm.TestUserBtnClick(Sender: TObject);
var
nCnt :integer;
User :IUser;
Persona :IUserPersona;
ArrayBounds :TSafeArrayBound;
ArrayData :Pointer;
TagList :PSafeArray;
nSize :integer;
begin
User := Session.GetUser;
ArrayBounds.lLbound := 0;
ArrayBounds.cElements := 0;
TagList := SafeArrayCreate( varInteger, 1, ArrayBounds );
User.GetTags( TagList );
if SafeArrayAccessData( TagList, ArrayData ) = S_OK then
begin
nSize := TagList.rgsabound[0].cElements;
OutLine( '----Available Tags, ' + IntToStr(nSize) + ' tags' );
for nCnt := 0 to nSize - 1 do
begin
OutLine( IntToStr( IntegerArray(ArrayData)[nCnt] ) );
end;
OutLine( '----');
SafeArrayUnAccessData( TagList );
SafeArrayDestroy( TagList );
end;
end;
解决方法:
另一个更新:
我只是意识到这可能是您的意思是,GetTags本身应该填充该Array(来自COM代码).但这永远无法工作,因为该参数是[in]参数.
为了使COM组件能够填充该数组,应将其作为[in,out]参数并通过引用(SAFEARRAY *)进行传递.
更新:好的,显然我在将.NET中COM组件的创建与从.NET中调用COM组件混合在一起.
CCW(可调用包装器)确实为COM SafeArray采用了.NET数组.我看到您在问题中的代码中创建了数组,但是没有显示实际填充它的方式.该代码可能有问题吗?你能分享吗?
不知道这是否可以解决您的问题,但过去我在使用COM-interop和SAFEARRAY时遇到过问题.
我从中学到的一件事是,COM SAFEARRAY的.NET等效项应该始终是对象,因此请尝试将数组作为对象而不是作为数组传递.
标签:com,com-interop,tlbimp,c,net 来源: https://codeday.me/bug/20191208/2091436.html