C#与VC相互调用之VC调用C#的DLL库

介绍

在之前的博文 C#与VC相互调用之C#调用VC的DLL https://blog.csdn.net/xinxin_2011/article/details/86704660 里面讲了C#程序如何调用VC的DLL,这里我们来介绍VC程序调用C#的DLL。

项目创建

打开VS2010,因为涉及到两个程序,这里先创建一个空的解决方案:
C#与VC相互调用之VC调用C#的DLL库_第1张图片
然后往里面添加一个C#的DLL项目:
C#与VC相互调用之VC调用C#的DLL库_第2张图片
选择“类库”项目模板:
C#与VC相互调用之VC调用C#的DLL库_第3张图片
点击完成后生成如下文件:
C#与VC相互调用之VC调用C#的DLL库_第4张图片
默认生成的是Class1类,我们改名为“CSharpDll”,并添加如下代码:
C#与VC相互调用之VC调用C#的DLL库_第5张图片
接下来再创建一个VC项目,来测试DLL的调用:
C#与VC相互调用之VC调用C#的DLL库_第6张图片
这里创建一个基于对话框的MFC程序:
C#与VC相互调用之VC调用C#的DLL库_第7张图片
点击下一步,只选一个粗框架就可以了:
C#与VC相互调用之VC调用C#的DLL库_第8张图片
继续下一步,只勾选“公共控件清单”即可:
C#与VC相互调用之VC调用C#的DLL库_第9张图片
按照默认的名字生成类文件:
C#与VC相互调用之VC调用C#的DLL库_第10张图片
点击完成后,自动生成如下项目文件:
C#与VC相互调用之VC调用C#的DLL库_第11张图片

编写测试代码

简单修改下VC页面视图:
C#与VC相互调用之VC调用C#的DLL库_第12张图片
其中“调用C#的库”按钮ID为ID_CSHARPDLL_BTN,编辑框的ID为IDC_EDIT_RES。双击按钮,添加处理函数:
C#与VC相互调用之VC调用C#的DLL库_第13张图片
上面代码会有很多划红线的错误,因为用到了gcnew和System::String等公共语言运行库,所以得在项目属性中添加“公共语言运行时支持”:
C#与VC相互调用之VC调用C#的DLL库_第14张图片
此外注意文件上方要添加C#库的引用:

#using "../CSharpLibrary/bin/Debug/CSharpLibrary.dll"

using namespace CSharpLibrary;

这里注意路径的写法,默认当前路径是TestCSharpDll目录,而CSharpLibrary与TestCSharpDll同在一个解决方案目录中,生成的库在CSharpLibrary的bin/Debug目录下,所以这样写。
先别着急编译,因为VC程序要调用DLL必须保证生成的exe和dll文件在同一目录,所以需要改一下VC程序生成exe的路径:
C#与VC相互调用之VC调用C#的DLL库_第15张图片
写好后把把VC程序设置为启动项目:
C#与VC相互调用之VC调用C#的DLL库_第16张图片
设置好之后就可以编译了,成功后生成如下文件:
C#与VC相互调用之VC调用C#的DLL库_第17张图片
看到exe和dll都生成了就可以运行程序进行测试了:
C#与VC相互调用之VC调用C#的DLL库_第18张图片
可以看到VC和dll的交互都正常,如果没出现正确结果,请仔细检查路径设置的是否正确。

细节说明

调用测试完了,有些细节需要说明一下,看代码:

System::String ^proName = gcnew System::String(L"张三");

这里的字符串传参为什么是L"张三"呢?因为用到的是Unicode字符集,前面加上L代码是宽字符,如果对字符集不太了解的,可以参见我之前文章 VS下使用多字符集编码和Unicode字符集编码的总结 https://blog.csdn.net/xinxin_2011/article/details/84985083
顺便再提一下字符串变量转换的时候用到的强制转换:

CString str = (CString)res;

那位说这样强制转换觉得不太安全,那么CString有没有构造函数传参System::String呢?因为是宽字符,所以得看CStringT的源代码,CStringT中有一个传入System String的构造函数:

// This template will compile only for  
// class SystemString == System::String  
  
#if defined(__cplusplus_cli)  
  
    template   
    CStringT( SystemString^ pString ) :  
        CThisSimpleString( StringTraits::GetDefaultManager() )  
    {  
        cli::pin_ptr pChar = PtrToStringChars( pString );  
        const wchar_t *psz = pChar;  
        *this = psz;  
    }  
  
#elif defined(_MANAGED) 

好了,既然有这样的构造函数,我们就可以替代强制转换了,改为如下代码:
C#与VC相互调用之VC调用C#的DLL库_第19张图片

VC调用C#的Dll显示界面

上面只是介绍了简单的字符串传递,那么VC能不能调用C#的Dll中的界面呢?下面来测试一下,在CSharpLibrary项目中添加一个界面类:
C#与VC相互调用之VC调用C#的DLL库_第20张图片
然后编辑窗体视图如下:
C#与VC相互调用之VC调用C#的DLL库_第21张图片
然后修改CSharpDll类,添加调用界面的函数:
C#与VC相互调用之VC调用C#的DLL库_第22张图片
最后在VC的OnBnClickedCsharpdllBtn函数中添加调用的代码:
C#与VC相互调用之VC调用C#的DLL库_第23张图片
看一下运行的结果:
C#与VC相互调用之VC调用C#的DLL库_第24张图片
OK,一切正常。

你可能感兴趣的:(基础知识,C#开发)