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 <iostream> #include <string.h> #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); ?? ??? ?strcpy_s(szOut, sizeof(szOut), _com_util::ConvertBSTRToString(temp)); ?? ??? ?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 <string.h> #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 <stdio.h> #include <STRING.H> #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(); }
|