手動生成C#的COM包裝類的常見問題和解決辦法
看一下如下程式碼:
[Guid("25088995-7924-4B15-B01A-EA7C422ADC68")] public class CHelloClass : IHello { [DispId(1)] [MethodImplAttribute(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] public extern void HelloWorld(); }
class Program { static void Main(string[] args) { CHelloClass obj = new CHelloClass(); obj.HelloWorld(); } } |
這裡的CHelloClass是一個COM物件,指定了GUID,實現了IHello介面的HelloWorld函式。然而,當執行這條語句CHelloClass obj = new CHelloClass,會產生如下異常:
Unhandled Exception: System.Security.SecurityException: ECall methods must be packaged into a system module. |
這裡異常資訊需要解釋一下:ECall是一種內部呼叫的方式(還存在其它方式如FCall等),由CLR本身實現,而不由使用者提供實現。當CHelloClass中缺少ComImportAttrib這個屬性的時候,CLR會認為HelloWorld這個函式是在CLR本身實現的,然後又在CLR內部的呼叫表(這個表維護所有CLR內部呼叫的函式)無法查到對應的實現,所以才丟擲異常。當ComImportAttribute存在的時候,CLR才知道這個class是從COM物件Import過來的,從而作一些特殊處理,並不會對HelloWorld按照ECall方式來處理。
我們再看一下,是否MethodImplAttribute這裡真正需要呢?可以試一下加上ComImport然後去掉MethodImplAttri看看:
[ComImport] [Guid("25088995-7924-4B15-B01A-EA7C422ADC68")] public class CHelloClass : IHello { [DispId(1)] public extern void HelloWorld(); }
class Program { static void Main(string[] args) { CHelloClass obj = new CHelloClass(); obj.HelloWorld(); } } |
當到了new CHelloClass這條語句的時候,會產生下面異常:
Unhandled Exception: System.TypeLoadException: Could not load type 'CHelloClass' from assembly 'Program, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' because the method 'HelloWorld' has no implementation (no RVA). at Program.Main(String[] args) |
這一次,CLR則報告HelloWorld函式沒有對應的實現程式碼。沒有RVA的意思是CLR無法找到HelloWorld函式程式碼的位置。這個位置是一個記憶體的相對位置,因此稱之為RVA(Relative Virtual Address)。由於實際的實現是由CLR提供,準確說是RCW提供,因此這裡是需要MethodImplAttrbute的。
最終正確的版本如下:
[ComImport] [Guid("25088995-7924-4B15-B01A-EA7C422ADC68")] public class CHelloClass : IHello { [DispId(1)] [MethodImplAttribute(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] public extern void HelloWorld(); }
class Program { static void Main(string[] args) { CHelloClass obj = new CHelloClass(); obj.HelloWorld(); } } |
當然了,如果你不自己編寫COM Wrapper程式碼的話則不會遇到類似的問題。所以請儘可能的讓Tlbimp替你生成Interop程式碼,而不是自己手動編寫,除非Tlbimpl生成的程式碼不符合你的要求。
相關文章
- 浮動元素引起的問題和解決辦法?
- 浮動元素引起的問題和解決辦法
- Redis常見的效能問題和解決方法UWRedis
- Firefox 使用常見問題和解決方法Firefox
- uni-app開發 常見異常和解決辦法APP
- 【TUNE_ORACLE】Oracle資料庫與HugePages(三)HugePages常見問題和解決辦法Oracle資料庫
- MySQL 資料庫崩潰(crash)的常見原因和解決辦法MySql資料庫
- SSL證書常見的錯誤和解決辦法是什麼?
- composer依賴相關的問題和解決辦法
- PhpCms安裝報錯怎麼辦?PHPCMS安裝使用常見問題解決辦法PHP
- Ubuntu 常見問題和解答Ubuntu
- MySQL組複製的幾個常見問題以及解決辦法MySql
- 常見的HTTP介面超時問題出現原因及解決辦法HTTP
- 常見php與mysql中文亂碼問題解決辦法PHPMySql
- Ubuntu下Linux配置核心各種常見錯誤和解決辦法UbuntuLinux
- 社交電商系統開發時的常見問題和解決方法
- Windows作業系統常見故障問題和解決方案Windows作業系統
- 【知識分享】伺服器常見異常問題及解決辦法伺服器
- Charls抓包,手機端下載安裝證書常見問題
- 踩坑日誌--CEPH叢集常見問題解決辦法
- 分享視訊直播常見問題與解決辦法彙總
- 粘包問題原因和解決方法
- 資料庫檔案複製問題和解決辦法資料庫
- 常見的反爬手段和解決思路
- CentOS 常見異常及解決辦法CentOS
- 解決 raw.githubusercontent.com 無法訪問的問題Github
- FastReport報表生成器有關COM / ActiveX快速報告常見問題AST
- CentOS6.5安裝mysql以及常見問題的解決CentOSMySql
- 關於$ is not defined的原因和解決辦法
- Oracle 11.2.0.4.0 install for Win10(專業版) 常見問題和解決方法OracleWin10
- web開發技巧-網頁排版佈局常見問題及解決辦法Web網頁
- Kafka常見的問題及解決方案Kafka
- 域名管理常見問題:域名解析不生效的原因和解決方法(中科三方)
- 有關 Android Studio 重複引入包的問題和解決方案Android
- git常見問題解決Git
- As常見問題解決方法
- jupyter安裝常見問題
- 安裝工具常見問題
- 伺服器卡的原因和解決辦法伺服器