本文实例展示了C++与C#互调dll的实现步骤,在进行大型项目共享dll动态链接库中可以用到。具体方法如下:
一、C#调用C++ dll步骤(只能导出方法):
1. c++建立空项目->源文件文件夹中添加cpp文件和函数2. c++属性设置中,配置类型设置为动态库dll,公共语言运行时支持改为/clr3. c#引用c++的dll4. c#声明c++的方法,并添加 DllImport特性5. c#工程属性设置为:目标平台x866. 注意方法的类型匹配7. 引发PInvokeStackImbalance异常:注意:C++的"_declspec"和C#的“CallingConvention=CallingConvention.Cdecl”
另外,可以通过VS的异常窗口,取消掉对 PInvokeStackImbalance异常的检测:
点击VS的“调试 - 异常”,打开异常窗口,展开选择“Managed Debugging Assistants/PInvokeStackImbalance”,去掉对应的“引发”可选框。 二、 c++调用 c# dll的步骤(可直接使用C#类):
1. 创建c++控制台应用程序2. 拷贝c# dll到c++工程根目录3. 工程属性->配置->常规->公共语言运行时支持->clr工程属性->配置->c/c++常规->调试信息格式->zi工程属性->配置->c/c++常规->公共语言运行时支持->clr
?12 | #using "CSharpDllPRoject.dll" using namespace CSharpDllProject; |
三、 c#调用c++类步骤(c++/cli,可直接使用C++类)
c++/cli简介:C++/CLI标准是基于Microsoft提交的标准C++与通用语言基础结构(Common Language Infrastructure)结合的技术1.使用c++/cli语法对标准c++类进行包装(可采用聚合模式,引用标准c++类,实现所有标准c++的方法)2.c#引用c++ dll后,可直接new出一个 c++/cli创建的托管类对象
下面就用一个完整的实例来详细说明怎样用托管C++封装一个C++类以提供给C#使用。
比如,现在有一个工程名为NativeCppDll的由C++编写的DLL,里面输出了一个CPerson类。下面是具体的代码:// NativeCppDll.h#pragma once#ifndef LX_DLL_CLASS_EXPORTS #define LX_DLL_CLASS __declspec(dllexport)#else #define LX_DLL_CLASS __declspec(dllimport)#endifclass LX_DLL_CLASS CPerson{public: CPerson(); CPerson(const wchar_t *pName, const wchar_t cSex, int iAge); void SetName(const wchar_t *pName); wchar_t * GetName(); void SetSex(const wchar_t cSex); wchar_t GetSex(); void SetAge(int iAge); int GetAge(); wchar_t * GetLastError();private: wchar_t m_szName[128]; wchar_t m_cSex; int m_iAge; wchar_t m_szLastError[128]; void ShowError();};// NativeCppDll.cpp#include "stdafx.h"#include "NativeCppDll.h"#include <iostream>#include <tchar.h>using namespace std;CPerson::CPerson(){ wcscpy_s(m_szName, _T("No Name")); m_cSex = 'N'; m_iAge = 0; wcscpy_s(m_szLastError, _T("No Error"));}CPerson::CPerson(const wchar_t *pName, const wchar_t cSex, int iAge){ wcscpy_s(m_szLastError, _T("No Error")); SetName(pName); SetSex(cSex); SetAge(iAge);}void CPerson::SetName(const wchar_t *pName){ if ((pName == NULL) || (wcslen(pName) == 0) || (wcslen(pName) > 127)) { wcscpy_s(m_szName, _T("No Name")); wcscpy_s(m_szLastError, _T("The length of the input name is out of range.")); ShowError(); return; } wcscpy_s(m_szName, pName);}wchar_t * CPerson::GetName(){ return m_szName;}void CPerson::SetSex(const wchar_t cSex){ if ((cSex != 'F')