BCB6 調用C# DLL

最近項目涉及第三方接口調用。第三方是用C#實現的WCF服務。而咱們的程序是使用的BCB6開發。所以,打算將與WCF的通信包含在C#的類庫中,給BCB6調用。BCB6 是沒法直接調用C#的DLL,但能夠經過C#編寫一個COM組件,而後BCB調用這個COM組件來調用。ios

  1. 用C#編寫COM

    大致步驟是c#

    1. 新建一個類庫項目

 

  1. 設置Assemblyinfo.cs

  2. 設置項目屬性

  3. 編寫代碼

using System; ide

using System.Collections.Generic; 函數

using System.Linq; 工具

using System.Text; 測試

using System.Runtime.InteropServices; //1添加Rumtime.InteropServices 程序集引用ui

using System.Windows.Forms; //2爲了演示,因此加入了forms引用spa

 

namespace ComImpTest 命令行

{ debug

[Guid("3CD116D4-18A1-4504-921B-57C053BAD618")] //3主菜單->工具->建立GUID產生

public interface IComInterface //4必須先定義接口

{

[DispId(1)] //5每個函數或者屬性都須要指定DispID

void Hello(string name);

[DispId(2)]

int Add(int x,int y);

[DispId(3)]

string COMINFO{get;}

 

}

 

[Guid("1A8EB38C-E732-49B2-A897-B40FFD744E3D")]

public class ComImp : IComInterface //6編寫一個實現接口的類

{

public void Hello(string name)

{

Console.WriteLine("你好"+name);

MessageBox.Show("你好"+name,"C# dll 彈出界面");

}

 

public int Add(int x, int y)

{

return x + y;

}

 

public string COMINFO

{

get

{

return "com 測試";

}

}

}

}

  1. 編譯獲得DLL 和 TLB

  1. BCB編寫調用
    1. 首先BCB的開發環境中須要安裝.NET FrameWork ,這裏都是用的.NET FrameWork 4.0,安裝以後,

      在如圖的目錄會獲得RegAsm.exe(必定要用安裝後獲得的RegAsm 從其餘地方複製的RegASM可能存在版本不兼容),

      這個在註冊COM的時候要用到。

    2. 創建一個BCB控制檯工程
    3. 吧RegAsm.exe(咱們是爲了註冊方便),前面編譯獲得的 ComImpTest.tlb 、ComImpTest.dll 複製到BCB工程的EXE

      輸出目錄。(這也不是必須的,本質上COM只要能註冊,而後BCB功能能找到TLB建立代理類便可)

    4. 用管理員啓動命令行,註冊ComImpTest.dll

       

      其本質是吧這個COM類註冊到了註冊表中。向系統進行了發佈。

    5. 用BCB 產生代理類

      打開BCB 工程,選擇主菜單 projectàimport type library

       

       

       

      獲得代理類

      包含這個頭文件,咱們就能夠調用了。

       

      可是這裏不知道是BCB的bug,仍是兼容性的問題,BCB產生的ComImp代理類的GUID是錯誤的。

      正確的GUID 應該是編寫C#dll 時產生的Guid

[Guid("1A8EB38C-E732-49B2-A897-B40FFD744E3D")]

 

咱們只須要替換這個Guid便可,若是不這麼作,調用時HRESULT會返回找不到實現接口。

 

 

 

 

  1. BCB 調用COM的代碼
    1. 在控制檯工程中,加入代理類的頭文件 ComImpTest_tlb.h
    2. 代碼以下

//---------------------------------------------------------------------------

#pragma hdrstop

#include <iostream>

#include <vcl.h> //注意,iostream要在 vcl.h 前面定義,不然cout<<AnsiString 報錯

#include "Comimptest_tlb.h"

using namespace std;

//---------------------------------------------------------------------------

 

#pragma argsused

int main(int argc, char* argv[])

{

HRESULT hr;

//初始化COM

CoInitialize ( NULL );

//建立智能指針命名空間在頭文件Comimptest_tlb.h中能夠查找到

//接口智能指針的定義也能查找到

    Comimptest_tlb::IComInterfacePtr ptr;

 

//建立實例,ComImp 的聲明,也能在頭文件中查找到。

    hr = ptr.CreateInstance(__uuidof (Comimptest_tlb::ComImp));

      

if(hr == S_OK)

{

//調用ADD方法

cout << ptr->Add (1, 2)<<endl;

//調用Hello方法,在bcbWidestring 對應 c# string

WideString name = "Zakk wylde 奧茲";

        ptr->Hello(name.c_bstr());

//調用COMINFO屬性,這裏COM進行了名字改變,這些函數均可以在頭文件中查到原型定義。

BSTR outp = NULL;

ptr->get_COMINFO(&outp);

//由於是寬字符,因此要轉換爲AnsiString進行輸出

cout<<AnsiString(outp)<<endl;

}

 

CoUninitialize ();

system("pause");

return 0;

}

 

 

 

 

4 用vc調用COM

用VC調用C#的COM 就沒有這麼多事情。下面是VC調用的代碼,

將ComImpTest.tlb 和 ComImpTest.dll 拷貝到 VC工程的debug目錄下。而後用import指令(BCB 沒法用import識別,估計是不兼容)

// testCOM3.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;
#import "../debug/ComImpTest.tlb"

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr;
 //初始化COM
    CoInitialize ( NULL );   
    //建立智能指針
    ComImpTest::IComInterfacePtr ptr;

    //建立實例
    hr = ptr.CreateInstance(__uuidof (ComImpTest::ComImp));
     
    if(hr == S_OK)
    {
        cout << ptr->Add (1,2)<<endl;
        ptr->Hello(L"VC++ 調用");
        cout<<ptr->COMINFO<<endl;
    }        

    CoUninitialize (); 
    system("pause");
    return 0;
}


//---------------------------------------------------------------------------
相關文章
相關標籤/搜索