一. 關(guān)于從 C# 客戶端調(diào)用 C++ 非托管代碼的方法.
本文不打算敘述, 參看以下文章.
http://www.codeproject.com/KB/cs/cominterop.aspx
二. 關(guān)于從 C++ 客戶端調(diào)用 C# 托管代碼的方法.
(一). 非常直接的方法, 參看這篇文章.
http://www.codeproject.com/KB/cs/unmanagedtomanaged.aspx
源代碼下載 http://www.shnenglu.com/Files/free2000fly/cpp-call-cs.zip
(二). 我們的方法. 這里主要講我們的方法. 這里只講實現(xiàn)過程, 不講原理.
1. C# 實現(xiàn)的組件
(1). 打開 VS 2008, 然后新建一個 C# 工程, 類型是 windows 的 class library, 工程名為 MyTestClsLib.
見下圖 [--圖1--]

(2). 打開 class1.cs 文件, 在 using System.Text; 語句后面添加語句
using System.Runtime.InteropServices;
(3). 將 public class Class1 類名改為更好認的, 如 SimpleType.
(4). 在類 SimpleType 類頭頂添加類接口屬性 [ClassInterface(ClassInterfaceType.AutoDual)]
以上三步見下圖 [--圖2--]

(5). 在 SimpleType 類內(nèi)部添加函數(shù).
public string ConvertIntToString(int n)
{
return n.ToString();
}
(6). 打開工程的 AssemblyInfo.cs 文件, 將語句
[assembly: ComVisible(false)]
改為
[assembly: ComVisible(true)]
(7). 打開工程的 "屬性(properties)" 對話框. 選中 build 選項卡, 在這一頁的最下邊勾選 "Register for COM interop" 檢查框.
見下圖 [--圖3--]

(8). 編譯這個工程, 如果一切順利, 將在 bin\debug\ 目錄下生成目標文件 MyTestClsLib.dll 和 MyTestClsLib.tlb 文件.
至此, C# 組件開發(fā)完畢. 通過查看注冊表,可以看到增添了如下內(nèi)容:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\CLSID\{E57F961E-9925-3025-A854-AF3E4B7C0801}]
@="MyTestClsLib.SimpleType"
[HKEY_CLASSES_ROOT\CLSID\{E57F961E-9925-3025-A854-AF3E4B7C0801}\Implemented Categories]
[HKEY_CLASSES_ROOT\CLSID\{E57F961E-9925-3025-A854-AF3E4B7C0801}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}]
[HKEY_CLASSES_ROOT\CLSID\{E57F961E-9925-3025-A854-AF3E4B7C0801}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="both"
"Class"="MyTestClsLib.SimpleType"
"Assembly"="MyTestClsLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
"RuntimeVersion"="v2.0.50727"
"CodeBase"="file:///E:/WUTemp/MyTestClsLib/bin/Debug/MyTestClsLib.dll"
[HKEY_CLASSES_ROOT\CLSID\{E57F961E-9925-3025-A854-AF3E4B7C0801}\InprocServer32\1.0.0.0]
"Class"="MyTestClsLib.SimpleType"
"Assembly"="MyTestClsLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
"RuntimeVersion"="v2.0.50727"
"CodeBase"="file:///E:/WUTemp/MyTestClsLib/bin/Debug/MyTestClsLib.dll"
[HKEY_CLASSES_ROOT\CLSID\{E57F961E-9925-3025-A854-AF3E4B7C0801}\ProgId]
@="MyTestClsLib.SimpleType"
[HKEY_CLASSES_ROOT\MyTestClsLib.SimpleType]
@="MyTestClsLib.SimpleType"
[HKEY_CLASSES_ROOT\MyTestClsLib.SimpleType\CLSID]
@="{E57F961E-9925-3025-A854-AF3E4B7C0801}"
2. C++ 客戶端的例子.
(1). 新建一個 C++ 控制臺程序, 工程名字是 TestClient, 見下圖 [--圖4--] .

(2). 在包含文件 stdafx.h 內(nèi)添加
#include <windows.h>
#include <atlbase.h>
(3). 在 TestClient.cpp 文件添加如下內(nèi)容.
#import "..\MyTestClsLib\bin\Debug\MyTestClsLib.tlb" raw_interfaces_only
using namespace MyTestClsLib;
(4). 隨便聲明一個函數(shù)并實現(xiàn)之, 比如 void Foo(void); 在這個函數(shù)體內(nèi)就可以調(diào)用我們先前實現(xiàn)的 C# 組件了.
比如這些代碼:
void Foo(void)
{
HRESULT hr = E_FAIL;
CComPtr<_SimpleType> spTmp;
hr = spTmp.CoCreateInstance(__uuidof(SimpleType));
if (SUCCEEDED(hr))
{
CComBSTR str;
spTmp->ConvertIntToString(887, &str);
}
}
(5). 然后在 main 函數(shù)里就可以調(diào)用 Foo 函數(shù)了, 調(diào)用之前記得初始化 COM 環(huán)境. 見下圖 [--圖5--] .

(6). 到此, 打完收工. 現(xiàn)在, 就可以編譯調(diào)試看看效果了. 看看 CComBSTR str 變量里是不是有了返回值 887?
例子代碼下載: http://www.shnenglu.com/Files/free2000fly/cstocpptest.zip
另一個例子, 用 C++ 的 ATL 定義接口, 然后用 C# 實現(xiàn)接口. 然后用 C++ 客戶端來調(diào)用之. http://www.shnenglu.com/Files/free2000fly/com2cs-impl.zip
參考資料:
(1) http://www.codeproject.com/KB/cs/ManagedCOM.aspx
(2) http://www.codeproject.com/KB/COM/cominterop.aspx
(3) http://www.codeproject.com/KB/cs/cominterop.aspx
(4) http://blogs.msdn.com/yizhang/archive/2007/11/05/net-mscoree-dll.aspx
(5) http://www.codeproject.com/KB/cs/unmanagedtomanaged.aspx
posted on 2009-03-23 16:02
free2000fly 閱讀(6748)
評論(11) 編輯 收藏 引用