[英]What happens between the .NET interop layer and COM?
I am using COM in my C# .NET project. 我在我的C#.NET项目中使用COM。
However one of the methods I call is not acting as expected. 但是我调用的方法之一并没有按预期运行。
So I am curious to see what is happening between my .NET code, the Interop layer and COM. 所以我很想知道我的.NET代码,Interop层和COM之间发生了什么。
I know the tlbimp.exe
generates the metadata wrapper for the COM component and I can see these generated methods in the Object browser. 我知道
tlbimp.exe
为COM组件生成元数据包装器,我可以在Object浏览器中看到这些生成的方法。
Am I able to see/debug what happens when one of these wrapper methods is called? 我是否能够看到/调试在调用其中一个包装器方法时会发生什么?
I pass an Array to the method below, and expect that this array will be populated, however the Array does not get populated. 我将一个数组传递给下面的方法,并期望将填充此数组,但不会填充数组。 I am calling the following
tlbimp.exe
generated method with unexpected results: 我调用以下
tlbimp.exe
生成的方法,结果意外:
int GetTags(System.Array buffer)
Member of CServer.IUser
Method IDL: 方法IDL:
[id(0x000000d5)]
HRESULT GetTags(
[in] SAFEARRAY(long) buffer,
[out, retval] long* retval);
.NET code calling this method: 调用此方法的.NET代码:
Array tagsArray = Array.CreateInstance(typeof(int), tagsLength);
userWrapper.GetTags(tagsArray);
Other COM methods I call work fine. 其他COM方法我称之为正常工作。 However when I call any method which expects an Array as a parameter it does not work as expected.
但是,当我调用任何期望将Array作为参数的方法时,它不能按预期工作。
I am presuming that there is something funny going in with the COM interop marshaller. 我假设COM互操作编组有一些有趣的东西。
So I would like to know if I can see what is happening after I call the GetTags()
method. 所以我想知道在调用
GetTags()
方法后是否可以看到发生了什么。
Also I have read the following here . 我也在这里阅读了以下内容。
"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"
How can I achieve the above? 我怎样才能实现上述目标?
EDIT: Adding a Delphi test script which works 编辑:添加一个有效的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;
Another update : I just realize it might be that you mean that the GetTags
itself should populate that Array (from the COM code). 另一个更新 :我只是意识到你可能意味着
GetTags
本身应该填充该数组(来自COM代码)。 But this can never work as that parameter is an [in]
parameter. 但这可能永远不会起作用,因为该参数是
[in]
参数。
For the COM component to be able to fill up that Array, It should be passed as an [in, out] parameter, and by reference (SAFEARRAY*). 要使COM组件能够填充该数组,它应该作为[in,out]参数和引用(SAFEARRAY *)传递。
Update : Ok, apparently I was mixing the creation of a COM component in .NET with calling a COM component from .NET. 更新 :好的,显然我是在.NET中混合创建COM组件并从.NET调用COM组件。
The CCW (com callable wrapper) indeed takes a .NET Array for COM SafeArray's. CCW(com可调用包装器)确实为COM SafeArray采用.NET数组。 I see you create your array in the code in your question, but you don't show how you actually populate it.
我看到你在问题的代码中创建了你的数组,但你没有显示你实际填充它的方式。 Maybe something's wrong with that code?
也许那段代码出了问题? Could you share it?
你能分享一下吗?
Not sure if this is a solution to your problem, but I've experienced problems with COM-interop and SAFEARRAY's in the past. 不确定这是否是您问题的解决方案,但我在过去遇到过COM-interop和SAFEARRAY的问题。
One thing I learned from it is that the .NET equivalent of a COM SAFEARRAY should always be object
, so try passing your array as an object
in stead of as an Array
. 有一件事我从中学到的是,.NET相当于一个COM SAFEARRAY的应该永远是
object
,所以尽量通过你的数组作为object
以代替作为Array
。
I hesitate to suggest this as an answer, but... 我毫不犹豫地建议这个答案,但......
If the Delphi test code really does work, as noted elsewhere, this means the GetTags method must not be playing properly by SAFEARRAY rules. 如果Delphi测试代码确实有效,如其他地方所述,这意味着GetFags方法不能通过SAFEARRAY规则正常播放。 If the COM method is always called in-process, you MAY be able to get the .NET code to work by doing some custom marshalling "by hand", following exactly what the unmanaged Delphi test code does.
如果COM方法总是在进程中调用,那么您可以通过“手动”执行一些自定义编组来实现.NET代码,完全遵循非托管Delphi测试代码的功能。
As a rough outline, I would imagine that this would involve: 作为一个粗略的轮廓,我想这将涉及:
But much better to get the COM component changed to do things properly, if you can. 但是,如果可以的话,更好地将COM组件更改为正确执行操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.