亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

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

在C++中反射調用.NET的方法(一)

2020-01-26 14:15:38
字體:
來源:轉載
供稿:網友

為什么要在C++中調用.NET

一般情況下,我們常常會在.NET程序中調用C/C++的程序,使用P/Invoke方式進行調用,在編寫代碼代碼的時候,首先要導入DLL文件,然后在根據C/C++的頭文件編寫特殊的C#平臺調用代碼,例如像下面這個樣子:

 [DllImport("Interop.dll",EntryPoint = "Multiply",CharSet = CharSet.Ansi)] static extern int Multiply(int factorA, int factorB);

詳細的過程,可以參考之前我這篇文章:《C#調用C和C++函數的一點區別》

有時候,我們也會有在C++中調用.NET的需求,比如我們在維護一個大型的C++應用程序,它年代久遠,現在需要增加一些新功能,而這些功能在.NET中已經有了,只需要調用它即可,如果為了方便想要用.NET重寫這個C++應用程序是不太現實的,幸好,C++/CLI提供了一個簡便的方案使得可以在C++中直接編寫.NET程序,所以C++/CLI代表托管和本地編程的結合,可以在托管代碼中直接使用本地代碼,也可以反過來,這樣結合了C++本地代碼的高效性和.NET代碼的強大性,看起來是非常有潛力的。

使用C++/CLI進行.NET編程

要進行C++/CLI編程,只需要進行下面的步驟:

1,添加.NET程序集的應用;

2,修改C++項目屬性,配置屬性->公共語言運行時支持-公共語言運行時支持(/clr)

然而,為了保持C++與.NET應用程序的獨立性,要求不能將.NET的DLL文件放到C++的應用程序目錄下,因此上述步驟1不可行,需要在C++代碼中使用反射來調用.NET。

注意,本文說的C++反射調用,不是對C++自身進行封裝的反射功能,而是在C++/CLI代碼中反射調用.NET代碼,原理上跟你在.NET應用中反射調用另外一個.NET的程序集一個道理。

首先,我們建立一個名字叫CppNetTest的解決方案,添加3個項目:

1,CppConsoleTest---一個C++控制臺項目,在項目中更改屬性支持CLR;

2,NetApp--一個.NET控制臺應用程序,作為對比示例代碼,方便編寫C++/CLI代碼參考;

3,NetLib--一個.NET類庫程序集,它將被1和2項目進行反射調用。

我們先在NetLib項目寫一個簡單的.NET 類,這個類的方法內部沒有復雜的業務邏輯代碼,僅僅用來供反射調用測試:

namespace NetLib{  public class User  {    static List<IUserInfo> UserDb = new List<IUserInfo>();    public int GetUserID(string IdString)    {      int result = 0;      int.TryParse(IdString, out result);      return result;    }    public DateTime GetUserBirthday(int userId)    {      return new DateTime(1980, 1, 1);    }    public IUserInfo GetUserByID(int userId)    {      IUserInfo userinfo= EntityBuilder.CreateEntity<IUserInfo>();      userinfo.ID = userId;      userinfo.Name = "姓名_" + userId;      userinfo.Birthday = new DateTime(1980, 1, 1);      return userinfo;    }    //返回List或者數組,不影響 C++調用    public List<IUserInfo> GetUsers(string likeName)    {      List<IUserInfo> users = new List<NetLib.IUserInfo>();      for (int i = 0; i < 10; i++)      {        IUserInfo userinfo = GetUserByID(i);        userinfo.Name += likeName;        users.Add(userinfo);      }      //return users.ToArray();      return users;    }    public bool SaveUsers(IList<IUserInfo> users)    {      UserDb.AddRange(users);      return true;    }    public IUserInfo CreateUserObject()    {      return EntityBuilder.CreateEntity<IUserInfo>();    }    public bool SaveUsers2(IEnumerable<Object> para)    {      var users = from u in para            select u as IUserInfo;      return SaveUsers (users.ToList());    }  }}

在CppConsoleTest項目的頭文件中,添加一個 UserProxy.h 的C++頭文件,在文件中添加下面的命名空間:

using namespace System;using namespace System::Reflection;using namespace Runtime::InteropServices;using namespace System::Collections;

這樣我們就可以使用反射相關的類型了。

在UserProxy類中,先編寫我們需要的構造函數:

public ref class UserProxy  {  private:    String^ assemblyFile; //"..//NetLib//bin//Debug//NetLib.dll"    Object^ dotnetObject;    Type^ entityBuilderType;    String^ className = "NetLib.User";    EntityHelper^ helper;      public:    UserProxy(String^ assemblyFile)    {      this->assemblyFile = assemblyFile;      Assembly^ ass = Assembly::LoadFrom(this->assemblyFile);      this->dotnetObject = ass->CreateInstance(className);      String^ sodPath = System::IO::Path::Combine(System::IO::Path::GetDirectoryName(this->assemblyFile), "PWMIS.Core.dll");      /*Assembly^ ass_sod = Assembly::LoadFrom(sodPath);      this->entityBuilderType = ass_sod->GetType("PWMIS.DataMap.Entity.EntityBuilder");*/      helper = gcnew EntityHelper(sodPath);    }}

注意我們的 C++/CLI的類必須是“引用”類型,所以需要加關鍵字 ref,即:

public ref class UserProxy{}

所有的.NET引用類型,在使用的時候,都必須在類型名字后加 ^ 符號,例如下面定一個.NET字符串類型變量:

String^ assemblyFile; 

帶^符號的變量,在C++/CLI中稱為 “句柄”對象,用來跟C++本地代碼的“指針”相區別。

在C++中,類的成員用 -> 符號調用,命名空間或者類的靜態成員,用::調用,例如上面的構造函數中的代碼:

Assembly^ ass = Assembly::LoadFrom(this->assemblyFile);

 注意:在本例中需要.NET類庫項目引用 PDF.NET SOD框架,在項目的“管理Nuget程序包”里面搜索 PDF.NET.SOD.Core 添加此引用即可。
學會了這些C++的基礎語法,那么編寫C++/CLI代碼就沒有主要的障礙了。

在C++/CLI中使用反射

反射調用第一個.NET類的方法

下面的方法,將會反射調用 User類的一個最簡單的方法 :

public int GetUserID(string IdString){}

該方法只有一個一個參數和一個簡單的返回值,下面是C++/CLI的反射調用代碼:

int GetUserID(String^ iDstring){  MethodInfo^ method = this->dotnetObject->GetType()->GetMethod("GetUserID", BindingFlags::Public | BindingFlags::Instance);  Func<String^, int>^ fun = (Func<String^, int>^)Delegate::CreateDelegate(Func<String^, int>::typeid, this->dotnetObject, method);  int result = fun(iDstring);    return result;}

注意這里創建了一個 Func<String,int>的委托方法,使用委托能夠簡化我們的反射調用并且有時候還能夠提高效率,在這段代碼中,有1個要注意的地方:

Func<String^, int>::typeid

這是C++/CLI特殊的語法,表示獲取“句柄”類型的類型ID,實際上它的結果就Type對象,等同于C#的
typeof(Func<string,int>)

PS:非常遺憾的是,typeid方式,沒法得到下面類型的類型值:
typeof(Func<,>),這給我們在動態構造泛型對象的時候造成了很大的困惑。

再看一個簡單方法的反射:

DateTime GetUserBirthday(int userId)    {      MethodInfo^ method = dotnetObject->GetType()->GetMethod("GetUserBirthday", BindingFlags::Public | BindingFlags::Instance);      Func<int, DateTime>^ fun = (Func<int, DateTime>^)Delegate::CreateDelegate(Func<int, DateTime>::typeid, this->dotnetObject, method);      DateTime result = fun(userId);      return result;    }

注意:由于DateTime是值類型,因此在進行類型申明的時候,不需要加^符號,僅需要對Func委托加上^句柄標記。

有了這2個簡單的方法,我們來看看如何調用這個.NET方法“代理類”: 

 NetLibProxy::UserProxy^ proxy = gcnew NetLibProxy::UserProxy("..//NetLib//bin//Debug//NetLib.dll");  int result= proxy->GetUserID("123456");  DateTime date = proxy->GetUserBirthday(result);  System::Console::WriteLine("C++/CLI .Net Proxy Class Call Test Result:/r/n UserID={0},/r/n Birthday={1}",     result,date.ToShortDateString());

OK,第一個C++/CLI代碼調用成功,而且還是反射調用的,心情小激動一下。

有關C++/CLI的反射,委托的詳細資料,可以參考MSDN的介紹:

https://msdn.microsoft.com/zh-cn/library/2x8kf7zx.aspx 使用 C++ 互操作(隱式 PInvoke)
https://msdn.microsoft.com/zh-CN/library/213x8e7w.aspx 泛型委托

在下一篇,我們將繼續探究C++/CLI 反射調用.NET中可能遇到"深坑",因此僅打算吧本篇文章作為一個“入門”,免得大家心生恐懼,錯過了挑戰艱險的機會。

以上所述是小編給大家介紹的在C++中反射調用.NET的方法(一),希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩精品视频在线免费观看| 欧美日韩在线一区| 国产精品久久久久久久久久新婚| 欧美二区在线播放| 国产精品露脸av在线| 亚洲欧美另类在线观看| 成人www视频在线观看| 亚洲欧美日韩精品久久奇米色影视| 日韩中文字幕在线精品| 国产精品99久久久久久久久| 久久人人爽人人爽爽久久| 日韩视频在线免费| 久久手机免费视频| 91免费电影网站| 亚洲精品www久久久| 91国在线精品国内播放| 亚洲一二三在线| 日韩在线观看视频免费| 狠狠躁夜夜躁人人爽天天天天97| 日韩视频在线一区| 国产视频精品自拍| 国产精品久久久久久超碰| 久久视频免费在线播放| 精品久久久久久中文字幕大豆网| 91精品视频在线看| 精品国内产的精品视频在线观看| 91九色国产视频| 日韩第一页在线| 日韩精品视频在线| 亚洲国模精品一区| www.久久久久| 久热精品视频在线观看| 日韩av中文字幕在线| 欧美视频在线看| 亚洲欧美精品在线| 亚洲第一福利网站| 精品国模在线视频| 日本精品久久中文字幕佐佐木| 538国产精品视频一区二区| 国产精品综合不卡av| 久久久久日韩精品久久久男男| 亚洲福利视频网| 亚洲欧美国产日韩中文字幕| 亚洲色图日韩av| 日韩高清不卡av| 日韩精品高清在线观看| 日韩在线视频中文字幕| 影音先锋日韩有码| 日韩中文综合网| 亚洲欧美精品一区二区| 日韩电影中文 亚洲精品乱码| 91久久久久久久| 亚洲精品videossex少妇| 成人精品视频99在线观看免费| 日韩av电影手机在线| 国产精品狠色婷| 精品国产成人在线| 亚洲精品国产精品乱码不99按摩| 中文字幕日韩免费视频| 92裸体在线视频网站| 一本色道久久综合狠狠躁篇怎么玩| 97视频免费观看| 成人午夜在线影院| 欧美成人免费小视频| 一道本无吗dⅴd在线播放一区| 亚洲欧美日韩久久久久久| 成人久久精品视频| 欧美精品在线观看| 成人伊人精品色xxxx视频| 亚洲另类图片色| 久久99精品国产99久久6尤物| 国产噜噜噜噜久久久久久久久| 日本一区二区三区四区视频| 欧美激情一二三| 中文字幕久久亚洲| 欧美另类在线播放| 欧美中文字幕视频在线观看| 国产精品亚洲美女av网站| 国产z一区二区三区| 亚洲欧美三级在线| 久久精品国产欧美亚洲人人爽| 伦理中文字幕亚洲| 国产精品久久一区主播| 亚洲天堂免费在线| 亚洲精品mp4| 正在播放国产一区| 疯狂做受xxxx高潮欧美日本| 69久久夜色精品国产7777| 久久久久久久影视| 国产精品福利小视频| 欧美日韩国产精品| 欧美日韩久久久久| 亚洲欧美日韩久久久久久| 尤物九九久久国产精品的分类| 亚洲精品国产综合久久| 欧美日韩爱爱视频| 欧美超级免费视 在线| 高清日韩电视剧大全免费播放在线观看| 亚洲字幕在线观看| 欧美综合第一页| 成人网址在线观看| 国产一区二区三区在线看| 日韩电影中文字幕| 亚洲午夜国产成人av电影男同| 国产精品视频26uuu| 一区二区日韩精品| 成人久久久久爱| 九九综合九九综合| 国产精品久久久久久久午夜| 亚洲国产精品电影在线观看| 亚洲免费视频网站| 亚洲黄页网在线观看| 久久综合伊人77777| 欧美激情精品久久久久久| 91a在线视频| www.日韩视频| 视频一区视频二区国产精品| 日韩黄色av网站| 久久久国产精品亚洲一区| 欧美成人合集magnet| 欧美在线观看日本一区| 久久人人97超碰精品888| 久久青草福利网站| 国产经典一区二区| 欧美极品欧美精品欧美视频| 2020久久国产精品| 中文字幕在线看视频国产欧美在线看完整| 亚洲va久久久噜噜噜| 亚洲精品久久久久中文字幕二区| 91在线视频成人| 国产精品久久久久久一区二区| 狠狠操狠狠色综合网| 亚洲午夜小视频| 日韩免费观看高清| 国产一区二区三区丝袜| xxx欧美精品| 国产精品91久久久| 91精品国产91久久久久久吃药| 国产午夜精品麻豆| 久久影院资源站| 91久久久精品| 日韩av影片在线观看| 在线观看精品自拍私拍| 国产精品1234| 欧美成年人在线观看| www.久久撸.com| 91精品久久久久久久久久另类| 久久久免费观看视频| 欧美成人全部免费| 国产亚洲精品综合一区91| 曰本色欧美视频在线| 日韩精品中文字幕在线| 97成人超碰免| 午夜精品一区二区三区在线视频| 国产精品99久久久久久白浆小说| 日本精品久久电影| 久久久国产精品亚洲一区| 久久精品色欧美aⅴ一区二区| 亚洲欧美精品suv| 久久国产精品久久国产精品| 精品国产91乱高清在线观看| 久久精品99久久香蕉国产色戒| 91久久久亚洲精品| 国产综合视频在线观看|