簡體   English   中英

.NET互操作層和COM之間會發生什么?

[英]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測試代碼的功能。

作為一個粗略的輪廓,我想這將涉及:

  • 分配非托管緩沖區來保存數組值
  • 通過P / Invoke調用Ole Automation SAFEARRAY初始化API以分配SAFEARRAY結構並將數組緩沖區作為其pData成員附加到它
  • 使用此SAFEARRAY調用GetTags方法
  • 在將...之前的非托管緩沖區編組到托管數組中之前......
  • 調用Win32 API來銷毀SAFEARRAY

但是,如果可以的話,更好地將COM組件更改為正確執行操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM