BCB6 调用C# DLL

BCB6 调用C# DLL

最近项目涉及第三方接口调用。第三方是用C#实现的WCF服务。而我们的程序是使用的BCB6开发。因此,打算将与WCF的通讯包含在C#的类库中,给BCB6调用。BCB6 是无法直接调用C#的DLL,但可以通过C#编写一个COM组件,然后BCB调用这个COM组件来调用。

  1. 用C#编写COM

    大体步骤是

    1. 新建一个类库项目

 

  1. 设置Assemblyinfo.cs

  2. 设置项目属性

  3. 编写代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

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

using System.Windows.Forms;//2为了演示,所以加入了forms引用

 

namespace ComImpTest

{

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

publicinterfaceIComInterface//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")]

publicclassComImp :IComInterface//6编写一个实现接口的类

{

publicvoid Hello(string name)

{

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

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

}

 

publicint Add(int x,int y)

{

return x + y;

}

 

publicstring 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. 代码如下

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

#pragmahdrstop

#include<iostream>

#include<vcl.h>//注意,iostream要在 vcl.h前面定义,否则cout<<AnsiString报错

#include"Comimptest_tlb.h"

usingnamespace 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;
}


//---------------------------------------------------------------------------
复制代码

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值