最近项目涉及第三方接口调用。第三方是用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产生

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方法,在bcb中Widestring 对应 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 (,)<<endl;
ptr->Hello(L"VC++ 调用");
cout<<ptr->COMINFO<<endl;
} CoUninitialize ();
system("pause");
return ;
} //---------------------------------------------------------------------------

BCB6 调用C# DLL的更多相关文章

  1. c# 调用c++DLL方法及注意事项

    引用命名空间 using System.Runtime.InteropServices 调用方法: 一.静态加载 用DllImprot方式来加载c++DLL.如下格式: //对应c++方法 //voi ...

  2. 在.net中调用Delphi dll的Pchar转换

    Pchar是非托管代码,要在.net中调用Delphi dll中的功能,请使用MarshalAs属性告知.net调用PInvoke去转换.net中标准的string类型.如果Delphi dll是De ...

  3. Java调用第三方dll文件的使用方法 System.load()或System.loadLibrary()

    Java调用第三方dll文件的使用方法 public class OtherAdapter { static { //System.loadLibrary("Connector") ...

  4. C#调用C++ DLL类方法

    C++的优势在于高效灵活,C#的优势在于简单易用,两者结合起来对项目开发来说是件好事,而且C++不容易反编译,也保障了代码的安全性,如果一些核心算法使用C#编写,那么保密就是一个问题. C++生成的D ...

  5. paip.java 调用c++ dll so总结

    paip.java 调用c++ dll so总结 ///////JNA (这个ms sun 的) 我目前正做着一个相关的项目,说白了JNA就是JNI的替代品,以前用JNI需要编译一层中间库,现在JNA ...

  6. C#调用C++ DLL 文件

    说来惭愧,都注册一年多了,却没有发表过一篇正式的博文,中间很多学习的过程也没有记录下来.如今到了一个新的环境,也有了学习的机会,一定要把每天的收获记录一下. 要做的东西需要引用C++编写的DLL,刚开 ...

  7. LR调用动态链接库DLL

    什么是动态库? 动态库一般又叫动态链接库(DLL),是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库. 动态链接提供了一种方法 ,使进程可以 ...

  8. C#调用C++ Dll

    现在项目基本都是旁边C++的哥们做好dll扔给我,然后我调用.好久之前晚上down了一份c#调用c++dll的方法,出处早已经遗忘.闲来无事,放上来好了.原作者看到后可以留言,我会把您链接放上的,帮了 ...

  9. 【JNI】OPUS压缩与解压的JNI调用(.DLL版本)

    OPUS压缩与解压的JNI调用(.DLL版本) 一.写在开头: 理论上讲,这是我在博客园的第一篇原创的博客,之前也一直想找个地方写点东西,把最近做的一些东西归纳总结下,但是一般工程做完了一高兴就把东西 ...

随机推荐

  1. 安装LoadRunner各种提示解决方法(转载)

    原文地址链接:https://jingyan.baidu.com/article/915fc414fc60fc51394b20fa.html 1.问:当安装提示"Micosoft Visua ...

  2. 20190722java学习习惯小结

    1.周一——周六: 学习: 周日: 巩固练习测试. 2.java 大数据. python 人工智能 .. 3.写技术博客! 4.python应用: 人工智能.web开发.自动化运维.数据分析.爬虫.游 ...

  3. C++编译器、链接器工作原理

    1 几个基本概念 编译:编译器对源文件的编译过程,就是将源文件中的文本形式代码翻译为机器语言形式的目标文件的过程,此过程中会有一系列语法检查.指令优化等,生成目标(OBJ)文件. 编译单元:每一个CP ...

  4. 工作总结--CTO(张王岩)File的使用

    名称     路径分隔符 pathSeparator   separator 构造器 文件名.路径名 getName()  getPath() getAbsolutePath()  getParent ...

  5. The request was aborted: Could not create SSL/TLS secure channel

    一.背景: 公司底层服务CDN从Akamai迁移到阿里云之后, 使用该服务的一个应用报错如下: System.AggregateException: One or more errors occurr ...

  6. Netty中两种Keepalive的区别

    在Server端开启TCP keepalive: 两种方式 serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); serverB ...

  7. 剑指offer15:反转链表后,输出新链表的表头。

    1 题目描述 输入一个链表,反转链表后,输出新链表的表头. 2 思路和方法 (1)利用栈作为中间存储,进行链表的反转,将压入的数据按先进后出的顺序弹出依次赋给链表再输出表头pHead. (2)将当前节 ...

  8. 模块 os 和 sys

    目录 os 模块 sys 模块 os 模块 os 模块是与操作系统交互的一个接口 方法 详解 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir(&quo ...

  9. scratch少儿编程第一季——04、想要做到有的放矢,瞄准方向很重要

    各位小伙伴大家好: 上期我们学习了动作模块的前面三个指令,今天我们继续学习下面的5个指令. 首先来看第一个(控制方向): 面向90方向默认就是屏幕的右边. 点击白色文本框上面的▼可以打开下拉菜单. 大 ...

  10. Array Beauty CodeForces - 1189F (dp,好题)

    大意: 定义$n$元素序列$a$的美丽度为 $\min\limits_{1\le i<j\le n}|a_i-a_j|$. 给定序列$a$, 求$a$的所有长为$k$的子序列的美丽度之和. 记 ...