本文實例展示了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')