[英]What happens between the .NET interop layer and COM?
我在我的C#.NET项目中使用COM。
但是我调用的方法之一并没有按预期运行。
所以我很想知道我的.NET代码,Interop层和COM之间发生了什么。
我知道tlbimp.exe
为COM组件生成元数据包装器,我可以在Object浏览器中看到这些生成的方法。
我是否能够看到/调试在调用其中一个包装器方法时会发生什么?
我将一个数组传递给下面的方法,并期望将填充此数组,但不会填充数组。 我调用以下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互操作编组有一些有趣的东西。
所以我想知道在调用GetTags()
方法后是否可以看到发生了什么。
我也在这里阅读了以下内容。
"if you are not satisified with the COM Interop marshaller, you can "override" just about every aspect of it through the very large and useful System::Runtime::InteropServices namespace"
我怎样才能实现上述目标?
编辑:添加一个有效的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
本身应该填充该数组(来自COM代码)。 但这可能永远不会起作用,因为该参数是[in]
参数。
要使COM组件能够填充该数组,它应该作为[in,out]参数和引用(SAFEARRAY *)传递。
更新 :好的,显然我是在.NET中混合创建COM组件并从.NET调用COM组件。
CCW(com可调用包装器)确实为COM SafeArray采用.NET数组。 我看到你在问题的代码中创建了你的数组,但你没有显示你实际填充它的方式。 也许那段代码出了问题? 你能分享一下吗?
不确定这是否是您问题的解决方案,但我在过去遇到过COM-interop和SAFEARRAY的问题。
有一件事我从中学到的是,.NET相当于一个COM SAFEARRAY的应该永远是object
,所以尽量通过你的数组作为object
以代替作为Array
。
我毫不犹豫地建议这个答案,但......
如果Delphi测试代码确实有效,如其他地方所述,这意味着GetFags方法不能通过SAFEARRAY规则正常播放。 如果COM方法总是在进程中调用,那么您可以通过“手动”执行一些自定义编组来实现.NET代码,完全遵循非托管Delphi测试代码的功能。
作为一个粗略的轮廓,我想这将涉及:
但是,如果可以的话,更好地将COM组件更改为正确执行操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.