• 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()来应付一下。

    就写到这里了,还有很多不懂得,请多多指正!

  • 相关阅读:
    ACM: SCU 4440 Rectangle
    ACM: NBUT 1646 Internet of Lights and Switches
    ACM: Long Live the Queen
    ACM: Racing Gems
    C++ 11 笔记 (一) : lambda
    cocos2d-x笔记2: 编译到安卓的步骤与注意事项
    C++笔记1: 单例模式。(一个简单的设计模式在C++中复杂出翔。。)
    Java笔记2 : 泛型的体现,及其上限、下限、通配符
    我终于忍不住喷一下某些书了,关于Java传引用的XX言论
    Java笔记1 : 在生产者消费者模式中,线程通信与共享数据,死锁问题与解决办法
  • 原文地址:https://www.cnblogs.com/deliver/p/2808959.html
Copyright © 2020-2023  润新知