最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

MFC dll實現(xiàn)C++/CLI dll組件,C#調用的全過程詳解(附完整源碼)

2023-07-09 12:28 作者:浮云繪圖  | 我要投稿

模塊化組件化實現(xiàn)獨立的功能模塊是軟件設計的良好習慣,一般用實現(xiàn)為DLL。普通的DLL對外提供接口是采用導出函數(shù)接口,如果接口數(shù)量不大,只是50個以內,這種方式很適合;如果對外接口有上百個,導出函數(shù)接口就完全破壞了軟件模塊化分層設計的理念,使用接口非常麻煩,此情形采用C++/CLI導出類方式實現(xiàn)比較適合,即核心實現(xiàn)先C++ DLL,然后C++/CLI直接調用C++ DLL導出類,對外第三方工程提供CLI類接口。浮云E繪圖以一個最簡單的繪圖模塊為示例,詳細介紹此方法的實現(xiàn)過程。


一、C++ DLL實現(xiàn)

本文只是為了介紹調用C++ dll導出類實現(xiàn)C++/CLI dll的完整過程,示例程序盡量簡單。先用C++實現(xiàn)一個繪圖組件dll。

C++ dll繪圖主鍵設計構思

1. 繪圖畫布CFyView:CFyView繼承自CWnd,是繪圖畫布窗口,并響應鼠標事件。

2. 繪圖數(shù)據(jù)容器CChart:管理所有業(yè)務數(shù)據(jù),(如需支持控件內滾軸,容器是虛擬畫布)。

3. 曲線CCurve:曲線數(shù)據(jù)和曲線繪制。


C++ dll程序開發(fā)過程

1. 新建工程

選擇C++ Windows 的?MFC動態(tài)鏈接庫? --> 項目取名FyMfcDll,解決方案取名FyDemo --> Dll類型選 使用共享MFC DLL的常規(guī) DLL

2. 創(chuàng)建繪圖窗口類CFyView

新建類CFyView,繼承于CWnd --> 添加窗口屬性變量int m_crBackColor,重載窗口消息OnPaint、OnLButtonDblClk。

class CFyView : public CWnd

{

public:

CFyView();

virtual ~CFyView();

bool Create(HWND hParentWnd);


DECLARE_MESSAGE_MAP()

afx_msg void OnPaint();

afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);


public:

int m_crBackColor;

HWND m_hParentWnd;


CChart m_chart;

};

先創(chuàng)建好繪圖窗口,方便調試繪圖功能。接著往下實現(xiàn)繪圖相關功能,等繪圖功能實現(xiàn)后,再在CFyView里聲明繪圖相關對象,在OnPaint完成繪圖呈現(xiàn)。

3. 創(chuàng)建數(shù)據(jù)管理器類CChart

數(shù)據(jù)管理類主要定義了曲線Curve對象集合、曲線標題、標題顯示位置屬性,以及添加、刪除曲線,設置標題位置、繪圖Draw等函數(shù)。

//作者:浮云E繪圖,專業(yè)付費定制各類CAD/Viso等繪圖編輯器、曲線控件等軟件

//QQ:316868127


class CChart

{

public:

CChart();

virtual ~CChart();


void AddCurve(CCurve* curve);

void RemoveCurve(CCurve* curve);

void ClearCurves();


void Draw(CDC* dc);


void SetTitlePos(int x, int y);

void GetTitlePos(int& x, int& y);

CString GetTitle();


public:

CString m_sTitle;

CPtrArray m_curves;


int m_iTitleX;

int m_iTitleY;

};

實際商業(yè)項目中,數(shù)據(jù)管理容器管理著大量的業(yè)務對象,就曲線控件而言,比如曲線網(wǎng)格、坐標軸、圖例等等數(shù)據(jù)。

4. 創(chuàng)建曲線類CCurve

曲線類主要定義了數(shù)據(jù)點集合CPoint數(shù)組、曲線名稱、曲線線條寬度、顏色、線型等屬性,主要方法是添加、清空點,以及畫點連線函數(shù)Draw。

class CCurve

{

public:

CCurve(CString name);

virtual ~CCurve();


virtual bool AddPoint(CPoint* point);

virtual void ClearPoints();


virtual void Draw(CDC* dc);


public:

CString m_sName;


int MAX_POINT_COUNT = 100;

CPoint* m_pts = new CPoint[100]; //實際項目,此處創(chuàng)建的數(shù)組個數(shù)由外部程序傳入

int m_nPointCount;


int m_nLineStyle;

int m_nLineWidth;

int m_crLineColor;

};

以上完成了C++ dll示例定義,完整的解決方案(包含4個工程)源碼,在文本底部提供下載鏈接。在些C++ dll時,為了方便快捷的測試,可以先寫一個C#測試工程,直接通過導出函數(shù)方式,測試C++ dll的核心流程。具體實現(xiàn)方式可參考?C#和VC++調用dll步驟,接口指針、字符串等類型對應關系。


C++ dll直接導出函數(shù)測試接口

extern "C" __declspec(dllexport) CFyView * NewFyChart()

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

return new CFyView();

}


extern "C" __declspec(dllexport) void DeleteFyChart(CFyView* fyView)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

delete fyView;

}


extern "C" __declspec(dllexport) bool CreateFyView(CFyView *fyView, HWND hParentWnd)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

return fyView->Create(hParentWnd);

}


extern "C" __declspec(dllexport) void LoadFyVDate(CFyView * fyView)

{

CChart* chart = &(fyView->m_chart);


int offx = 50;

CCurve* curve1 = new CCurve(_T("curve 001"));

for (int i = 0; i < 20; i++)

{

curve1->AddPoint(new CPoint(offx, rand()%50));


offx += 10;

}

curve1->m_crLineColor = 0x00FF00;

curve1->m_nLineWidth = 2;

chart->AddCurve(curve1);


CCurve* curve2 = new CCurve(_T("curve 001"));

for (int i = 0; i < 40; i++)

{

curve2->AddPoint(new CPoint(offx, 100+rand() % 50));


offx += 10;

}

curve2->m_crLineColor = 0x0;

curve2->m_nLineWidth = 1;

chart->AddCurve(curve2);


fyView->RedrawWindow();

}


extern "C" __declspec(dllexport) void SetFyVBackColor(CFyView * fyView, int color)

{

fyView->m_crBackColor = color;


fyView->RedrawWindow();

}


extern "C" __declspec(dllexport) int GetFyVBackColor(CFyView * fyView)

{

return fyView->m_crBackColor;

}


C#工程直接調用C++ dll測試實例

? ? ? ? private const string LTDLL_NAME = "FyMfcDll.dll";

[DllImport(LTDLL_NAME, EntryPoint = "NewFyChart", CallingConvention = CallingConvention.Cdecl)]

public static extern IntPtr NewFyChart();

[DllImport(LTDLL_NAME, EntryPoint = "DeleteFyChart", CallingConvention = CallingConvention.Cdecl)]

public static extern void DeleteFyChart(IntPtr chart);


[DllImport(LTDLL_NAME, EntryPoint = "CreateFyView", CallingConvention = CallingConvention.Cdecl)]

public static extern bool CreateFyView(IntPtr fyView, IntPtr hParentWnd);

[DllImport(LTDLL_NAME, EntryPoint = "LoadFyVDate", CallingConvention = CallingConvention.Cdecl)]

public static extern void LoadFyVDate(IntPtr chart);


[DllImport(LTDLL_NAME, EntryPoint = "SetFyVBackColor", CallingConvention = CallingConvention.Cdecl)]

public static extern void SetFyVBackColor(IntPtr chart, int color);

[DllImport(LTDLL_NAME, EntryPoint = "GetFyVBackColor", CallingConvention = CallingConvention.Cdecl)]

public static extern int GetFyVBackColor(IntPtr chart);



IntPtr m_fyChart;


public Form1()

? ? ? ? {

? ? ? ? ? ? InitializeComponent();

? ? ? ? }


private void Form1_Load(object sender, EventArgs e)

{

m_fyChart = NewFyChart();


CreateFyView(m_fyChart, this.panel1.Handle);


LoadFyVDate(m_fyChart);

}


private void btnChangeBk_Click(object sender, EventArgs e)

? ? ? ? {

int bkclr = GetFyVBackColor(m_fyChart);

SetFyVBackColor(m_fyChart, 0xADD8E6);

? ? ? ? }


二、C++/CLI dll、 C++ dll、C#之數(shù)據(jù)類型的對應關系

?3種開發(fā)語言常用的數(shù)據(jù)類型對應關系如下表所示:

需要特別說明的是:

1>需要函數(shù)形參返回int值時,C++定義為int&,CLI定義為int%,C#定義為ref int。如GetChartSize(int& w, int& h) --> GetChartSize(int% w, int% h) --> GetChartSize(ref int w, ref int h);

2>需要顏色定義時,C++不支持Color只能用int,CLI支持Color,C#支持Color,因為int和Color類型的內存不一樣,需要中間層CLI把int 與 Color相互轉換(DateTime類型也是如此)。

3>CLI類加^,等同于C#的類,都是托管對象。

那么C++對象是怎么與C#對應上的呢?他們無法直接對應,得通過CLI層轉換。得在CLI層同時維護C++類指針與CLI類引用,并且讓他們關聯(lián)上。對C#使用CCurve^托管對象,對內維護C++類CCurve*指向的非托管內存。具體請看下一節(jié)CLI工程源碼。


4> 屬性的實現(xiàn)。C++使用setXXX和GetXXX函數(shù),CLI使用property即set和get方法,C#直接訪問變量。

三、C++/CLI DLL實現(xiàn)

C++/CLI dll程序開發(fā)過程

1. 新建C++/CLI工程

選擇 CLR類庫(.NET Framework) --> 項目取名 FyClr

2. 添加FView類,作為C++窗口類CFyView的對應

// FView.h文件

using namespace System;

namespace fy_dll

{

public ref class FView : public IDisposable

{

public:

FView();

virtual ~FView();

};

}



// FView.cpp文件

#include "pch.h"

#include "FView.h"

namespace fy_dll

{

FView::FView()

{}


FView::~FView()

{}

}

1> FView是托管類,帶ref關鍵字;

2>FView類繼承于IDisposable,作為C++資源對象(窗口)的對應類,請繼承于IDisposable

3>請定義一個namespace 命名空間,在C#工程好引用。


C++對象與C#對應

? ? //FView.h

? ? #include "../FyMfcDll/CFyView.h"


? ? public ref class FView : public IDisposable

? ? {


public:

FView();

property Color BackColor {

Color get();

void set(Color value);

}


private:

CFyView* m_cFyView;


? ? ......

? ? };



? ? //-----------------------------------------------

? ? //FView.cpp

? ? FView::FView()

{

m_cFyView = new CFyView();

}


Color FView::BackColor::get()

{

return UInt2Color(m_cFyView->m_crBackColor);

}

void FView::BackColor::set(Color value)

{

m_cFyView->m_crBackColor = Color2UInt(value);

}

是在ref class FView類里定義了一個C++對象指針,維系這與C++ dll的關系。


C++/CLI dll封裝C++ dll過程和編譯選項

1> 回到C++工程,把需要導出的類定義加關鍵詞

class ?CFyView : public CWnd ?--> 改成 class __declspec(dllexport) ?CFyView : public CWnd

2>CLI工程編譯選項設置

????????a> 項目屬性 ->? 配置屬性 -> 高級 ->??MFC的使用,設為"在共享DLL中使用MFC";

????????b> 項目屬性 ->? 配置屬性 -> 高級 ->??字符集,設為"使用多字節(jié)字符集;(如果文字亂碼)

? ? ? ? b> 項目屬性 ->? 配置屬性 -> 調試 -> 命令,可設為調用此dll的應用程序EXE;(非常重要,方便調試代碼)

? ? ? ? c> 項目屬性 ->? 配置屬性 -> 調試 ->?調試器類型,設為"混合(.NET Framework)";(方便調試代碼)

????????d> 項目屬性 ->? 鏈接器?-> 常規(guī)?->?附加庫目錄,設為"$(SolutionDir)$(Configuration)\";

? ? ? ? e> 項目屬性 ->? 鏈接器?-> 輸入 ->?附加依賴項,設為"$FyMfcDll.lib";(因為本項目CLI工程調用了C++ FyMfcdll工程dll)

? ? ? ? ?f> 項目屬性 ->? C/C++ -> 代碼生成 ->?結構成員對齊,設為"4字節(jié)";(如果C++工程與CLI工程對通一結構體內存數(shù)據(jù)錯了,兩個工程需設置相同的結構成員對齊方式)

? ? ? ? ?g> 項目屬性 ->? 配置屬性 -> 高級 -> 公共語言運行時支持,設為"公用語言運行時支持(/clr)";(C++工程與CLI工程都要設置)


3. CLI工程,繼續(xù)新建托管類FChart對應C++工程的CChart類,新建托管類FCurve對應C++工程導出類CCurve。

C++ 工程類如CChart定義改成class __declspec(dllexport) ?CChart? -->?CLI工程FChart類新增有必要對外提供接口訪問的屬性和成員函數(shù)(實現(xiàn)是調用C++指針對象執(zhí)行)。工程源碼底部下載。


四、第三方調用C++/CLI DLL示例

1. 新建項目,選 C# Windows 桌面? --> Windows 窗體應用(.NET Framework) --> 取名“TestClrDllDemo”

2. 引用上文開發(fā)的Clr組件。1>添加代碼 using yf_dll? --> 2> 點擊“引用”,右鍵“添加引用”,瀏覽clr組件生成目錄,選擇fyClr.dll。

3. C#工程直接調用CLI DLL里的各種類。


?解決方案可以運行,包含4個工程:(完整源碼下載地址)https://download.csdn.net/download/fyhhack/87991560

1. MFC dll工程 FyMfcDll,C++ MFC實現(xiàn)核心業(yè)務和繪圖。

2. C++/CLI dll工程 fyClr ,封裝 MFC dll各功能,以導出類方式對外提供接口,直接C#訪問。

3. C# Winform測試MFC dll工程 TestMfcdllDemo

4. C# Winform測試C++/CLI dll工程 TestClrDllDemo


MFC dll實現(xiàn)C++/CLI dll組件,C#調用的全過程詳解(附完整源碼)的評論 (共 條)

分享到微博請遵守國家法律
南郑县| 海伦市| 思南县| 措美县| 蒙城县| 石阡县| 金湖县| 自贡市| 务川| 南涧| 临安市| 双桥区| 伊通| 博客| 萨嘎县| 元朗区| 任丘市| 大宁县| 蛟河市| 江都市| 阿勒泰市| 故城县| 洪江市| 镇原县| 宣化县| 临颍县| 陆丰市| 积石山| 瑞丽市| 方正县| 大邑县| 友谊县| 翁源县| 澄城县| 化德县| 罗山县| 墨脱县| 临城县| 阳新县| 咸阳市| 丁青县|