C#通過COM組件調用C++的代碼


這個主題在《c#高級編程》中有提到,可以下本電子書來看看。一下我也列出自己的學習筆記。

根據網上的說法,C#調用C++至少有以下幾種方法:

1通過COM組件調用

2通過MC++轉接

3利用Intptr

 

由於我只能成功使用COM組件的方法,所以下面只談一下這個方法。

 

一.通過ALT建立COM組件

1、創建ATL Project

步驟1:建立一個解決方案。   步驟2:在 該解決方案中,新建一個 vc++ 的 ATL 項目。見下圖

選擇Dynamic-link library(DLL)

2、向工程中添加ATL對象

選擇ATL Simple Object

名字為FunTest

Interface選擇Custom

3、在接口中添加方法.(在類視圖中)

方法名為Sum,參數如下圖,有三個參數

 

接口方法的實現, 這個太簡單了

STDMETHODIMP CFunTest::Sum(LONG num1, LONG num2, LONG* pVal) 
{ 
    // TODO: Add your implementation code here 
    *pVal = num1 + num2; 
    return S_OK; 
}

 

二.在C#中調用COM組件

1、新建一個C# console項目,比如叫Test(winform的也是一樣道理,只是Console調試更方便而已。第一次在C#中調用COM組件時,建議先用Console試試,否則會搞得一頭煙)

2、添加引用:

在彈出的對話框中選COM子頁,找到ATLProjectTest 1.0類型庫(或類似的東西)

就會發現在Test->引用下多了ATLProjectTestLib

3在主函數(program.cs)中調用組件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ATLProjectTestLib;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            ATLProjectTestLib.FunTestClass f1 = new FunTestClass();
            Console.Write (f1.Sum(3,4)); 
        }
    } 
}

 

三.很多的細節及注意事項

僅按上面一步步地操作下來發現還會出錯,會說找不到XX COM組件,或是COM組件沒注冊。實際上很多不當操作都會導致上面這個錯誤。只有當你生成的文件中有Interop.ATLProjectTestLib.dll時,你才算成功了。

1、所有修改都要重新編譯。如修改了ATL項目,首先要重新編譯ATL,再重新編譯C# project。當把項目移到另一台計算機,有時編譯器由於ATL項目沒有被修改,而不會重新編譯,這就無法寫注冊表。這時可以把ATL項目的Debug文件夾刪除,再重新編譯。

2、在創建ATL project時,由於一個選Dual或Custom的地方,我認為應該選Dual,但網上較多文章選Custom。

以下是選了Custom后應做的補救,

回到ATLProjectTest,在ATLProjectTest.idl中(或雙擊 類視圖->IFunTest)

import "oaidl.idl";
import "ocidl.idl";

[
    object,
    uuid(90477521-7218-4CA1-AADC-EAF3C42AB24B),
    dual, //--------按原做法不設這個屬性,只有設了這個屬性才不會錯 
    helpstring("IFunTest 接口"),
    pointer_default(unique)
]

 

3、ATL默認按32位編譯,而C#中一般是按any CPU形式,像我是64位機的就要小心了。要改一下C#項目中的生成規則。

點擊項目的屬性頁:

設置目標平台為x86

4、做完上面這3點,大概Test應該能運行了。可以先跳到第四大點看完后再倒回來。

在實際的工程中,一般有很多個項目,假設以C#項目為主,還有一個ATL項目ATLProjectTest。而這個ATLProjectTest被Business項目(邏輯層)調用,而Business又被Form項目(用戶層)調用,這都是很常見的。

在“編譯”時就不能直接啟動調試,要按ATLProjectTest->Business->Form的順序一個個地生成項目。

5、有時會因為找不到Interop.ATLProjectTestLib.dll而出錯,可以試着把各個項目的輸出路徑都改到同一個文件夾(如用戶層工程的文件夾)。

四.更具體的編程

ATL與C#類型對應

ATL

C#

LONG

int

DOUBLE

double

CHAR

sbyte

VARIANT_BOOL

bool

BSTR

string

*

ref

在C++中更多用STL string來寫

BSTR與STL string的轉化方法

#include <iostream> #include <string> 
#include<comutil.h> #pragma comment(lib,"comsuppw") 

using namespace std; 

string str;             //STL string

BSTR bs;

bs = _com_util::ConvertStringToBSTR(str.c_str()); 

str = _com_util::ConvertBSTRToString(bs);

 

解決了字符串的問題數組和對象都好辦,因為可以序列化。

有關構造函數和析構函數我還不太會怎么做,但可以自定義Init()和ToEnd()來應付一下。

就寫到這里了,還有很多不懂得,請多多指正!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM