国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++與C#互調dll的實現步驟

2019-11-08 18:24:42
字體:
來源:轉載
供稿:網友

本文實例展示了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"usingnamespace 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') && (cSex != 'M') && (cSex != 'm') && (cSex != 'f'))           m_cSex 'N';        wcscpy_s(m_szLastError, _T("The input sex is out of [F/M]."));        ShowError();                return;       m_cSex cSex;}wchar_t CPerson::GetSex(){    return m_cSex;}void CPerson::SetAge(int iAge){    if ((iAge 0) || (iAge 150))           m_iAge 0;        wcscpy_s(m_szLastError, _T("The input age is out of range."));        ShowError();        return;       m_iAge iAge;}int CPerson::GetAge(){    return m_iAge;}wchar_t CPerson::GetLastError(){    return m_szLastError;}void CPerson::ShowError(){    cerr << m_szLastError << endl;}

   這是一個很典型的由C++開發的DLL,輸出一個完整的C++類。如果現在要求開發一個C#工程,需要用到這個DLL中輸出的C++類CPerson,該怎么辦呢?針對這個例子來說,類CPerson非常小,可以用C#重新寫一個跟這個C++類一樣的類。可是,如果需要的C++類很大,或者很多的時候,重寫工程將非常龐大。而且這樣沒有對現有的代碼進行重用,浪費了現有資源,開發起來費時費力。   當然,還是有方法解決這個問題的。那就是用托管C++將C++類給封裝一下,然后再提供給C#來使用。下面就用代碼來詳細說明怎樣用托管C++來封裝上面的那個C++類。   首先,要創建一個托管C++的DLL工程ManageCppDll,然后在里面添加下面的代碼:   

// ManageCppDll.h#pragma once#define LX_DLL_CLASS_EXPORTS#include "../NativeCppDll/NativeCppDll.h"using namespace System;namespace ManageCppDll    public ref class Person       // 包裝所有類CPerson的公有成員函數    public:        Person();        Person(String strName, Char cSex, int iAge);        ~Person();        property String Name                   void set(String strName);            String get();               property Char Sex                   void set(Char cSex);            Char get();               property int Age                   void set(int iAge);            int get();               String GetLastError();    private:        // 類CPerson的指針,用來調用類CPerson的成員函數        CPerson *m_pImp;    };};

   從這個頭文件就能看出來,這是對C++類CPerson的包裝。類Person的所有公有成員函數都跟C++類CPerson一樣,只不過成員函數的參數和返回值就改成了托管C++的類型,這也是讓類Person能在C#中使用的首要條件。當然只需要對公有成員函數進行封裝,對于保護成員函數和私有成員函數則不必做任何封裝。   類Person僅有一個私有的成員變量:一個類CPerson的指針。而類Person的所有成員函數的實現都是靠這個CPerson指針來調用類CPerson的相應成員函數來實現。   下面是具體的實現代碼:

// ManageCppDll.cpp#include "stdafx.h"#include "ManageCppDll.h"#include <vcclr.h>namespace ManageCppDll    // 在構造函數中創建類CPerson的對象并在析構函數中將該對象銷毀    // 所有的成員函數實現都是通過指針m_pImp調用類CPerson的相應成員函數實現    Person::Person()           m_pImp new CPerson();       Person::Person(String strName, Char cSex, int iAge)           // 將string轉換成C++能識別的指針        pin_ptr<const wchar_t> wcName PtrToStringChars(strName);        m_pImp new CPerson(wcName, cSex, iAge);       Person::~Person()           // 在析構函數中刪除CPerson對象        delete m_pImp;       void Person::Name::set(String strName)           pin_ptr<const wchar_t> wcName PtrToStringChars(strName);        m_pImp->SetName(wcName);       String Person::Name::get()           return gcnew String(m_pImp->GetName());       void Person::Sex::set(Char cSex)           m_pImp->SetSex(cSex);       Char Person::Sex::get()           return m_pImp->GetSex();       void Person::Age::set(int iAge)           m_pImp->SetAge(iAge);       int  Person::Age::get()           return m_pImp->GetAge();       String Person::GetLastError()           return gcnew String(m_pImp->GetLastError());    }};

   如果要在C#中使用類Person,首先要添加對ManageCppDll.dll的引用,然后就可以像用普通的C#類一樣的使用類Person了。比如下面這樣的代碼:

using ManageCppDll;Person person new Person();person.Name "StarLee";person.Sex 'M';person.Age 28;

   熟悉設計模式的看了上面的代碼肯定會發現,這樣的設計跟BRIDGE模式如出一轍。其實,上面的方法也算是一種BRIDGE模式,由托管C++充當了C#中使用用C++開發的類的橋梁。另外,這種形式也可以理解為ADAPTER模式,托管C++類Person就是C++類CPerson的一個適配器。通過這個橋梁,可以很容易的重用以前用C++開發的類,讓這些C++類繼續在C#中發揮它們的效用,讓開發變得事半功倍。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 兴和县| 江川县| 边坝县| 大同市| 河西区| 攀枝花市| 临夏县| 宣武区| 信宜市| 兴海县| 大安市| 抚松县| 涞水县| 青田县| 高安市| 德州市| 绥芬河市| 阆中市| 漯河市| 武功县| 广水市| 库尔勒市| 盈江县| 灌南县| 祁门县| 夹江县| 仁布县| 昌黎县| 和林格尔县| 迁安市| 佛坪县| 辽宁省| 洛阳市| 小金县| 花莲市| 西丰县| 莲花县| 威宁| 武安市| 安庆市| 临沭县|