C#封装动态库,提供给C++调用

1, 首先封装一个C# Dll, 即创建工程为C#类库;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace MyCharpDll
{
    [ComVisible(true)]
    [Guid("0CE96C54-CC5F-47A6-BD21-C2635CEDC2D8")]
    public interface IMyCSharp    // 接口
    {
        [DispId(1)]
        string CombinString(string str1, string str2, out string outstr);
    }

    [ComVisible(true)]
    [Guid("56209E46-A605-492F-AA50-9D6608116181")]
    [ClassInterface(ClassInterfaceType.None)]
    public class MyCSharp : IMyCSharp // 实现类继承接口
    {
        public string CombinString(string str1, string str2, out string outstr)
        {
            outstr = str1 + str2;
            return outstr;
        }
    }
}

1) 工程->属性->应用程序->程序集信息...  弹出对话框, 勾选 "使程序集COM可见";
2) 工程->属性->生成  勾选 "为COM互操作注册"; (在其他机器上运行, 则要手动将dll注册为COM)
(3) 在这里我们通过regasm.exe生成注册表文件供使用者将dll注册为
COM组件(其实就是把GUID导入注册表)。
脚本文件如下:
regasm E:\UnmanagecodeCallManagecode\CalcClass\CalcClass\bin\Debug\CalcClass.dll
regasm E:\UnmanagecodeCallManagecode\CalcClass\CalcClass\bin\Debug\CalcClass.dll /tlb: CalcClass.tlb
regasm E:\UnmanagecodeCallManagecode\CalcClass\CalcClass\bin\Debug\CalcClass.dll /regfile: CalcClass.reg
注意使用的regasm.exe版本与开发dll所使用的.NET Framework版本最好保持一致。
运行该脚本生成CalcClass.reg文件。在其他机器上运行该文件,即可注册该COM组件,才能正常使用

注册DLLD脚本
@echo off
@echo on
RegAsm.exe  LanJiaoSharpDll.dll
pause

注销DLL脚本
@echo off
@echo on
RegAsm.exe  LanJiaoSharpDll.dll /u
pause


2, VC++调用C# Dll

#include
#include
#import "MyCharpDll.tlb"
using namespace std;
using namespace MyCharpDll;

void main()
{
    CoInitialize(NULL);
    IMyCSharpPtr myCSharpPtr;
    myCSharpPtr.CreateInstance(__uuidof(MyCSharp));
    if (myCSharpPtr != NULL)
    {
        char *pStr1 = "你好--";
        char* pStr2 = "欢迎光临";
        char szOut[256];
        BSTR temp;
        memset(szOut, 0, sizeof(szOut));
        myCSharpPtr->CombinString(_bstr_t(pStr1), _bstr_t(pStr2), &temp);
       char* pchar = _com_util::ConvertBSTRToString(temp); 
        strcpy_s(szOut, sizeof(szOut), pchar );
        delete[] pchar;  // 否则内存泄露
        cout << szOut << endl;
        myCSharpPtr.Release();
    }
    else
        cout << "创建接口失败" << endl;
    CoUninitialize();
}

3, VC对C# Dll再次封装

头文件:
#define CSharpDll_Export
#ifdef CSharpDll_Export
#define CSharpDllApi    __declspec(dllexport)
#else
#define CSharpDllApi    __declspec(dllimport)
#endif

extern "C" CSharpDllApi bool CombinString(char* pStr1, char* pStr2, char* pOut);

源文件:

#include "CSharpDll.h"
#include
#import "MyCharpDll.tlb"
using namespace MyCharpDll;

bool CombinString(char* pStr1, char* pStr2, char* pOut)
{
    bool bRet = false;
    CoInitialize(NULL);
    IMyCSharpPtr myCSharpPtr;
    myCSharpPtr.CreateInstance(__uuidof(MyCSharp));
    if (myCSharpPtr != NULL)
    {
        BSTR temp;
        myCSharpPtr->CombinString(_bstr_t(pStr1), _bstr_t(pStr2), &temp);
        strcpy(pOut, _com_util::ConvertBSTRToString(temp));
        myCSharpPtr.Release();
        bRet = true;
    }
    else
        bRet = false;
    CoUninitialize();
    return bRet;
}


4, 外部调用

#include
#include
#include "CSharpDll.h"
#pragma comment(lib, "CSharpDll.lib")  // 这时候只需 CSharpDll.dll 文件, 因为C# DLL已经注册为COM

void main()
{
    char* pStr1 = "这是CSharp编写的DLL ";
    char* pStr2 = "该DLL提供了一个字符创拼接函数";
    char szOut[256];
    memset(szOut, 0, sizeof(szOut));
    if ( CombinString(pStr1, pStr2, szOut) )
    {
        printf("调用成功: %s\n", szOut);
    }
    else
        printf("调用失败\n");
    getchar();
}

你可能感兴趣的:(Windows编程,c#,c++,开发语言)