多年來 COM 物件一直是 Windows 編程的基礎,不可避免的是,在向.NET過渡時,還是需要繼續使用現有的COM對象。“互通性封送處理”是一個打包過程,在將參數和傳回值移動到 COM 物件或從 COM 物件移出時,此過程將這些參數和傳回值打包為等價的資料類型。
公用語言運行庫通過名為運行庫可調用封裝 (Runtime Callable Wrapper,RCW) 的代理來公開 COM 物件。雖然 RCW 在 .NET 用戶端看來是普通的對象,但它的主要功能是封送在 .NET 用戶端和 COM 物件之間傳遞的調用。同時.NET提供Interop 程式集,它用作託管和Unmanaged 程式碼之間的橋樑,將 COM 物件成員映射為等價的 .NET 託管成員。
下面介紹採用VC++6.0與VS2005(C#)編寫的DLL/COM的各種調用方法
1. VC編寫的DLL在VC中調用
(1)VC編寫DLL程式
建立"Win32 Dynamic-Link Library"工程->"一個可以匯出某些符號的DLL工程"->完成
添加變數、函數、類
#ifdef MYVCDLL_EXPORTS
#define MYVCDLL_API __declspec(dllexport)
#else
#define MYVCDLL_API __declspec(dllimport)
#endif
////////自訂函數/////////
MYVCDLL_API bool myFunction(void);
////////自訂變數/////////
extern MYVCDLL_API int myVar;
////////自訂類///////////
class MYVCDLL_API MyCCalculator
{
public:
int subtract(int a, int b);
int add(int a, int b);
MyCCalculator();
virtual ~MyCCalculator();
};
(2)VC編寫DLL調用程式
#include "stdafx.h"
#include "MyVcDll\MyVcDll.h"
#include "MyVcDll\MyCCalculator.h"
#pragma comment(lib, "MyVcDll\\Debug\\MyVcDll.lib")
int main(int argc, char* argv[])
{
// 調用DLL變數
printf("調用的DLL中的變數的值為:%d\n\n", myVar);
// 調用DLL函數
printf("調用的DLL中的函數MyFunction()的傳回值為:%d\n\n", myFunction());
// 調用DLL類
MyCCalculator myCal;
printf("調用DLL中計算類執行加法:%d+%d=%d\n\n", 5, 3, myCal.add(5, 3));
printf("調用DLL中計算類執行減法:%d-%d=%d\n\n", 5, 3, myCal.subtract(5, 3));
printf("End!\n");
return 0;
}
2. VC編寫的COM在VC中調用
(1)VC編寫COM程式
建立"ALT COM AppWizard"工程->"動態連結程式庫(DLL)"->完成
"New ALT Object..."->"Simple Object"
"Add Method..."->add([in] int a, [in] int b, [out] int result)
"Add Method..."->subtract([in] int a, [in] int b, [out] int result)
組建工程,註冊COM
(2)VC編寫COM調用程式
#include "stdafx.h"
#include "MyVcCom\MyVcCom.h"
#include "MyVcCom\MyVcCom_i.c"
int main(int argc, char* argv[])
{
// 聲明 HRESULT 和 IMyCalculator 介面指標
HRESULT hr;
IMyCalculator *IMyCal = NULL;
// 初始化 COM
hr = CoInitialize(0);
// 使用 SUCCEEDED 宏並檢查是否能得到一個介面指標
if(SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_MyCalculator, NULL, CLSCTX_INPROC_SERVER,
IID_IMyCalculator, (void**) &IMyCal);
// 如果成功,則調用 add 方法,否則顯示相應的出錯資訊
if(SUCCEEDED(hr))
{
int result;
IMyCal->add(5, 3, &result);
printf("Call Com MyCalculator Add Method : 5 + 3 = %d\n\n", result);
IMyCal->subtract(5, 3, &result);
printf("Call Com MyCalculator Subtract Method : 5 - 3 = %d\n\n", result);
IMyCal->Release();
}
else
{
printf("CoCreateInstance Failed!\n\n");
}
}
// 釋放 COM
CoUninitialize();
printf("Programe End!\n");
return 0;
}
3. VC編寫的DLL在VS中調用
(1)VC編寫DLL程式
建立"Win32 Dynamic-Link Library"工程->"一個可以匯出某些符號的DLL工程"->完成
添加函數
#ifdef MYVCDLL_EXPORTS
#define MYVCDLL_API __declspec(dllexport)
#else
#define MYVCDLL_API __declspec(dllimport)
#endif
//////////////自訂函數////////////
extern "C" MYVCDLL_API char* myFunction1(void);
extern "C" MYVCDLL_API int myFunction2(void);
(2)VS編寫DLL調用程式
將VC編寫的DLL檔案拷貝到,VS調用程式的Debug目錄下
using System.Runtime.InteropServices;
[DllImport("MyVcDll.dll")]
unsafe static extern char* myFunction1();
[DllImport("MyVcDll.dll")]
static extern int myFunction2();
註:在項目屬性 "產生"->"允許不安全的程式碼" 打勾
4. VC編寫的COM在VS中調用
(1)VC編寫COM程式
建立"ALT COM AppWizard"工程->"動態連結程式庫(DLL)"->完成
"New ALT Object..."->"Simple Object"
"Add Method..."->add([in] int a, [in] int b, [out] int result)
"Add Method..."->subtract([in] int a, [in] int b, [out] int result)
組建工程,註冊COM
(2)VS編寫COM調用程式
在"項目"->"引用", 尋找並添加註冊的"COM"
using MYVCCOMLib;
MyCalculator myCal = new MyCalculator();
int result;
myCal.add(5, 3, out result);
MessageBox.Show(string.Format("{0}+{1}={2}", 5, 3, result));
5. VS編寫的COM在VC中調用
(1)VS編寫COM程式
建立"工程"->"類庫"
"項目屬性"->"產生"->"為 COM Interop 註冊" 打勾
修改"AssemblyInfo.cs"->"[assembly: ComVisible(true)]"
using System.Runtime.InteropServices;
// 介面
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("4C0C5188-83EC-4f52-8DBD-DFC3732CF8DE")]
public interface IMyCalculator
{
[DispId(1)]
int Add(int a, int b);
[DispId(2)]
int Substract(int a, int b);
}
// 類
[ProgId("MyCalculator.DotNet")]
[ClassInterface(ClassInterfaceType.None)]
[Guid("FB17DD89-9BF9-431a-9620-705F7D3E9AFB")]
public class MyCalculator : IMyCalculator
{
public int Add(int a, int b)
{
return a + b;
}
public int Substract(int a, int b)
{
return a - b;
}
}
(2)VC編寫COM調用程式
拷貝COM的DLL的.tlb檔案到工程目錄
#include "stdafx.h"
// 1. 匯入類型庫tlb
#import "MyVsCom.tlb"
using namespace MyVsCom;
int main(int argc, char* argv[])
{
// 2. 初始化COM
CoInitialize(NULL); //NULL換成0也可以
// 3. 產生智能指標 -- 名字空間::介面Ptr pObject((__uuidof(名字空間::類)))
MyVsCom::IMyCalculatorPtr pCal((__uuidof(MyVsCom::MyCalculator)));
// 4. 調用COM中的方法
int result = pCal->Add(5, 3);
printf("調用VS(C#)編寫的COM的類方法: %d+%d=%d\n\n", 5, 3, result);
result = pCal->Substract(5, 3);
printf("調用VS(C#)編寫的COM的類方法: %d-%d=%d\n\n", 5, 3, result);
// 5. 釋放環境
CoUninitialize();
printf("Programe End!\n");
return 0;
}