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();
}