锘??xml version="1.0" encoding="utf-8" standalone="yes"?> 涓銆佺華璁?/strong>
褰撳井杞帹鍑篤S.NET7瀹炵幇浜嗗彲鎵╁睍鐨勬墭綆++鍚庯紝C++紼嬪簭鍛樹滑鍙嶆槧涓嶄竴銆傚敖綆″ぇ閮ㄥ垎鐨勭▼搴忓憳瀵逛簬鑳藉緇х畫浣跨敤C++鎰熷埌寰堟鎱幫紝浣嗗嚑涔庢墍鏈夌殑浜哄浜庢墭綆++鎻愪緵鐨勬櫐娑╄娉曟劅鍒板緢鐥涜嫤銆傚井杞槑鏄句粠鍙嶉涓劅瑙夊埌鎵樼C++涓嶆槸閭d箞鎴愬姛銆?
2003騫?0鏈?鏃ワ紝ECMA錛堟媧茶綆楁満鍒墮犲晢鍗忎細錛夊甯冩垚绔嬩笓瀹剁粍錛岃礋璐g粨鍚圛SO鏍囧噯C++涓庨氱敤璇█錛屽紑鍙戜竴涓彲鎵╁睍璇█鐨勬爣鍑嗭紝榪欎釜鏂扮殑鍙墿灞曡璦琚О涓篊++/CLI鏍囧噯銆傝繖涓爣鍑嗗皢琚玍S.NET2005鐨凜++緙栬瘧鍣ㄦ敮鎸併?
浜屻佽佽娉曞瓨鍦ㄧ殑闂
1銆佹櫐娑╃箒鐞愮殑璇硶鍜屾枃娉?-榪欎袱涓?鍙岄噸搴曠嚎"闂鍔犻噸浜嗛槄璇葷殑璐熸媴銆?
2銆佷簩嫻佺殑CLI鏀寔--鐩稿涓嶤#涓嶸B.NET錛孧C++浣跨敤涓嶆柟渚跨殑宸ヤ綔鍖烘潵鎻愪緵CLI鏀寔錛屼緥濡傦紝瀹冩病鏈変竴涓竴涓瀵瑰簲鐨勭粨鏋勬潵鍒椾婦.NET鐨勯泦鍚堛?
3銆丆++涓?NET綺楅檵鍦扮粨鍚?-瀵逛簬CLI綾誨瀷錛屼綘涓嶈兘浣跨敤C++鐨勭壒鑹詫紝渚嬪妯℃澘錛涘悓鏍鳳紝瀵逛簬C++綾誨瀷錛屼綘涓嶈兘浣跨敤CLI鐨勭壒鑹詫紝渚嬪紕庣墖甯愰泦銆?
4銆佷護浜烘販娣嗙殑鎸囬拡--闈炴墭綆$殑C++鐨勬寚閽堝強鎵樼鐨勫紩鐢ㄦ寚閽堥兘浣跨敤*璇硶錛岃繖闈炲父浠や漢娣鋒穯錛屽洜涓?gc鎸囬拡涓庢墭綆℃寚閽堝湪鏈川鍜岃涓轟笂瀹屽叏涓嶅悓銆?
5銆丮FC緙栬瘧鍣ㄤ笉鑳戒駭鐢熷彲鏍¢獙鐨勪唬鐮併?
涓夈丆++/CLI緇欐垜浠彁渚涗簡浠涔堬紵
1銆佷紭闆呮祦鐣呯殑璇硶鍜屾枃娉?-C++/CLI涓篊++寮鍙戜漢鍛樹功鍐欐墭綆′唬鐮佹彁渚涗簡涓縐嶉潪甯歌嚜鐒剁殑鎰熻錛屽茍涓斿畠鎻愪緵浜嗛潪鎵樼浠g爜鍒版墭綆′唬鐮佺殑騫蟲粦榪囧害銆備互鍓嶆墍璋撶殑"鍙岄噸搴曠嚎"闂鐜板湪宸茬粡鑽$劧鏃犲瓨銆?
2銆佷竴嫻佺殑CLI鏀寔--CLI鐗硅壊錛屼緥濡傚睘鎬с佺鐗囬泦鍚堝拰灞炵被寰楀埌浜嗙洿鎺ユ敮鎸侊紝姝ゅ錛孋++/CLI榪樺噯璁稿皢榪欎簺鐗硅壊鐢ㄤ簬鏈湴闈炴墭綆$殑綾匯?
3銆佷竴嫻佺殑C++綾繪敮鎸?-C++鐗硅壊錛屼緥濡傛ā鏉垮拰鏋愭瀯鍑芥暟瀵逛簬鎷栫鍜岄潪鎷栫綾葷戶緇湁鏁堛傚疄闄呬笂錛孋++/CLI鏄綘鍙互"琛ㄩ潰涓?鍦ㄦ爤鎴朇++鏈湴鍫嗕笂澹版槑涓涓?NET綾誨瀷鍞竴鐨?NET璇█銆?
4銆佸湪.NET涓嶤++涔嬮棿鐨勬矡澹戜笂鏋惰搗浜嗕竴搴фˉ姊?-C++寮鍙戜漢鍛樺湪鎶ㄥ嚮BCL鏃朵笉鍐嶈薄紱誨紑姘寸殑楸箋?
5銆丆++/CLI緙栬瘧鍣ㄤ駭鐢熺殑鍙墽琛屾枃浠跺畬鍏ㄦ槸鍙牎楠岀殑銆?
鍥涖?Hello World"灝忕▼搴?/strong>
涓婅堪浠g爜闄や簡涓嶉渶瑕佸紩鐢╩scorlib.dll搴撳錛屼笌鑰佺殑璇硶娌℃湁澶ぇ鐨勫尯鍒紝鍥犱負鏃犺浣犱粈涔堟椂鍊欎嬌鐢?clr榪涜緙栬緫錛岀紪璇戝櫒閮藉彲浠ユ殫涓繘琛屽紩鐢紙鐜板湪榛樿鐨勬槸/clr:newSyntax錛夈?
浜斻佸彞鏌?/strong>
涓庤佺殑璇硶涓昏鐨勬販娣嗘槸鎴戜滑涔犳儻浜庝嬌鐢?絎﹀彿鏉ュ0鏄庢嫋綆″紩鐢ㄦ垨闈炴嫋綆℃寚閽堬紝鍦–++/CLI閲屽井杞紩鍏ヤ簡鍙ユ焺鐨勬蹇點?
^絎﹀彿浠h〃涓涓墭綆″璞★紙澹版槑鏃剁湅涓婂幓璞′釜甯藉瓙錛夛紝鎸夌収CLI鐨勮瀹氾紝鍙ユ焺浠h〃涓涓嫋綆″璞$殑寮曠敤銆傚彞鏌勫湪CLI涓槸鏂扮殑璇硶錛岀浉褰撲簬C++涓殑-gc鎸囬拡銆傚彞鏌勪笌鎸囬拡涓嶅啀娣鋒穯錛屽湪鏈川涓婁袱鑰呭畬鍏ㄤ笉鍚屻?
鍏佸彞鏌勪笌鎸囬拡鏄庢牱鍖哄垎寮鏉ョ殑錛?/strong>
1銆佹寚閽堝0鏄庢椂浣跨敤*絎﹀彿錛岃屽彞鏌勪嬌鐢╚絎﹀彿銆?
2銆佸彞鏌勬槸閽堝鎷栫鍫嗕笂瀵硅薄鐨勬嫋綆″紩鐢紝鑰屾寚閽堜粎浠呮寚鍚戝唴瀛樹腑鐨勪竴涓湴鍧銆?
3銆佹寚閽堝緢紼沖畾錛孏C寰幆涓嶄細褰卞搷鍒板畠錛涘彞鏌勫湪鍩轟簬GC鎴栧唴瀛樼揣寮犵殑鎯呭喌涓嬶紝鍙互鎸囧悜涓嶅悓鐨勫唴瀛樹綅緗?
4銆佸浜庢寚閽堬紝紼嬪簭寮鍙戜漢鍛樺繀欏?鏄懼紡"鍦板垹闄わ紝鍚﹀垯浼氶潰涓存硠闇茬殑鍗遍櫓錛岃屽浜庡彞鏌勶紝鏄惁榪涜鏄懼紡鍒犻櫎鍒欏畬鍏ㄦ牴鎹▼搴忎漢鍛樼殑鐖卞ソ浜嗐?
5銆佸彞鏌勪竴瀹氳鎸囧悜涓涓叿浣撶殑綾誨瀷錛屽嵆鎵璋撶殑綾誨瀷瀹夊叏鎬э紝鑰屾寚閽堟槑鏄句笉鏄繖鏍鳳紝浣犲喅涓嶅彲浠ュ皢涓涓彞鏌勬寚鍚慥oid^綾誨瀷銆?
6銆佹濡俷ew鎿嶄綔絎﹁繑鍥炰竴涓寚閽堜竴鏍鳳紝gcnew榪斿洖涓涓彞鏌勩?
涓冦丆LR瀵硅薄紺轟緥
鍏抽敭瀛梘cnew鐢ㄦ潵瀹炰緥鍖栦竴涓狢LI瀵硅薄錛岃屼笖瀹冭繑鍥炰竴涓寚鍚戝湪CLR鍫嗕笂鐨勫璞$殑鍙ユ焺錛実cnew鐨勪紭鐐瑰湪浜庡畠鍙互鏂逛究鐨勮鎴戜滑鍖哄垎鎷栫鍜岄潪鎷栫鐨勫疄渚嬪璞°?
澶ч儴鍒嗘儏鍐典笅錛実cnew鍏抽敭瀛楀拰^鎿嶄綔絎︽彁渚涗簡浣犵敤鏉ヨ繘琛孊CL鐨勪竴鍒囨墜孌碉紝浣嗘槸寰堟槑鏄句綘闇瑕佸垱寤哄拰澹版槑灞炰簬鑷繁鐨勬嫋綆$被鍜屾帴鍙c?
鍏佸0鏄庣被鍨?
CLR綾誨瀷鏈変竴涓艦瀹硅瘝鍓嶇紑鐢ㄦ潵璇存槑綾誨瀷鐨勭綾伙紝涓嬮潰鏄疌++/CLI涓殑綾誨瀷澹版槑紺轟緥錛?
涓婅堪紼嬪簭涓殑浠g爜涓庤佺殑C++璇█鐩告瘮鐪嬩笂鍘婚潪甯哥畝媧侊紝鍦ㄤ互寰鐨凜++浠g爜涓紝鑷沖皯瑕佺敤鍒?gc鍜?interface榪欎袱涓叧閿瘝銆?
涔濄佽綆?鎷嗙鎿嶄綔
鍦–++/CLI涓紝鍔犵鏄殣鍚殑錛岃屼笖綾誨瀷鏄畨鍏ㄧ殑錛屼竴涓簩榪涘埗鐨勬嫹璐濊鎵ц騫跺湪CLR鍫嗕笂褰㈡垚涓涓璞★紝鍘葷鏄樉寮忕殑錛屼粎浠呴渶瑕佷嬌鐢╮einterpret_cast鎿嶄綔絎︽潵瑙i櫎寮曠敤銆?
鍦ㄤ笂榪頒唬鐮佷腑錛?o"瀵硅薄鏄竴涓姞綆辯殑鎷瘋礉錛屼粠絎簩涓鍙onsole::WriteLine.鐨勮緭鍑哄彲浠ュ緢鏄庢樉鍦扮湅鍒幫紝瀹冨茍娌℃湁娑夊強鍒癷nt綾誨瀷鐨勬暣鏁板箋?
褰撲綘瀵逛竴縐嶆暟鍊肩被鍨嬭繘琛屽姞綆辨搷浣滄椂錛岃繑鍥炵殑瀵硅薄璁頒綇浜嗘渶鍒濈殑鏁板肩被鍨嬨?
鍥犳涓嶈兘瀵逛笉鍚岀被鍨嬬殑瀵硅薄榪涜鍘葷鎿嶄綔銆?
濡傛灉浣犻潪灝濊瘯榪欎箞鍋氾紝閭d箞浣犲皢寰楀埌涓涓猄ystem.InvalidCastException銆傝鎴戜滑鏉ユ帰璁ㄤ竴涓嬪畬緹庣殑綾誨瀷瀹夊叏鎬э紝濡傛灉浣犺鐪嬪唴閮ㄤ唬鐮侊紝浣犲皢鐪嬪埌寰蔣鐨勫唴閮ㄧ鍦ㄥ疄闄呬腑鐨勮繍鐢ㄣ備緥濡傦細
緙栬瘧鍚庣殑浠g爜鏄細
鏍規嵁寰蔣鐨勫唴閮ㄦ枃妗o紝綆辨搷浣滃皢鏈姞宸ョ殑綾誨瀷杞崲涓轟竴涓叿浣撶被鍨嬬殑瀹炰緥錛岃繖欏瑰伐浣滅殑瀹屾垚閫氳繃鍒涘緩涓涓柊鐨勫璞″茍灝嗘暟鎹嫹璐濆埌榪欎釜鏂板垎閰嶇殑瀵硅薄銆?
鍗併佸啓鍦ㄥ悗闈㈢殑璇?/strong>
涓轟粈涔堝緢澶氫漢宸茬粡鍙互浣跨敤C銆丆++銆?NET鏉ュ紑鍙戠▼搴忎絾榪樺湪縐瀬瀛︿範C++/CLI鍛紝鎴戞兂鏈夊洓涓柟闈㈢殑鍘熷洜錛?
1銆佷粠緙栬瘧鍣ㄧ洿鍒板唴灞傞兘榪樺湪鏀寔C++浠g爜錛?
2銆丆++/CLI瀵逛簬鍏朵粬鏍囧噯鏉ヨ鏃犳剰鏄叿鏈夋瘉鐏у湴錛?
3銆佷笌鐢熶勘鏉ョ殑鍐呴儴鏀寔鑳滆繃鎵鏈夊叾浠朇LI璇█
4銆佹墍鏈夊湪MFC涓嚭鐜扮殑涓嬪垝綰塊兘宸蹭笉鍐嶅瓨鍦ㄣ?/p>
1. 綆浠?br>
涓錛?br>
C++/CLI錛氱涓嫻佺殑CLI璇█(杞澆)
浜岋紝
]]>C++/CLI錛氱涓嫻佺殑CLI璇█
2005-08-25 11:25 浣滆咃細 鏈卞厛蹇犵紪璇?鍑哄錛?澶╂瀬緗?璐d換緙栬緫錛氭柟鑸?
銆銆鏈枃騫朵笉鏄負浜嗗鎵緾++/CLI鐨勮緣鐓岋紝涔熶笉鏄負浜嗚船浣庡叾瀹冨C#鎴栬匳B.NET絳夎璦錛岀浉鍙嶏紝榪欏彧鏄竴涓潪瀹樻柟鐨勩佷互涓涓枩嬈㈣繖縐嶈璦鐨勯潪寰蔣闆囧憳韜喚鏉ヨ璇丆++/CLI鏈夊畠鐨勮嚜宸辯殑鍞竴鐨勮鑹詫紝鍙綔涓虹涓嫻佺殑.NET緙栫▼璇█銆?br>
銆銆涓涓笉鏂湪鏂伴椈緇勫拰鎶鏈鍧涗笂鍑虹幇鐨勯棶棰樻槸錛屽綋璞#鍜孷B.NET榪欐牱鐨勮璦鏇撮傚悎浜庤繖縐嶇敤閫旀椂錛屼負浠涔堣浣跨敤C++鏉ュ紑鍙?NET搴旂敤杞歡銆傞氬父榪欐牱涓浜涢棶棰樺悗闈㈢殑璇勮璇存槸錛孋++璇硶鏄庢牱鐨勫鏉傚拰浠や漢璐硅В錛孋++鐜板湪鏄庢牱涓縐嶈繃鏃剁殑璇█錛岃繕鏈変粈涔圴S.NET璁捐鑰呭凡涓嶅啀鍍忔敮鎸丆#鍜孷B.NET涓鏍風戶緇敮鎸丆++銆傚叾涓竴浜涚寽鐤戞槸瀹屽叏鑽掕艾鐨勶紝浣嗘湁浜涜娉曢儴鍒嗘紜傚笇鏈涙湰鏂囨湁鍔╀簬婢勬竻鎵鏈夎繖浜涘洿緇旵++/CLI璇█鍙婂叾鍦╒S.NET璇█灞傛涓殑鍦頒綅鐨勭枒鎯戯紝紲炵鍜屼笉淇′換銆傝璁頒綇錛屾湰浣滆呮棦涓嶄負寰蔣宸ヤ綔涔熸病鏈変粠寰蔣閭i噷鍙栧緱鎶ラ叕錛屽彧鏄兂浠庢妧鏈笂瀵笴++/CLI浣滀竴璇勫垽銆?br>
銆銆2. 蹇熺畝媧佺殑鏈満interop
銆銆闄や簡P/Invoke鏈哄埗鍙敤鍦ㄥ彟澶栫殑璞#鎴朧B.NET榪欐牱鐨勮璦澶栵紝C++鎻愪緵浜嗕竴縐嶇嫭鏈夌殑interop鏈哄埗錛岀О浣淐++ interop銆侰++ interop姣擯/Invoke鐩磋寰楀錛屽洜涓轟綘鍙槸綆鍗曞湴#include闇瑕佺殑澶存枃浠訛紝騫朵笌闇瑕佺殑搴撹繘琛岄摼鎺ュ氨鑳借薄鍦ㄦ湰鏈篊++涓竴鏍瘋皟鐢ㄤ換浣曞嚱鏁般傚彟澶栵紝瀹冩瘮P/Invoke閫熷害蹇?-榪欐槸寰堝鏄撹兘璇佹槑鐨勩傜幇鍦紝鍙簤杈╃殑鏄湪瀹為檯搴旂敤杞歡鐨勫紑鍙戜腑錛岀粡鐢盋++ interop鑾峰緱鐨勬ц兘濂藉涓庤姳鍦ㄧ敤鎴鋒帴鍙d氦浜掋佹暟鎹簱瀛樺彇銆?a class=bluekey target=_blank>緗戠粶鏁版嵁杞偍銆佸鏉傛暟瀛︾畻娉曠瓑鏂歸潰鐨勬椂闂寸浉姣斿彲浠ヨ蹇界暐錛屼絾鏄簨瀹炴槸鍦ㄦ湁浜涙儏鍐典笅錛岀敋鑷抽氳繃姣忔interop璋冪敤鑺傜渷鐨勫嚑涓撼縐掍篃鑳界粰鍏ㄥ眬搴旂敤紼嬪簭鎬ц兘/鍝嶅簲閫犳垚宸ㄥぇ褰卞搷錛岃繖鏄粷瀵逛笉鑳借蹇借鐨勩備笅闈㈡湁涓ら儴鍒嗕唬鐮佺墖鏂?涓涓槸浣跨敤P/Invoke鏈哄埗鐨凜#紼嬪簭錛屼竴涓槸浣跨敤C++ Interop鏈哄埗鐨凜++紼嬪簭)錛屾垜鍒嗗埆璁板綍浜嗗叾鍚勮嚜浠g爜閲嶅鎵ц娑堣楃殑鏃墮棿(姣)銆備笉綆′綘濡備綍瑙i噴榪欎簺鏁版嵁錛屼笉綆¤繖浼氬浣犵殑搴旂敤紼嬪簭浜х敓浠涔堝獎鍝嶏紝鍏ㄦ槸浣犵殑浜嬨傛垜浠呮墦綆椾簨瀹炴у湴鎸囧嚭錛孋++浠g爜鐨勬墽琛岄熷害瑕佹瘮C#(鍏朵腑浣跨敤浜嗚緝澶氱殑鏈満interop璋冪敤)蹇?br>
銆銆1) C#紼嬪簭(浣跨敤P/Invoke)
[SuppressUnmanagedCodeSecurity]
[DllImport("kernel32.dll")]
static extern uint GetTickCount();
[SuppressUnmanagedCodeSecurity]
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint GetWindowsDirectory(
[Out] StringBuilder lpBuffer, uint uSize);
static void Test(int x)
{
StringBuilder sb = new StringBuilder(512);
for (int i = 0; i < x; i++)
GetWindowsDirectory(sb, 511);
}
static void DoTest(int x)
{
uint init = GetTickCount();
Test(x);
uint tot = GetTickCount() - init;
Console.WriteLine("Took {0} milli-seconds for {1} iterations",tot, x);
}
static void Main(string[] args)
{
DoTest(50000);DoTest(500000);DoTest(1000000);DoTest(5000000);
Console.ReadKey(true);
}
銆銆2) C++紼嬪簭(浣跨敤C++ Interop)
void Test(int x)
{
TCHAR buff[512];
for(int i=0; i<x; i++)
GetWindowsDirectory(buff, 511);
}
void DoTest(int x)
{
DWORD init = GetTickCount();
Test(x);
DWORD tot = GetTickCount() - init;
Console::WriteLine("Took {0} milli-seconds for {1} iterations",tot, x);
}
int main(array<System::String ^> ^args)
{
DoTest(50000);DoTest(500000);DoTest(1000000);DoTest(5000000);
Console::ReadKey(true);
return 0;
}
銆銆3) 閫熷害姣旇緝
銆銆
閲嶅嬈℃暟
C# 紼嬪簭
C++紼嬪簭
50,000
61
10
500,000
600
70
1,000,000
1162
140
5,000,000
6369
721
銆銆鍏舵ц兘宸埆鐪熸槸浠や漢鎯婃剷錛佽繖鐨勭‘鏄鏄庝負浠涔堣浣跨敤C++/CLI鐨勪竴涓ソ鐞嗙敱錛屽鏋滀綘鍦ㄤ嬌鐢ㄦ湰鏈篿nterop榪涜寮鍙戯紝閭d箞鎬ц兘錛佸畬鍏ㄧ敱浜庢ц兘錛屾垜灝卞皢琚揩鍊熷姪鏈満interop鏉ュ疄鐜板茍闈炲熀浜巜eb鐨?NET搴旂敤紼嬪簭銆傚綋鐒訛紝涓轟粈涔堟垜鎯寵浣跨敤.NET鏉ュ紑鍙戦渶瑕佸ぇ閲忔湰鏈篿nterop鎶鏈殑搴旂敤紼嬪簭瀹屽叏鏄彟澶栦竴涓棶棰樸?br>
銆銆濡傛灉浣犱粛鎬鐤戣繖縐嶆ц兘浼樺娍錛屾湁鍙﹀鐨勭悊鐢辨潵璇存槑浣犱負浠涔堜笉寰椾笉浣跨敤C++/CLI鑰屼笉鏄疌#鎴朧B.NET鈥斺旀簮鐮佽啫鑳錛佷笅闈㈡槸涓涓狢++鍑芥暟鐨勪緥瀛愶紝瀹冧嬌鐢ㄤ簡IP甯姪鑰匒PI鏉ユ灇涓句竴鍙版満鍣ㄤ笂鐨勭綉緇滈傞厤鍣ㄥ茍涓斿垪鍑轟笌姣忎釜閫傞厤鍣ㄧ浉鑱旂郴鐨勬墍鏈塈P鍦板潃銆?br>
銆銆4) 鏋氫婦n/w閫傞厤鍣ㄧ殑C++浠g爜
void ShowAdapInfo()
{
PIP_ADAPTER_INFO pAdapterInfo = NULL;
ULONG OutBufLen = 0;
//寰楀埌闇瑕佺殑緙撳啿鍖哄ぇ灝?br>if(GetAdaptersInfo(NULL,&OutBufLen)==ERROR_BUFFER_OVERFLOW)
{
int divisor = sizeof IP_ADAPTER_INFO;
#if _MSC_VER >= 1400
if( sizeof time_t == 8 ) divisor -= 8;
#endif
pAdapterInfo = new IP_ADAPTER_INFO[OutBufLen/divisor];
//鍙栧緱閫傞厤鍣ㄤ俊鎭?br>if( GetAdaptersInfo(pAdapterInfo, &OutBufLen) != ERROR_SUCCESS )
{//璋冪敤澶辮觸 }
else
{
int index = 0;
while(pAdapterInfo)
{
Console::WriteLine(gcnew String(pAdapterInfo->Description));
Console::WriteLine("IP Address list : ");
PIP_ADDR_STRING pIpStr = &pAdapterInfo->IpAddressList;
while(pIpStr)
{
Console::WriteLine(gcnew tring(pIpStr->IpAddress.String));
pIpStr = pIpStr->Next;
}
pAdapterInfo = pAdapterInfo->Next;
Console::WriteLine();
}
}
delete[] pAdapterInfo;
}
}
銆銆鐜板湪璁╂垜浠湅涓涓嬌鐢≒/Invoke鐨凜#鐗堟湰銆?br>
銆銆5) 浣跨敤P/Invoke鎶鏈殑C#鐗堟湰
const int MAX_ADAPTER_NAME_LENGTH = 256;
const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
const int ERROR_BUFFER_OVERFLOW = 111;
const int ERROR_SUCCESS = 0;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADDRESS_STRING
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string Address;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADDR_STRING
{
public IntPtr Next;
public IP_ADDRESS_STRING IpAddress;
public IP_ADDRESS_STRING Mask;
public Int32 Context;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct IP_ADAPTER_INFO
{
public IntPtr Next;
public Int32 ComboIndex;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst = MAX_ADAPTER_NAME_LENGTH + 4)]
public string AdapterName;
[MarshalAs(UnmanagedType.ByValTStr,
SizeConst = MAX_ADAPTER_DESCRIPTION_LENGTH + 4)]
public string AdapterDescription;
public UInt32 AddressLength;
[MarshalAs(UnmanagedType.ByValArray,
SizeConst = MAX_ADAPTER_ADDRESS_LENGTH)]
public byte[] Address;
public Int32 Index;
public UInt32 Type;
public UInt32 DhcpEnabled;
public IntPtr CurrentIpAddress;
public IP_ADDR_STRING IpAddressList;
public IP_ADDR_STRING GatewayList;
public IP_ADDR_STRING DhcpServer;
public bool HaveWins;
public IP_ADDR_STRING PrimaryWinsServer;
public IP_ADDR_STRING SecondaryWinsServer;
public Int32 LeaseObtained;
public Int32 LeaseExpires;
}
[DllImport("iphlpapi.dll", CharSet = CharSet.Ansi)]
public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref int pBufOutLen);
static void ShowAdapInfo()
{
int OutBufLen = 0;
//寰楀埌闇瑕佺殑緙撳啿鍖哄ぇ灝?br>if( GetAdaptersInfo(IntPtr.Zero, ref OutBufLen) ==
ERROR_BUFFER_OVERFLOW )
{
IntPtr pAdapterInfo = Marshal.AllocHGlobal(OutBufLen);
//鍙栧緱閫傞厤鍣ㄤ俊鎭?br>if( GetAdaptersInfo(pAdapterInfo, ref OutBufLen) != ERROR_SUCCESS )
{ //璋冪敤澶辮觸浜?}
else{
while(pAdapterInfo != IntPtr.Zero)
{
IP_ADAPTER_INFO adapinfo =
(IP_ADAPTER_INFO)Marshal.PtrToStructure(
pAdapterInfo, typeof(IP_ADAPTER_INFO));
Console.WriteLine(adapinfo.AdapterDescription);
Console.WriteLine("IP Address list : ");
IP_ADDR_STRING pIpStr = adapinfo.IpAddressList;
while (true){
Console.WriteLine(pIpStr.IpAddress.Address);
IntPtr pNext = pIpStr.Next;
if (pNext == IntPtr.Zero)
break;
pIpStr = (IP_ADDR_STRING)Marshal.PtrToStructure(
pNext, typeof(IP_ADDR_STRING));
}
pAdapterInfo = adapinfo.Next;
Console.WriteLine();
}
}
Marshal.FreeHGlobal(pAdapterInfo);
}
}
3. 鏍堣涔夊拰紜畾鎬х殑鏋愭瀯
銆銆C++緇忕敱鏍堣涔夋ā浠跨粰浜嗘垜浠‘瀹氭х殑鏋愭瀯銆傜畝璦涔嬶紝鏍堣涔夋槸Dispose妯″紡鐨勮壇濂界殑璇硶鏇夸唬鍝併備絾鏄畠鍦ㄨ涔変笂姣擟# using鍧楄娉曟洿鐩磋浜涖傝鐪嬩笅鍒楃殑C#鍜孋++浠g爜孌碉紙閮藉仛涓鏍風殑浜嬫儏-榪炴帴涓や釜鏂囦歡鐨勫唴瀹瑰茍鎶婂畠鍐欏埌絎笁涓枃浠朵腑錛夈?br>
銆銆1) C#浠g爜--浣跨敤鍧楄涔?br>
public static void ConcatFilestoFile(String file1, String file2, String outfile)
{
String str;
try{
using (StreamReader tr1 = new StreamReader(file1))
{
using (StreamReader tr2 = new StreamReader(file2))
{
using (StreamWriter sw = new StreamWriter(outfile))
{
while ((str = tr1.ReadLine()) != null)
sw.WriteLine(str);
while ((str = tr2.ReadLine()) != null)
sw.WriteLine(str);
}
}
}
}
catch (Exception e)
{ Console.WriteLine(e.Message); }
}
銆銆2) C++浠g爜--鏍堣涔?br>
static void ConcatFilestoFile(String^ file1, String^ file2, String^ outfile)
{
String^ str;
try{
StreamReader tr1(file1);
StreamReader tr2(file2);
StreamWriter sw(outfile);
while(str = tr1.ReadLine())
sw.WriteLine(str);
while(str = tr2.ReadLine())
sw.WriteLine(str);
}
catch(Exception^ e)
{ Console::WriteLine(e->Message); }
}
銆銆C#浠g爜涓庣浉絳夌殑C++ 浠g爜鐩告瘮涓嶄粎鍏嶄笉浜嗗啑闀匡紝鑰屼笖using鍧楄娉曡紼嬪簭鍛樿嚜宸辨槑紜湴鎸囧畾浠栨兂鍦ㄥ摢鍎胯皟鐢―ispose錛坲sing鍧楃殑緇撴潫澶勶級錛岃屼嬌鐢–++/CLI鐨勬爤璇箟錛屽彧闇璁╃紪璇戝櫒浣跨敤甯歌鐨勮寖鍥磋鍒欐潵澶勭悊瀹冨嵆鍙備簨瀹炰笂錛岃繖浣垮緱鍦–#涓慨鏀逛唬鐮佹瘮鍦–++涓洿涔忓懗-浣滀負涓瀹炰緥錛岃鎴戜滑淇敼榪欎簺浠g爜浠ヤ究鍗充嬌浠呭瓨鍦ㄤ竴涓緭鍏ユ枃浠朵篃鑳藉垱寤鴻緭鍑烘枃浠躲傝鐪嬩笅闈慨鏀瑰悗鐨凜#鍜孋++浠g爜銆?br>
銆銆3) 淇敼鍚庣殑C#浠g爜
public static void ConcatFilestoFile(String file1, String file2, String outfile)
{
String str;
try{
using (StreamWriter sw = new StreamWriter(outfile))
{
try{
using (StreamReader tr1 = new StreamReader(file1))
{
while ((str = tr1.ReadLine()) != null)
sw.WriteLine(str);
}
}
catch (Exception) { }
using (StreamReader tr2 = new StreamReader(file2))
{
while ((str = tr2.ReadLine()) != null)
sw.WriteLine(str);
}
}
}
catch (Exception e){ }
}
銆銆鎶婇拡瀵筍treamWriter鐨剈sing鍧楁斁鍒伴《灞傞渶瑕侀噸鏂拌皟鏁磚sing鍧楃粨鏋?-榪欏湪涓婇潰鎯呭喌涓嬫樉鐒朵笉鏄釜澶ч棶棰橈紝浣嗘槸瀵逛簬瀹為檯寮鍙戜腑鐨勪慨鏀癸紝榪欏彲鑳芥槸鐩稿綋妯$硦鐨勪笖鏄撳鑷撮昏緫閿欒鐨勩?br>
銆銆4) 淇敼鍚庣殑C++浠g爜
static void ConcatFilestoFile(String^ file1, String^ file2, String^ outfile)
{
String^ str;
try{
StreamWriter sw(outfile);
try{
StreamReader tr1(file1);
while(str = tr1.ReadLine())
sw.WriteLine(str);
}
catch(Exception^){}
StreamReader tr2(file2);
while(str = tr2.ReadLine())
sw.WriteLine(str);
}
catch(Exception^){}
}
銆銆榪欐牱涓嶆槸姣斿湪C#涓殑鍋氭洿瀹規槗浜涘悧錛熸垜鎭板ソ鎶奡treamWriter澹版槑縐誨埌浜嗛《閮ㄥ茍澧炲姞浜嗕竴涓澶栫殑try鍧楋紝灝辮繖浜涖傜敋鑷沖浜庤薄鍦ㄦ垜鐨勭ず渚嬩唬鐮佺墖鏂腑鐨勭悙紕庝簨鎯咃紝濡傛灉鎵娑夊強鐨勫鏉傛у湪C++涓ぇ澶у噺灝戯紝閭d箞錛屽綋浣犲伐浣滀簬鏇村ぇ鐨勫伐紼嬫椂浣犺兘鎯寵薄浣跨敤鏍堣涔夊浣犵殑緙栫爜鏁堢巼鍗冧竾鐨勫獎鍝嶃?br>
銆銆榪樹笉紜俊錛熷ソ錛岃鎴戜滑鐪嬩竴涓嬫垚鍛樺璞″拰瀹冧滑鐨勬瀽鏋勫惂銆侷magine CLI GC綾籖1鍜孯2錛屼簩鑰呴兘瀹炵幇浜咺disposable鎺ュ彛涓旈兘鏈夊嚱鏁癋()錛岃繕鏈変竴涓狢LI GC綾籖錛屽畠鏈塕1鍜孯2鎴愬憳鍜屼竴涓嚱鏁癋()-瀹冨唴閮ㄥ湴璋冪敤R1鍜孯2涓婄殑F()鎴愬憳鍑芥暟銆傝鎴戜滑鍏堢湅C#瀹炵幇銆?br>
銆銆5) 涓涓猟isposable綾葷戶鎵垮眰嬈$殑C#瀹炵幇
class R1 : IDisposable{
public void Dispose() { }
public void F() { }
}
class R2 : IDisposable{
public void Dispose() { }
public void F() { }
}
class R : IDisposable{
R1 m_r1 = new R1();
R2 m_r2 = new R2();
public void Dispose()
{
m_r1.Dispose();
m_r2.Dispose();
}
public void F()
{
m_r1.F();
m_r2.F();
}
public static void CallR()
{
using(R r = new R())
{r.F();}
}
}
銆銆榪欓噷鏈夊嚑浠朵簨鎯呰鍋氾細蹇呴』涓烘瘡涓猟isposable 綾繪墜宸ュ疄鐜癐Disposable鎺ュ彛錛屽浜庡叿鏈夋垚鍛楻1鍜孯2鐨勭被R錛孌ispose鏂規硶涔熼渶瑕佽皟鐢ㄦ垚鍛樼被涓婄殑Dispose銆傜幇鍦ㄨ鎴戜滑鍒嗘瀽涓婇潰鍑犱釜綾葷殑C++瀹炵幇銆?br>
銆銆6) 絳変環鐨凜++瀹炵幇
ref class R1
{
public:
~R1(){}
void F(){}
};
ref class R2
{
public:
~R2(){}
void F(){}
};
ref class R
{
R1 m_r1;
R2 m_r2;
public:
~R(){}
void F()
{
m_r1.F();
m_r2.F();
}
static void CallR()
{
R r;
r.F();
}
};
銆銆娉ㄦ剰錛岃繖閲屼笉鍐嶆湁鎵嬪伐鐨処disposable鎺ュ彛瀹炵幇(鎴戜滑鐨勭被涓粎寤虹珛浜嗘瀽鏋勫櫒)鑰屼笖鏈濂界殑閮ㄥ垎--綾籖鐨勬瀽鏋勫櫒(Dispose鏂規硶)騫舵病鏈夊湪璇ョ被鍙兘鍚湁鐨勫彲閲婃斁鐨勬垚鍛樹笂璋冪敤Dispose-瀹冩病鏈夊繀瑕佽繖鏍峰仛錛岀紪璇戝櫒鑷姩涓轟箣鐢熸垚鎵鏈夌殑浠g爜錛?
4. 娣峰悎綾誨瀷
銆銆鎴戜滑鐭ラ亾錛孋++鏀寔鏈満綾誨瀷-鎬繪槸濡傛錛汣++鏀寔CLI綾誨瀷-鏈枃姝f槸鐗瑰埆寮鴻皟榪欎竴鐐癸紱瀹冭繕鏀寔娣峰悎綾誨瀷-鍏鋒湁CLI鎴愬憳鐨勬湰鏈虹被鍨嬪拰鍏鋒湁鏈満鎴愬憳鐨凜LI綾誨瀷錛佽灝界鑰冭檻鎵鏈変綘鑳界殑鍙兘闇姹傘?br>
銆銆娉ㄦ剰錛岃皥鍒癢hidbey錛屾販鍚堢被鍨嬪疄鐜拌繕涓嶅畬鏁達紱灝辨垜浠嶣randon錛孒erb鍜孯onald鍙戣〃鐨勬潗鏂欑殑鐞嗚В寰楃煡錛屽瓨鍦ㄨ繖縐嶇浉褰撻叿鐨勭被鍨?-緇熶竴妯″瀷錛屽畠灝嗗湪Orcas涓疄鐜?-浣犺兘澶熷湪鏈満C++鍫嗕笂new/delete CLI綾誨瀷錛岃屼笖涔熻兘澶熷湪CLI鍫嗕笂gcnew/delete鏈満綾誨瀷銆備絾鏃㈢劧榪欐槸Whidbey浠ュ悗鐨勪笢瑗匡紝鏈枃涓嶈璁虹粺涓妯″瀷銆?br>
銆銆鍦ㄦ垜璋堣浣犱綍鏃朵嬌鐢ㄦ販鍚堢被鍨嬩互鍓嶏紝鎴戞兂鍚戜綘璇存槑浠涔堟槸娣峰悎綾誨瀷銆傚鏋滀綘鐞嗚В娣峰悎綾誨瀷錛岃璺寵繃涓嬮潰鍑犳銆傝繖閲屽紩鐢˙randon Bray鐨勮娉曪細"涓縐嶆販鍚堢被鍨嬶紝鎴栬呮槸鏈満綾籸ef綾伙紙闇瑕佹湁瀵硅薄鎴愬憳錛夛紝鎴栬呮槸閫氳繃澹版槑鎴栫戶鎵胯鍒嗛厤鍦ㄥ瀮鍦懼洖鏀跺爢鎴栨湰鏈哄爢涓婄殑銆?鍥犳濡傛灉浣犳湁涓涓墭綆$被鍨嬫垨鑰呮湁涓涓湁鎵樼鎴愬憳鐨勬湰鏈虹被鍨嬶紝浣犲氨鏈変簡涓涓販鍚堢被鍨嬨俈C++ Whidbey涓嶇洿鎺ユ敮鎸佹販鍚堢被鍨?緇熶竴綾誨瀷妯″瀷鏄竴縐峎hidbey涔嬪悗鐨勬蹇?錛屼絾鏄畠緇欐垜浠垝瀹氫簡瀹炵幇娣峰悎綾誨瀷鐨勬潯浠躲傝鎴戜滑寮濮嬭璁哄寘鍚墭綆℃垚鍛樼殑鏈満綾誨瀷銆?br>
ref class R
{
public:
void F(){}
//鍋囧畾 non-trivial ctor/dtor
R(){}
~R(){}
};
銆銆鍦ㄦ垜鐨勪緥瀛愪腑錛岃鎯寵鎵樼綾誨瀷R鏈変竴涓猲on-trivial鏋勯犲櫒鍜屼竴涓猲on-trivial鏋愭瀯鍣ㄣ?br>
class Native
{
private:
gcroot<R^> m_ref;
public:
Native():
m_ref(gcnew R()){}
~Native()
{ delete m_ref; }
void DoF()
{ m_ref->F(); }
};
銆銆鏃㈢劧錛屾垜涓嶈兘鍦ㄦ垜鐨勭被涓嫢鏈変竴涓猂鎴愬憳錛屾垜浣跨敤浜唃croot妯℃澘綾?鍦╣croot.h涓0鏄庯紝浣嗘槸浣犺鐢?#include vcclr.h")錛屽畠鍖呰浜哠ystem::Runtime::InteropServices::GCHandle緇撴瀯銆傚畠鏄釜璞$被涓鏍風殑鐏墊晱鎸囬拡錛屽畠閲嶈澆浜嗚繍綆楃->浠ヨ繑鍥炵敤浣滄ā鏉垮弬鏁扮殑鎵樼綾誨瀷銆傚洜姝ゅ湪涓婇潰綾諱腑錛屾垜鍙互浣跨敤m_ref錛屽氨濂借薄鎴戝凡緇忓0鏄庡畠鏄疪^錛岃屼笖浣犺兘鍦―oF鍑芥暟涓湅鍒拌繖姝e湪璧蜂綔鐢ㄣ傚疄闄呬笂浣犲彲浠ヨ妭鐪乨elete錛岃繖鍙互閫氳繃浣跨敤auto_gcroot(綾諱技浜巗td::auto_ptr錛屽湪msclr\auto_gcroot.h鏂囦歡涓0鏄?浠f浛gcroot鏉ュ疄鐜般備笅闈㈡槸涓涓洿濂戒簺鐨勪嬌鐢╝uto_gcroot鐨勫疄鐜般?br>
class NativeEx
{
private:
msclr::auto_gcroot<R^> m_ref;
public:
NativeEx() : m_ref(gcnew R()){}
void DoF()
{ m_ref->F(); }
};
銆銆涓嬮潰璁╂垜浠湅鐩稿弽鐨勬儏褰細涓涓狢LI綾葷殑鏈満鎴愬憳銆?br>
ref class Managed
{
private:
Native* m_nat;
public:
Managed():m_nat(new Native()){ }
~Managed()
{ delete m_nat; }
!Managed()
{ delete m_nat;
#ifdef _DEBUG
throw gcnew Exception("Oh, finalizer got called!");
#endif
}
void DoF()
{ m_nat->DoF(); }
};
銆銆鎴戜笉鑳藉畾涔変竴涓狽ative瀵硅薄鏉ヤ綔涓轟竴涓猺ef綾繪垚鍛橈紝鍥犳闇瑕佷嬌鐢ㄤ竴涓狽ative*瀵硅薄鏉ヤ唬鏇褲傛垜鍦ㄦ瀯閫犲櫒涓璶ew璇ative瀵硅薄錛岀劧鍚庡湪鏋愭瀯鍣ㄥ拰finalizer涓璬elete瀹冦傚鏋滀綘榪愯璇ュ伐紼嬬殑璋冭瘯鐗堬紝鍦ㄦ墽琛屽埌finalizer鏃跺皢鎶涘嚭涓涓紓甯? 鍥犳寮鍙戣呭彲浠ラ┈涓婃坊鍔犱竴涓delete鐨勮皟鐢ㄦ垨涓轟粬鐨凜LI綾誨瀷浣跨敤鏍堣涔夋妧鏈傚鎬殑鏄紝搴撳紑鍙戝皬緇勬病鏈夊緩绔嬩竴涓猤croot鐨勫弽鍚戝疄鐜?浣嗚繖涓嶆槸涓ぇ闂錛屾垜浠彲浠ヨ嚜宸卞啓銆?br>
template<typename T> ref class nativeroot
{
T* m_t;
public:
nativeroot():m_t(new T){}
nativeroot(T* t):m_t(t){}
T* operator->()
{ return m_t; }
protected:
~nativeroot()
{ delete m_t; }
!nativeroot()
{
delete m_t;
#ifdef _DEBUG
throw gcnew Exception("Uh oh, finalizer got called!");
#endif
}
};
銆銆榪欎粎鏄釜鐩稿綋綆鍗曠殑鐏墊晱鎸囬拡瀹炵幇錛屽氨璞′竴涓礋璐f湰鏈哄璞″垎閰?鍥炴敹鐨剅ef綾匯備笉綆℃庢牱錛屽熷姪nativeroot妯℃澘綾伙紝鎴戜滑鍙互濡備笅淇敼鎵樼綾伙細
ref class ManagedEx
{
private:
nativeroot<Native> m_nat;
public:
void DoF()
{ m_nat->DoF(); }
};
銆銆濂斤紝鍏充簬娣峰悎綾誨瀷鐨勬渶澶ч棶棰樻槸浠涔堝憿錛熶綘鍙兘闂傛渶澶ч棶棰樻槸錛岀幇鍦ㄤ綘鑳芥販鍚堜嬌鐢ㄤ綘鐨凪FC銆丄TL銆乄TL銆丼TL浠g爜浠撳簱鍜?NET妗嗘灦錛屽茍鐢ㄥ彲鑳界殑鏈鐩存帴鐨勬柟寮?鍙渶鍐欎綘鐨勬販鍚堟ā寮忎唬鐮佸茍緙栬瘧瀹炵幇!浣犲彲浠ュ緩绔嬪湪涓涓狣LL搴撲腑寤虹珛MFC 綾伙紝鐒跺悗寤虹珛涓涓?NET搴旂敤紼嬪簭鏉ヨ皟鐢ㄨ繖涓狣LL錛岃繕闇瑕佹妸.NET綾繪垚鍛樻坊鍔犲埌浣犵殑MFC綾伙紙涔熷疄鐜板彲浠ョ浉鍙嶇殑鎯呭喌錛夈?br>
銆銆浣滀負涓渚嬶紝璁炬兂浣犳湁涓MFC瀵硅瘽妗?-瀹冮氳繃涓涓琛岀殑緙栬緫妗嗘帴鍙楁潵鑷敤鎴風殑鏁版嵁-鐜板湪錛屼綘鏈変竴鏂扮殑瑕佹眰-鏄劇ず涓涓彧璇葷紪杈戞錛屽畠灝嗘樉紺哄綋鍓嶅湪璇ュ琛岀紪杈戞涓枃鏈殑md5鍝堝笇緇撴灉銆備綘鐨勯槦鍙嬫鍦ㄦ偛鍙逛粬浠皢蹇呴』鑺辮垂鍑犱釜灝忔椂閽葷爺crypto API錛岃屼綘鐨勪笂鍙稿湪鎷呭咖浣犱滑鍙兘蹇呴』瑕佷拱涓涓涓夋柟鍔犲瘑搴擄紱閭f鏄綘鍦ㄤ粬浠潰鍓嶆爲绔嬪艦璞$殑鏃跺欙紝浣犲甯冧綘灝嗗湪15鍒嗛挓鍐呭仛瀹岃繖欏逛換鍔°備笅闈㈡槸瑙e喅鐨勫姙娉曪細
銆銆娣誨姞涓涓柊鐨勭紪杈戞鍒頒綘鐨勫璇濇璧勬簮涓紝騫朵笖娣誨姞鐩稿簲鐨凞DX鍙橀噺銆傞夋嫨/clr緙栬瘧妯″紡騫朵笖娣誨姞涓嬪垪浠g爜鍒頒綘鐨勫璇濇鐨勫ご鏂囦歡涓細
#include <msclr\auto_gcroot.h>
using namespace System::Security::Cryptography;
銆銆浣跨敤auto_gcroot妯℃澘鏉ュ0鏄庝竴涓狹D5CryptoServiceProvider鎴愬憳錛?br>
protected:
msclr::auto_gcroot<MD5CryptoServiceProvider^> md5;
銆銆鍦∣nInitDialog榪囩▼涓紝gcnew MD5CryptoServiceProvider鎴愬憳銆?br>
md5 = gcnew MD5CryptoServiceProvider();
銆銆騫朵笖涓哄琛岀紪杈戞娣誨姞涓涓狤N_CHANGE澶勭悊鍣細
void CXxxxxxDlg::OnEnChangeEdit1()
{
using namespace System;
CString str;
m_mesgedit.GetWindowText(str);
array<Byte>^ data = gcnew array<Byte>(str.GetLength());
for(int i=0; i<str.GetLength(); i++)
data[i] = static_cast<Byte>(str[i]);
array<Byte>^ hash = md5->ComputeHash(data);
CString strhash;
for each(Byte b in hash)
{
str.Format(_T("%2X "),b);
strhash += str;
}
m_md5edit.SetWindowText(strhash);
}
銆銆榪欓噷浣跨敤浜嗘販鍚堢被鍨嬶細涓涓湰鏈篊dialog媧劇敓綾伙紝璇ョ被鍚湁涓涓狹D5CryptoServiceProvider鎴愬憳(CLI綾誨瀷)銆備綘鍙互杞繪槗鍦拌瘯楠岀浉鍙嶇殑鎯呭喌錛堝鏃╂湡鐨勪唬鐮佺墖鏂凡鏄劇ず鐨勶級鈥斺斿彲浠ュ緩绔嬩竴涓猈indows琛ㄥ崟搴旂敤紼嬪簭鑰屼笖鍙兘鎯沖埄鐢ㄤ竴涓湰鏈虹被搴?-榪欎笉鎴愰棶棰橈紝浣跨敤涓婇潰瀹氫箟鐨勬ā鏉縩ativeroot鍗沖彲銆?br>
5. 鎵樼妯℃澘
銆銆涔熻浣犲娉涘瀷鐨勬蹇靛凡寰堟竻妤氫簡錛屽畠甯姪浣犻伩鍏嶈繘鍏++鐨勬ā鏉挎ⅵ欖囷紝瀹冩槸瀹炵幇妯℃澘鐨勬渶浣蟲柟寮忥紝絳夌瓑銆傚ソ錛屽亣璁捐繖浜涘叏閮ㄦ紜紝C++/CLI鏀寔娉涘瀷灝辮薄浠諱綍鍏跺畠CLI璇█涓鏍?浣嗘槸瀹冩湁鑰屽叾瀹冧竴浜汣LI璇█榪樻病鏈夌殑鏄畠榪樻敮鎸佹墭綆℃ā鏉?涔熷氨鏄ā鏉垮寲鐨剅ef鍜寁alue綾匯傚鏋滀綘浠ュ墠浠庢湭浣跨敤榪囨ā鏉匡紝浣犱笉鑳戒竴涓嬫璧忚繖涔堝浼樼偣錛屼絾鏄鏋滀綘鏈夋ā鏉夸嬌鐢ㄨ儗鏅屼笖浣犲凡鍙戠幇浜嗘硾鍨嬩腑瀛樺湪鐨勫彲鑳介檺鍒朵綘緙栫爜鐨勬柟寮忥紝鎵樼妯℃澘灝嗕細澶уぇ鍑忚交浣犵殑璐熸媴銆備綘鑳借仈鍚堜嬌鐢ㄦ硾鍨嬪拰妯℃澘- 浜嬪疄涓婃湁鍙兘鐢ㄤ竴涓墭綆$被鍨嬬殑妯℃澘鍙傛暟鏉ュ疄渚嬪寲涓涓硾鍨嬬被鍨?灝界鐩稿弽鐨勬儏褰㈡槸涓嶅彲鑳界殑錛屽洜涓鴻繍琛屾椂鍒誨疄渚嬪寲鐢辨硾鍨嬫墍鐢?銆係TL.NET (鎴朣TL/CLR)浠ュ悗璁ㄨ錛岃寰堝ソ鍦板埄鐢ㄦ硾鍨嬪拰鎵樼妯℃澘鐨勬販鍚堢紪紼嬪惂銆?br>
銆銆娉涘瀷浣跨敤鐨勫瓙綾誨瀷綰︽潫鏈哄埗灝嗛槻姝綘鍐欏嚭涓嬮潰鐨勪唬鐮侊細
generic<typename T> T Add(T t1, T t2)
{ return t1 + t2; }
銆銆緙栬瘧閿欒錛?br>
error C2676: binary ’+’ : ’T’ does not define this operator or a conversion to a type acceptable to the predefined operator
銆銆鐜板湪璇風湅鐩稿簲鐨勬ā鏉跨増鏈細
template<typename T> T Add(T t1, T t2)
{ return t1 + t2; }
銆銆閭d箞灝卞彲浠ヨ繖鏍峰仛錛?br>
int x1 = 10, x2 = 20;
int xsum = Add<int>(x1, x2);
銆銆榪樺彲浠ヨ繖鏍峰仛錛?br>
ref class R
{
int x;
public:
R(int n):x(n){}
R^ operator+(R^ r)
{ return gcnew R(x + r->x); }
};
//...
R^ r1 = gcnew R(10);
R^ r2 = gcnew R(20);
R^ rsum = Add<R^>(r1, r2);
銆銆榪欏湪涓涓薄int鐨勬湰鏈虹被鍨嬩互鍙婁竴涓猺ef綾誨瀷(鍙ref綾誨瀷鏈変竴涓?榪愮畻絎?鎯呭喌涓嬮兘鑳藉伐浣滆壇濂姐傝繖涓硾鍨嬬己鐐逛笉鏄竴涓皟璇曢敊璇垨緙洪櫡-瀹冩槸璁捐閫犳垚鐨勩傛硾鍨嬬殑瀹炰緥鍖栨槸鍦ㄨ繍琛屾椂閫氳繃璋冪敤閰嶄歡闆嗗疄鐜扮殑錛屽洜姝ょ紪璇戝櫒涓嶈兘紜煡涓鐗瑰畾鎿嶄綔鑳借鏂借浜庝竴涓硾鍨嬪弬鏁幫紝闄ら潪瀹冨尮閰嶄竴涓瓙綾誨瀷綰︽潫錛屽洜姝ょ紪璇戝櫒鍦ㄥ畾涔夋硾鍨嬫椂瑙e喅榪欎釜闂銆傚綋浣犱嬌鐢ㄦ硾鍨嬫椂鐨勫彟澶栦竴涓Θ紕嶆槸錛屽畠涓嶄細鍏佽浣犱嬌鐢ㄩ潪綾誨瀷鍙傛暟銆備笅鍒楁硾鍨嬬被瀹氫箟涓嶄細緙栬瘧錛?br>
generic<typename T, int x> ref class G{};
銆銆緙栬瘧閿欙細
error C2978: syntax error : expected ’typename’ or ’class’; found type ’int’; non-type parameters are not supported in generics
銆銆涓庢墭綆℃ā鏉跨浉姣旇緝錛?br>
template<typename T, int x = 0> ref class R{};
銆銆濡傛灉浣犲紑濮嬫劅嬋C++鍚戜綘鎻愪緵浜嗘硾鍨嬪拰鎵樼妯℃澘錛岄偅涔堣鐪嬩笅闈㈣繖涓涓緥瀛愶細
template<typename T> ref class R{
public:
void F()
{ Console::WriteLine("hey"); }
};
template<> ref class R<int>
{
public:
void F()
{ Console::WriteLine("int"); }
};
銆銆浣犱笉鑳界敤娉涘瀷榪欐牱緙栫爜錛涘惁鍒欙紝灝嗕駭鐢燂細
銆銆緙栬瘧閿欙細error C2979: explicit specializations are not supported in generics
銆銆浣嗗彲浠ュ湪緇ф壙閾句腑娣峰悎浣跨敤妯℃澘鍜屾硾鍨嬶細
generic<typename T> ref class Base
{
public:
void F1(T){}
};
template<typename T> ref class Derived : Base<T>
{
public:
void F2(T){}
};
//...
Derived<int> d;
d.F1(10);
d.F2(10);
銆銆鏈鍚庯紝浣犱笉鑳戒粠涓涓硾鍨嬪弬鏁扮被鍨嬫淳鐢熶竴涓硾鍨嬬被銆?br>
銆銆涓嬪垪浠g爜涓嶄細鎴愬姛緙栬瘧錛?br>
generic<typename T> ref class R : T
{};
銆銆error C3234: a generic class may not derive from a generic type parameter
銆銆妯℃澘璁╀綘榪欐牱鍋?濂藉儚浣犺繕涓嶇煡閬撹繖浜?錛?br>
ref class Base{
public:
void F(){}
};
generic<typename T> ref class R : T
{};
//...
R<Base> r1;
r1.F();
銆銆榪欐牱錛屽綋浣犱笅嬈¢亣鍒板娉涘瀷鐨勮船璋ゆ椂錛屼綘灝辯煡閬撹鎬庝箞鍋氫簡銆?br>
銆銆6. STL/CLR
銆銆褰撳ぇ閲忎嬌鐢⊿TL鐨凜++寮鍙戣呰漿鍚?NET1/1.1鏃朵竴瀹氭劅瑙夐潪甯稿埆鎵紝浠栦滑涓殑璁稿鍙兘浼氭斁寮冨茍杞洖鍒板師鏉ョ殑鏈満緙栫爜銆備粠鎶鏈笂璁詫紝浣犺兘緇撳悎.NET綾誨瀷(using gcroot)浣跨敤鏈満STL錛屼絾鏄駭鐢熺殑緇撴灉浠g爜鍙兘鐩稿綋浣庢晥錛屾洿涓嶇敤璇存槸涓戦檵浜嗭細
std::vector< gcroot<IntPtr> >* m_vec_hglobal;
//...
for each(gcroot<IntPtr> ptr in *m_vec_hglobal)
{ Marshal::FreeHGlobal(ptr);}
銆銆澶фVC++灝忕粍鑰冭檻鍒頒簡榪欎簺騫跺喅瀹氬湪Whidbey浠ュ悗錛屼粬浠細鎻愪緵STL.NET錛堟垨STL/CLR錛夊茍鍙互鍗曠嫭浠庣綉涓婁笅杞姐?br>
銆銆浣犲彲鑳介棶涓轟粈涔堬紵Stan Lippman錛屽湪浠栫殑MSDN鏂囩珷(STL.NET Primer)涓粰鍑轟簡3鏉″師鍥狅細
銆銆·鍙墿灞曟?-STL璁捐鎶婄畻娉曞拰瀹瑰櫒闅旂鍒拌嚜宸辯殑搴旂敤絀洪棿-涔熷氨鏄綘鍙互鏈変竴緇勫鍣ㄥ拰涓緇勭畻娉曪紝騫朵笖浣犺兘鍦ㄤ換浣曚竴涓鍣ㄤ笂浣跨敤榪欎簺綆楁硶錛涘悓鏃朵綘鑳藉湪浠諱綍涓涓畻娉曚腑浣跨敤榪欎簺瀹瑰櫒銆傚洜姝わ紝濡傛灉浣犳坊鍔犱竴縐嶆柊鐨勭畻娉曪紝浣犺兘鍦ㄤ換浣曚竴縐嶅鍣ㄤ腑浣跨敤瀹冿紱鍚屾牱錛屼竴涓柊鐨勫鍣ㄤ篃鍙互涓庣幇鏈夌畻娉曢厤鍚堜嬌鐢ㄣ?br>
銆銆·緇熶竴鎬?-鎵鏈夋牳蹇僀++寮鍙戣呴泦涓湪涓璧鳳紝姹囬泦璧蜂粬浠簿濡欑殑STL涓撻暱錛屽啀浣跨敤浠栦滑鐨勪笓闀垮垯杞昏濺鐔熻礬銆傝杈冨ソ鍦頒嬌鐢⊿TL闇瑕佽姳璐規椂闂?鐒惰屼竴鏃︿綘鎺屾彙浜嗗畠錛屼綘灝辨湁浜嗗湪.NET涓栫晫涓嬌鐢ㄤ綘鐨勬妧宸х殑鏄庢樉浼樺娍銆備笉鏄悧錛?br>
銆銆·鎬ц兘--STL.NET閫氳繃浣跨敤瀹炵幇娉涘瀷鎺ュ彛鐨勬墭綆℃ā鏉垮疄鐜般傚茍涓旀棦鐒跺畠鐨勬牳蹇冨凡鐢–++鍜屾墭綆℃ā鏉跨紪鐮侊紝鍙互鏈熺浖瀹冩瘮鍦˙CL涓婁嬌鐢ㄧ殑娉涘瀷瀹瑰櫒鏇村叿鏈夋ц兘浼樺娍銆?br>
銆銆浣跨敤榪嘢TL鐨勪漢涓嶉渶瑕佷換浣曠ず鑼冿紝鎵浠ヤ笅闈唬鐮佹湁鐩婁簬浠ュ墠娌℃湁浣跨敤榪嘢TL鐨勪漢銆?br>
vector<String^> vecstr;
vecstr.push_back("wally");
vecstr.push_back("nish");
vecstr.push_back("smitha");
vecstr.push_back("nivi");
deque<String^> deqstr;
deqstr.push_back("wally");
deqstr.push_back("nish");
deqstr.push_back("smitha");
deqstr.push_back("nivi");
銆銆鎴戜嬌鐢ㄤ簡涓や釜STL.NET瀹瑰櫒-vector鍜宒eque錛屽茍瑁呮弧涓や釜瀹瑰櫒錛屼嬌鍏剁湅璧鋒潵鐩稿悓(鍦ㄤ袱涓鍣ㄤ腑閮戒嬌鐢ㄤ簡push_back)銆傜幇鍦紝鎴戝皢鍦ㄤ袱涓鍣ㄤ笂浣跨敤replace綆楁硶-鎴戜滑鍐嶆鐪嬪埌錛岃繖浜涗唬鐮佹槸寰堢浉鍚岀殑銆?br>
replace(vecstr.begin(), vecstr.end(),
gcnew String("nish"), gcnew String("jambo"));
replace(deqstr.begin(), deqstr.end(),
gcnew String("nish"), gcnew String("chris"));
銆銆榪欓噷鐗瑰埆瑕佹敞鎰忕殑鏄垜浣跨敤浜?鍚屾牱"鐨勭畻娉?-replace騫跺湪涓や釜涓嶅悓STL瀹瑰櫒涓婁嬌鐢ㄧ浉鍚岀殑鍑芥暟璋冪敤銆傝繖鏄綋Stan璋堝強"鍙墿灞曟?鏃剁殑鎰忔濄備笅闈㈡垜鐢ㄤ竴涓畝鍗曞嚱鏁版潵璇佹槑錛?br>
template<typename ForwardIterator> void Capitalize(
ForwardIterator first錛孎orwardIterator end)
{
for(ForwardIterator it = first; it < end; it++)
*it = (*it)->ToUpper();
}
銆銆瀹冮亶鍘嗕竴涓猄ystem::String^瀹瑰櫒騫舵妸鍏朵腑鐨勬瘡涓瓧絎︿覆杞寲涓哄ぇ鍐欍?br>
Capitalize(vecstr.begin(), vecstr.end());
Capitalize(deqstr.begin(), deqstr.end());
for(vector<String^>::iterator it = vecstr.begin();
it < vecstr.end(); it++)
Console::WriteLine(*it);
Console::WriteLine();
for(deque<String^>::iterator it = deqstr.begin();
it < deqstr.end(); it++)
Console::WriteLine(*it);
銆銆涓婇潰鎴戠殑綆楁硶鑳藉涓巚ector鍜宒eque瀹瑰櫒宸ヤ綔鑹ソ銆傝嚦姝わ紝涓嶅啀緇嗚皥錛涘惁鍒欙紝guru绔欎笂鐨凷TL鐖卞ソ鑰呬滑浼氬鎴戠兢璧鋒敾鍑伙紝鑰岄潪STL浜哄彲鑳芥劅鍒板帉鐑︺傚鏋滀綘榪樻病浣跨敤榪嘢TL錛屽彲浠ュ弬鑰冩湁鍏寵祫鏂欍?br>
7. 鐔熸倝鐨勮娉?br>
銆銆寮鍙戣呯粡甯歌糠鎭嬩粬浠墍鐢ㄧ殑緙栫▼璇█錛岃屽緢灝戞槸鍑轟簬瀹炵敤鐨勭洰鐨勩傝繕璁板緱褰撳井杞甯冧笉鍐嶄負VB6鎻愪緵瀹樻柟鏀寔鏃訛紝VB6浜虹殑鍙嶆姉鍚楋紵闈濾B6浜哄姝ゅ彲鑳介潪甯擱渿鎯婏紝鑰岃侀亾鐨刅B6浜烘棭宸蹭負浠栦滑鐨勮璦浣滃ソ钁ぜ鍑嗗浜嗐備簨瀹炰笂錛屽鏋淰B.NET浠庢潵娌¤鍙戞槑錛屽鏁癡B6浜哄皢浼氱寮.NET錛屽洜涓篊#灝嗕細瀵逛粬浠潪甯擱檶鐢燂紝鑰屽畠鐨勭鍏堝氨鏄疌++銆傚浠婏紝璁稿VB.NET浜哄彲鑳藉凡緇忚漿鍚戜簡C#錛屼絾鏄粬浠笉浼氫粠VB6鐩存帴杞悜C#錛沄B.NET璧峰埌涓涓ˉ姊佷綔鐢ㄨ浠栦滑鐨勬濇兂鑴辯寮鍘熸潵VB6鎬濇兂銆傜浉搴斿湴錛屽鏋滃井杞粎鍙戣VB.NET(鑰屾病鏈塁#)錛岄偅涔?NET鍙兘鎴愪負浜嗘柊鐨勯潰鍚戝璞B錛屼笖甯︽湁涓涓洿澶х殑綾誨簱-C++紺懼洟鐨勪漢鍙兘瀵規鍡や箣浠ラ薊-浠栦滑鐢氳嚦涓嶄細楹葷儲鍦版楠?NET鍩虹綾誨簱銆備負浠涔堜換浣曚嬌鐢ㄤ竴縐嶇壒瀹氳璦鐨勫紑鍙戣呬細瀵瑰彟澶栦竴涓洟浣撶殑浣跨敤鍙﹀寮鍙戣璦鐨勫紑鍙戣呭棨涔嬩互榧伙紵榪欎笉鏄垜瑕佸洖絳旂殑闂銆?-瑕佸洖絳旇闂涔熻瑕佸厛鍥炵瓟涓轟粈涔堟湁鐨勪漢鍠滄濞佸+蹇岋紝鏈夌殑浜哄枩嬈㈠彲鍙e彲涔愶紝鑰岃繕鏈変漢鍠滄鐗涘ザ銆傛墍鏈夋垜瑕佽鐨勬槸錛屽寮鍙戣呮潵璇達紝璇硶瀹舵棌鏄釜澶ч棶棰樸?br>
銆銆浣犺涓哄浜庝竴涓叿鏈塁++鑳屾櫙鐨勪漢錛屼笅闈㈢殑浠g爜鍏鋒湁鎬庢牱鐨勭洿瑙夋э紵
char[] arr =new char[128];
銆銆浠?濂瑰彲鑳藉洖絳旂殑絎竴浠朵簨鏄紝鏂規嫭鍙鋒斁閿欎簡浣嶇疆銆備笅闈㈣繖鍙ュ張濡備綍錛?br>
int y=arr.Length;
銆銆"鍛!"-鏈鍙兘鐨勫弽鏄犮傜幇鍦ㄦ妸涓嬮潰涓庡墠闈㈢浉姣旇緝錛?br>
char natarr[128];
array<char>^ refarr=gcnew array<char>(128);
int y=refarr->Length;
銆銆璇鋒敞鎰忓0鏄庝竴涓湰鏈烘暟緇勫拰涓涓墭綆℃暟緇勬椂鐨勮娉曞尯鍒傝繖閲屼笉鍚岀殑妯℃澘褰㈠紡鐨勮娉曞彲瑙嗗寲鍦板憡璇紑鍙戣呰繖涓浜嬪疄--refarr騫朵笉鏄吀鍨嬬殑C++鏁扮粍鑰屼笖瀹冨彲鑳芥槸鏌愮CLI綾葷殑媧劇敓鐗?浜嬪疄涓婄‘鏄姝?錛屾墍浠ユ瀬鏈夊彲鑳藉彲浠ユ妸鏂規硶鍜屽睘鎬у簲鐢ㄤ簬瀹冦?br>
銆銆C#鐨刦inalizer璇硶鏈鏈夊彲鑳藉紩璧瘋漿鍚慍#鐨凜++紼嬪簭鍛樼殑娣鋒穯銆傝鐪嬭涓嬪垪C#浠g爜錛?br>
class R
{ ~R(){} }
銆銆濂斤紝榪欐牱~R鐪嬭搗鏉ヨ薄涓涓瀽鏋勫櫒浣嗗疄闄呮槸涓猣inalizer銆備負浠涔堬紵璇蜂笌涓嬮潰鐨凜++浠g爜姣旇緝錛?br>
ref class R
{
~R(){ }
!R(){ }
};
銆銆榪欓噷~R鏄瀽鏋勫櫒錛堝疄闄呬笂絳変環浜庝竴涓瀽鏋勫櫒鐨凞ispose妯″紡-浣嗗C++浜哄憳鏉ヨ錛岃繖瀹冪殑琛屼負璞′釜鏋愭瀯鍣級鑰屾柊鐨?R璇硶鏄負finalizer寤虹珛鐨?榪欐牱灝變笉鍐嶆湁娣鋒穯鑰屼笖璇硶鐪嬩笂鍘諱篃涓庢湰鏈篊++鐩稿尮閰嶃?br>
銆銆璇風湅涓涓婥#娉涘瀷璇硶錛?br>
class R<T>{};
銆銆鍐嶈鐪嬩竴涓婥++鐨勮娉曪細
generic<typename T> ref class R{};
銆銆鏇劇粡浣跨敤榪囨ā鏉跨殑浜洪┈涓婂氨鐪嬪嚭榪欑C++璇硶錛岃孋#璇硶涓嶈兘淇濊瘉鍏舵病鏈夋販娣嗘т笖涔熶笉鐩磋銆傛垜鐨勮鐐規槸錛屽鏋滀綘浠ュ墠鍏鋒湁C++鑳屾櫙錛孋++/CLI璇硶灝嗘渶璐磋繎浜庝綘浠ュ墠鎵鐢ㄣ侰#(浠ュ強J#)鐪嬩笂鍘昏薄C++錛屼絾鏄繕鏈夌浉褰撳鐨勬瀬涓轟嬌浜虹儲鐏殑濂囨涔夊樊鍒屼笖濡傛灉浣犳病鏈夊畬鍏ㄦ斁寮僀++錛岃娉曞樊鍒皢姘歌繙涓嶅仠鍦板甫緇欎綘娣蜂貢鍜屾尗鎶樸備粠榪欑鎰忎箟涓婅錛屾垜璁や負VB.NET鏇村ソ浜涳紝鑷沖皯瀹冩湁鑷繁鍞竴鐨勮娉曪紝鎵浠ラ偅浜涘叡鐢–++鍜孷B.NET鐨勪漢涓嶄細浜х敓璇硶娣蜂貢銆?br>
銆銆8. 緇撹
銆銆鏈鍚庯紝鑷充簬浣犵敤浠涔堣璦緙栫▼錛岃繖鍙兘渚濊禆璁稿鍥犵礌鈥斺斿錛氫綘鍦ㄥ鏍″涔犵殑鏄粈涔堣璦錛屼綘鏄敤浠涔堣璦寮鍙戠殑鐜版湁浠g爜浠撳簱錛屾槸鍚︿綘鐨勫鎴峰浣犳湁鍏蜂綋鐨勮璦瑕佹眰絳夈傛湰鏂囩殑涓昏鐩殑鏄府鍔╀綘紜畾浣跨敤C++/CLI鐨勫嚑涓槑紜殑鍦烘墍--榪欓噷錛屽畠姣斿彟澶朇LI璇█鏇村叿鏈夋槑鏄句紭鍔褲傚鏋滀綘寮鍙戠殑搴旂敤紼嬪簭鏈?0%鐨勪嬌鐢ㄦ椂闂存槸娑夊強鏈満interop錛屼負浣曡繕瑕佽冭檻浣跨敤鍙﹀鐨勮屼笉鏄疌++錛熷鏋滀綘鎯沖紑鍙戜竴涓氱敤闆嗗悎錛屼負浠涔堜粎鎶婁綘鑷繁闄愬埗鍦ㄦ硾鍨嬩笂錛岃屼笉鏄粨鍚堟硾鍨嬪拰妯℃澘鐨勪紭鍔垮憿錛熷鏋滀綘宸茬粡鐢–++宸ヤ綔錛屼負浠涔堣繕瑕佸涔犱竴縐嶆柊鐨勮璦?鎴戝父瑙夊緱璞#鍜孷B.NET榪欐牱鐨勮璦鎬繪槸灝介噺鍚戝紑鍙戣呴殣钘廋LR錛岃孋++涓嶄粎璁╀綘鍝佸懗CLR錛岀敋鑷沖彲浠ヨ浣犲幓浜插惢CLR!
Description | C++/CLI | C# |
---|---|---|
Allocate reference type | ReferenceType^ h = gcnew ReferenceType; | ReferenceType h = new ReferenceType(); |
Allocate value type | ValueType v(3, 4); | ValueType v = new ValueType(3, 4); |
Reference type, stack semantics | ReferenceType h; | N/A |
Calling Dispose method | ReferenceType^ h = gcnew ReferenceType;
delete h; |
ReferenceType h = new ReferenceType();
((IDisposable)h).Dispose(); |
Implementing Dispose method | ~TypeName() {} | void IDisposable.Dispose() {} |
Implementing Finalize method | !TypeName() {} | ~TypeName() {} |
Boxing | int^ h = 123; | object h = 123; |
Unboxing | int^ hi = 123;
int c = *hi; |
object h = 123;
int i = (int) h; |
Reference type definition | ref class ReferenceType {};
ref struct ReferenceType {}; |
class ReferenceType {} |
Value type definition | value class ValueType {};
value struct ValueType {}; |
struct ValueType {} |
Using properties | h.Prop = 123;
int v = h.Prop; |
h.Prop = 123;
int v = h.Prop; |
Property definition | property String^ Name { String^ get() { return m_value; } void set(String^ value) { m_value = value; } } |
string Name { get { return m_name; } set { m_name = value; } } |
#using using namespace System; int main(void) { Console::WriteLine(S"Hello World"); return 0; } |
綾誨瀷鎻忚堪 | 鏍囧噯C++綾誨瀷鍚?/td> | 鎵樼C++綾誨瀷鍚?/td> | 闀垮害(浣? |
甯冨皵鍨?/td> | bool | bool | 8 |
瀛楃鍨?/td> | char | signed char | 8 |
鏃犵鍙峰瓧絎﹀瀷 | unsigned char | char | 8 |
鐭暣鍨?/td> | short [int] | short | 16 |
鏃犵鍙風煭鏁村瀷 | unsigned short [int] | unsigned short | 16 |
鏁村瀷 | int | int 鎴?long | 32 |
鏃犵鍙鋒暣鍨?/td> | unsigned [int] | unsigned int 鎴?long | 32 |
闀挎暣鍨?/td> | long [int] | long | 32 |
鏃犵鍙烽暱鏁村瀷 | unsigned long [int] | unsigned long | 32 |
鍗曠簿搴︽誕鐐瑰瀷 | float | float | 32 |
鍙岀簿搴︽誕鐐瑰瀷 | double | double | 64 |
闀垮弻綺懼害嫻偣鍨?/td> | long double | -- | 64 |
Unicode瀛楃 | -- | wchar_t | 16 |
64浣嶆暣鍨?/td> | -- | __int64 | 64 |
鏃犵鍙?4浣嶆暣鍨?/td> | -- | unsigned __int64 | 64 |
96浣嶅崄榪涘埗鍊?/td> | -- | Decimal | 96 |
瀵硅薄綾誨瀷 | -- | Object* | 32 |
瀛楃涓茬被鍨?/td> | -- | String* | -- |
#using using namespace System; int main(void) { String* hello = S"Hello World"; Console::WriteLine(hello); return 0; } |
__gc class G { public: int k; int sum(int); }; G::sum(int i) {return i*(i + 1)/2;} int main() { G * g = new G; Console::WriteLine(g->sum(4)); // 緇撴灉杈撳嚭10 return 0; } |
#using using namespace System; __value struct V { int i; }; __gc struct G { V v; }; // 宓屽叆鍒癬_gc綾諱腑 V f(V v) { // 瀹氫箟涓涓叏灞鍑芥暟錛屽叾鍊煎瓨鍌ㄥ湪榪愯鏍堜腑 v.i += 1; // 涓嶅獎鍝嶅師鏉ュ艦鍙倂鐨勫?br />return v; // 榪斿洖V緇撴瀯綾誨瀷鐨勫?br />} int main(void) { V v1 = {10}; // 鍦ㄨ繍琛屾爤涓0鏄庡茍鍒濆鍖?br />V v2 = f(v1); // 璋冪敤f鍑芥暟錛屾鏃秜1涓殑i涓?0錛岃寁2涓殑i涓?1 G *pG = new G; // 涓篏瀹炰緥鍒嗛厤鍫嗙┖闂?br />pG->v = v1; // pG鐨剉涓殑i涓?0 pG->v.i += v2.i; // pG鐨剉涓殑i涓?0+11=21 Console::WriteLine(v1.i); // 杈撳嚭緇撴灉涓?0 Console::WriteLine(v2.i); // 杈撳嚭緇撴灉涓?1 Console::WriteLine(pG->v.i); // 杈撳嚭緇撴灉涓?1 return 0; } |
__gc __interface Ibase { void f(); }; |
#using using namespace System; __gc __interface Ibase1 { int f(int); }; __gc __interface Ibase2 { int f(int); }; __gc struct C: Ibase1, Ibase2 { int f(int i) { // 鎺ュ彛鏂規硶鐨勫疄鐜?br />return 2*i-1; }; }; int main(void){ C* c = new C; Console::WriteLine((c -> f(1)).ToString()); // 杈撳嚭緇撴灉涓? Console::WriteLine((__try_cast // 杈撳嚭緇撴灉涓? Console::WriteLine((__try_cast // 杈撳嚭緇撴灉涓? return 0; } |
#using using namespace System; __gc class G { public: __property int get_Size() { Console::WriteLine(S"get_灞炴?); return nSize; }; __property void set_Size(int i) { Console::WriteLine(S"set_灞炴?); nSize = i; }; private: int nSize; }; int main() { G * pG = new G; pG->Size = 10; // 璋冪敤set_Size int i = pG->Size; // 璋冪敤get_Size Console::WriteLine(i); } |
#using using namespace System; __delegate int GetDayOfWeek(); // 濮旀淳鏂規硶鐨勫0鏄?br />__gc class MyCalendar { public: MyCalendar() : m_nDayOfWeek(4) {} int MyGetDayOfWeek() { Console::WriteLine("闈為潤鎬佹柟娉?); return m_nDayOfWeek; } static int MyStaticGetDayOfWeek() { Console::WriteLine("闈欐佹柟娉?); return 6; } private: int m_nDayOfWeek; }; int main(void) { GetDayOfWeek * pGetDayOfWeek; // 澹版槑濮旀淳綾誨瀷鍙橀噺 int nDayOfWeek; // 灝嗙被鐨勯潤鎬佹柟娉昅yStaticGetDayOfWeek緇戝畾鎴愬媧?br />pGetDayOfWeek = new GetDayOfWeek(0, &MyCalendar::MyStaticGetDayOfWeek); nDayOfWeek = pGetDayOfWeek->Invoke(); // 濮旀淳鐨勮皟鐢?br />Console::WriteLine(nDayOfWeek); // 灝嗕竴涓被鐨勫疄渚嬬粦瀹氭垚濮旀淳 MyCalendar * pcal = new MyCalendar(); pGetDayOfWeek = static_cast new GetDayOfWeek(pcal, &MyCalendar::MyGetDayOfWeek))); nDayOfWeek = pGetDayOfWeek->Invoke(); Console::WriteLine(nDayOfWeek); // 鍒犻櫎緇戝畾濮旀淳鐨勭被瀹炰緥 pGetDayOfWeek = static_cast new GetDayOfWeek(pcal, &MyCalendar::MyGetDayOfWeek))); return 0; } |
delete h;
((IDisposable)h).Dispose();
int c = *hi;
int i = (int) h;
ref struct ReferenceType {};
value struct ValueType {};
int v = h.Prop;
int v = h.Prop;
The second option for interop is to use P/Invoke. This is accomplished using the DllImport attribute, specifying the attribute on the method declaration for the function you want to import. Marshaling is handled according to how it has been specified in the declaration. However, DllImport is only useful if you have code that exposes the required functions through a DLL export.
When you need to call managed code from native code, CLR hosting is an option. In such a scenario, the native application has to drive all of the execution: setting up the host, binding to the runtime, starting the host, retrieving the appropriate AppDomain, setting up the invocation context, locating the desired assembly and class, and invoking the operation on the desired class. This is definitely one of the most robust solutions in terms of control over what and when things happen, but it is also incredibly tedious and requires a lot of custom code.
The fourth option, and quite possibly the easiest and the most performant, is to use the interop capabilities in C++. By throwing the /clr switch, the compiler generates MSIL instead of native machine code. The only code that is generated as native machine code is code that just can't be compiled to MSIL, including functions with inline asm blocks and operations that use CPU-specific intrinsics such as Streaming SIMD Extensions (SSE). The /clr switch is how the Quake II port to .NET was accomplished. The Vertigo software team spent a day porting the original C code for the game to code that successfully compiled as C++ and then threw the /clr switch. In no time they were up and running on the .NET Framework. Without adding any additional binaries and simply by including the appropriate header files, managed C++ and native C++ can call each other without any additional work on the part of the developer. The compiler handles the creation of the appropriate thunks to go back and forth between the two worlds.
/O1 | 鍒涘緩灝忎唬鐮?/td> |
/O2 | 鍒涘緩蹇熶唬鐮?/td> |
/Oa | 鍋囪娌℃湁鍒悕 |
/Ob | 鎺у埗鍐呰仈灞曞紑 |
/Od | 紱佺敤浼樺寲 |
/Og | 浣跨敤鍏ㄥ眬浼樺寲 |
/Oi | 鐢熸垚鍐呴儴鍑芥暟 |
/Op | 鏀瑰杽嫻偣鏁頒竴鑷存?/td> |
/Os | 浠g爜澶у皬浼樺厛 |
/Ot | 浠g爜閫熷害浼樺厛 |
/Ow | 鍋囧畾鍦ㄥ嚱鏁拌皟鐢ㄤ腑浣跨敤鍒悕 |
/Ox | 浣跨敤鏈澶т紭鍖?(/Ob2gity /Gs) |
/Oy | 鐪佺暐妗嗘灦鎸囬拡 |
浠g爜鐢熸垚
/arch | 浣跨敤 SSE 鎴?SSE2 鎸囦護鐢熸垚浠g爜 |
/clr | 鍚敤 C++ 鐨勬墭綆℃墿灞曞茍浜х敓鍦ㄥ叕鍏辮璦榪愯搴撲笂榪愯鐨勮緭鍑烘枃浠?/td> |
/EH | 鎸囧畾寮傚父澶勭悊妯″瀷 |
/G3 | 浼樺寲浠g爜浠ヤ紭閫?386 澶勭悊鍣ㄣ傚湪 Visual C++ 5.0 涓凡緇忓仠鐢紝緙栬瘧鍣ㄥ皢蹇界暐姝ら夐」 |
/G4 | 浼樺寲浠g爜浠ヤ紭閫?486 澶勭悊鍣ㄣ傚湪 Visual C++ 5.0 涓凡緇忓仠鐢紝緙栬瘧鍣ㄥ皢蹇界暐姝ら夐」 |
/G5 | 浼樺寲浠g爜浠ヤ紭閫?Pentium |
/G6 | 浼樺寲浠g爜浠ヤ紭閫?Pentium Pro銆丳entium II 鍜?Pentium III 澶勭悊鍣?/td> |
/G7 | 閽堝 Pentium 4 鎴?Athlon 浼樺寲浠g爜銆?/td> |
/GB | 涓?/G6 絳夋晥錛涘皢 _M_IX86 鐨勫艱緗負 600 |
/Gd | 浣跨敤 __cdecl 璋冪敤綰﹀畾 |
/Ge | 嬋媧誨爢鏍堟帰嫻?/td> |
/GF
/Gf |
鍚敤瀛楃涓叉睜 |
/Gh | 璋冪敤鎸傞挬鍑芥暟 _penter |
/GH | 璋冪敤鎸傞挬鍑芥暟 _pexit |
/GL | 鍚敤鍏ㄧ▼搴忎紭鍖?/td> |
/Gm | 鍚敤鏈灝忛噸鏂扮敓鎴?/td> |
/GR | 鍚敤榪愯鏃剁被鍨嬩俊鎭?(RTTI) |
/Gr | 浣跨敤 __fastcall 璋冪敤綰﹀畾 |
/Gs | 鎺у埗鍫嗘爤鎺㈡祴 |
/GT | 鏀寔浣跨敤闈欐佺嚎紼嬫湰鍦板瓨鍌ㄥ尯鍒嗛厤鐨勬暟鎹殑綰ょ▼瀹夊叏 |
/GX | 鍚敤鍚屾寮傚父澶勭悊 |
/Gy | 鍚敤鍑芥暟綰ч摼鎺?/td> |
/Gz | 浣跨敤 __stdcall 璋冪敤綰﹀畾 |
/MD | 浣跨敤 MSVCRT.lib 鍒涘緩澶氱嚎紼?DLL |
/MDd | 浣跨敤 MSVCRTD.lib 鍒涘緩璋冭瘯澶氱嚎紼?DLL |
/ML | 浣跨敤 LIBC.lib 鍒涘緩鍗曠嚎紼嬪彲鎵ц鏂囦歡 |
/MLd | 浣跨敤 LIBCD.lib 鍒涘緩璋冭瘯鍗曠嚎紼嬪彲鎵ц鏂囦歡 |
/MT | 浣跨敤 LIBCMT.lib 鍒涘緩澶氱嚎紼嬪彲鎵ц鏂囦歡 |
/MTd | 浣跨敤 LIBCMTD.lib 鍒涘緩璋冭瘯澶氱嚎紼嬪彲鎵ц鏂囦歡 |
杈撳嚭鏂囦歡
/FA
/Fa |
鍒涘緩鍒楄〃鏂囦歡 璁劇疆鍒楄〃鏂囦歡鍚?/td> |
/Fd | 閲嶅懡鍚嶇▼搴忔暟鎹簱鏂囦歡 |
/Fe | 閲嶅懡鍚嶅彲鎵ц鏂囦歡 |
/Fm | 鍒涘緩鏄犲皠鏂囦歡 |
/Fo | 鍒涘緩瀵硅薄鏂囦歡 |
/Fp | 鎸囧畾棰勭紪璇戝ご鏂囦歡鍚?/td> |
/FR
/FR |
鐢熸垚嫻忚鍣ㄦ枃浠?/td> |
/Fx | 灝嗘彃鍏ョ殑浠g爜涓庢簮鏂囦歡鍚堝茍 |
璋冭瘯
/GS | 緙撳啿鍖哄畨鍏ㄦ鏌?/td> |
/GZ | 涓?/RTC1 鐩稿悓 |
/RTC | 鍚敤榪愯鏃墮敊璇鏌?/td> |
/Wp64 | 媯嫻?64 浣嶅彲縐繪鎬ч棶棰?/td> |
/Yd | 灝嗗畬鏁寸殑璋冭瘯淇℃伅鏀懼湪鎵鏈夊璞℃枃浠朵腑 |
/Yl | 鍒涘緩璋冭瘯搴撴椂鎻掑叆 PCH 寮曠敤 |
/Z7 | 鐢熸垚涓?C 7.0 鍏煎鐨勮皟璇曚俊鎭?/td> |
/Zd | 鐢熸垚琛屽彿 |
/Zi | 鐢熸垚瀹屾暣鐨勮皟璇曚俊鎭?/td> |
棰勫鐞嗗櫒
/AI | 鎸囧畾鍦ㄨВ鏋愪紶閫掑埌 #using 鎸囦護鐨勬枃浠跺紩鐢ㄦ椂鎼滅儲鐨勭洰褰?/td> |
/C | 鍦ㄩ澶勭悊鏈熼棿淇濈暀娉ㄩ噴 |
/D | 瀹氫箟甯告暟鍜屽畯 |
/E | 灝嗛澶勭悊鍣ㄨ緭鍑哄鍒跺埌鏍囧噯杈撳嚭 |
/EP | 灝嗛澶勭悊鍣ㄨ緭鍑哄鍒跺埌鏍囧噯杈撳嚭 |
/Fl | 棰勫鐞嗘寚瀹氱殑鍖呭惈鏂囦歡 |
/FU | 寮哄埗浣跨敤鏂囦歡鍚嶏紝灝卞儚瀹冨凡琚紶閫掑埌 #using 鎸囦護涓鏍?/td> |
/I | 鍦ㄧ洰褰曚腑鎼滅儲鍖呭惈鏂囦歡 |
/P | 灝嗛澶勭悊鍣ㄨ緭鍑哄啓鍏ユ枃浠?/td> |
/U | 縐婚櫎棰勫畾涔夊畯 |
/u | 縐婚櫎鎵鏈夌殑棰勫畾涔夊畯 |
/X | 蹇界暐鏍囧噯鍖呭惈鐩綍 |
/ZI | 灝嗚皟璇曚俊鎭寘鍚湪涓庘滅紪杈戝茍緇х畫鈥濆吋瀹圭殑紼嬪簭鏁版嵁搴撲腑 |
璇█
/vd | 鍙栨秷鎴栧惎鐢ㄩ殣钘忕殑 vtordisp 綾繪垚鍛?/td> |
/vmb | 瀵規寚鍚戞垚鍛樼殑鎸囬拡浣跨敤鏈浣崇殑鍩?/td> |
/vmg | 瀵規寚鍚戞垚鍛樼殑鎸囬拡浣跨敤瀹屽叏涓鑸?/td> |
/vmm | 澹版槑澶氶噸緇ф壙 |
/vms | 澹版槑鍗曚竴緇ф壙 |
/vmv | 澹版槑铏氭嫙緇ф壙 |
/Za | 紱佺敤璇█鎵╁睍 |
/Zc | 鍦?/Ze 涓嬫寚瀹氭爣鍑嗚涓?/td> |
/Ze | 鍚敤璇█鎵╁睍 |
/Zg | 鐢熸垚鍑芥暟鍘熷瀷 |
/Zl | 浠?.obj 鏂囦歡涓Щ闄ら粯璁ゅ簱鍚?/td> |
/Zp n | 灝佽緇撴瀯鎴愬憳 |
/Zs | 鍙鏌ヨ娉?/td> |
閾炬帴
/F | 璁劇疆鍫嗘爤澶у皬 |
/LD | 鍒涘緩鍔ㄦ侀摼鎺ュ簱 |
/LDd | 鍒涘緩璋冭瘯鍔ㄦ侀摼鎺ュ簱 |
/link | 灝嗘寚瀹氱殑閫夐」浼犻掔粰 LINK |
/MD | 浣跨敤 MSVCRT.lib 緙栬瘧浠ュ垱寤哄綰跨▼ DLL |
/MDd | 浣跨敤 MSVCRTD.lib 緙栬瘧浠ュ垱寤鴻皟璇曞綰跨▼ DLL |
/ML | 浣跨敤 LIBC.lib 緙栬瘧浠ュ垱寤哄崟綰跨▼鍙墽琛屾枃浠?/td> |
/MLd | 浣跨敤 LIBCD.lib 緙栬瘧浠ュ垱寤鴻皟璇曞崟綰跨▼鍙墽琛屾枃浠?/td> |
/MT | 浣跨敤 LIBCMT.lib 緙栬瘧浠ュ垱寤哄綰跨▼鍙墽琛屾枃浠?/td> |
/MTd | 浣跨敤 LIBCMTD.lib 緙栬瘧浠ュ垱寤鴻皟璇曞綰跨▼鍙墽琛屾枃浠?/td> |
棰勭紪璇戝ご
/Y- | 蹇界暐褰撳墠鐢熸垚涓殑鎵鏈夊叾浠栭緙栬瘧澶寸紪璇戝櫒閫夐」 |
/Yc | 鍒涘緩棰勭紪璇戝ご鏂囦歡 |
/Yd | 灝嗗畬鏁寸殑璋冭瘯淇℃伅鏀懼湪鎵鏈夊璞℃枃浠朵腑 |
/Yu | 鍦ㄧ敓鎴愭湡闂翠嬌鐢ㄩ緙栬瘧澶存枃浠?/td> |
/YX | 鑷姩澶勭悊棰勭紪璇戝ご |
鏉傞」
@ | 鎸囧畾鍝嶅簲鏂囦歡 |
/? | 鍒楀嚭緙栬瘧鍣ㄩ夐」 |
/c | 緙栬瘧浣嗕笉閾炬帴 |
/H | 闄愬埗澶栭儴錛堝叕鍏憋級鍚嶇О鐨勯暱搴?/td> |
/HELP | 鍒楀嚭緙栬瘧鍣ㄩ夐」 |
/J | 鏇存敼榛樿鐨?char 綾誨瀷 |
/nologo | 鍙栨秷鏄劇ず鐧誨綍鐗堟潈鏍囧織 |
/QI0f | 紜繚 Pentium 0F 鎸囦護娌℃湁闂 |
/QIfdiv | FDIV銆丗PREM銆丗PTAN 鍜?FPATAN 鎸囦護鏈夌己闄風殑 Intel Pentium 寰鐞嗗櫒鐨勫彉閫氭柟娉?/td> |
QIfist | 褰撻渶瑕佷粠嫻偣綾誨瀷杞崲涓烘暣鍨嬫椂鍙栨秷 Helper 鍑芥暟 _ftol 鐨勮皟鐢?/td> |
/showIncludes | 鍦ㄧ紪璇戞湡闂存樉紺烘墍鏈夊寘鍚枃浠剁殑鍒楄〃 |
/Tc
/TC |
鎸囧畾 C 婧愭枃浠?/td> |
/Tp
/TP |
鎸囧畾 C++ 婧愭枃浠?/td> |
/V | 璁劇疆鐗堟湰瀛楃涓?/td> |
/W | 璁劇疆璀﹀憡絳夌駭 |
/w | 紱佺敤鎵鏈夎鍛?/td> |
/Wall | 鍚敤鎵鏈夎鍛婏紝鍖呮嫭榛樿鎯呭喌涓嬬鐢ㄧ殑璀﹀憡 |
/WL | 鍦ㄤ粠鍛戒護琛岀紪璇?C++ 婧愪唬鐮佹椂鍚敤閿欒淇℃伅鍜岃鍛婃秷鎭殑鍗曡璇婃柇 |
/Zm | 鎸囧畾棰勭紪璇戝ご鍐呭瓨鍒嗛厤闄愬埗 |
C/C++ 鐢熸垚鍙傝?/a> | 緙栬瘧鍣ㄩ夐」 | 璁劇疆緙栬瘧鍣ㄩ夐」
Wow, its turning into a busy month. I just haven鈥檛 had any time to blog despite having a number of interesting topics to cover. I鈥檒l try to get a few of them written soon. Here鈥檚 a topic from one of my regular readers.
The CLR naturally supports mixing managed and native method calls allowing you to easily call native functions from managed functions (which are of course natively compiled before execution) and visa versa. This is all largely transparent in C++. What鈥檚 not as transparent is how to mix managed and native types. The reason is that there is a greater distinction between native and managed types compared with function calls. Beside obvious differences such as those introduced by different calling conventions and virtual invocation, function calls aren鈥檛 all that different. Types however require a bit more help from the programmer/compiler since native and managed types can have very different characteristics. This is very evident in C# as you often need to decorate native type definitions with all kinds of attributes to control memory layout and marshalling. Fortunately for the C++ programmer the compiler takes care of much of this when you define or include native type definitions such as those found in the various Windows header files, but the programmer is still responsible for telling the compiler just how those types are to be used.
Visual C++ provides many of the building blocks for mixing native and managed types but in some cases you need to write a little code to help it along. Fortunately C++/CLI is very capable. Let鈥檚 consider a few different scenarios.
Embed Simple Managed Type in Native Type
Since the CLR needs to keep track of every single instance of a managed type in a process, storing some kind of reference/pointer/handle to a managed object in a native type is not directly supported since instances of native types can be allocated in any region of memory and cast to all kinds of foreign data types that would be completely opaque to the CLR and its services. Instead you need to register such occurrences with the CLR so that it is aware of these 鈥渘ative鈥?references to managed types. This is achieved with the use of the GCHandle type. Internally GCHandle manages a static table of (native) pointers that are used to lookup the objects in the managed heap. Of course using GCHandle directly from C++ can be quite tedious. It鈥檚 a CLS compliant value type which means native pointers are represented by IntPtr values. It also does not preserve static type information so static_casts are inevitable. Fortunately Visual C++ ships with the gcroot native template class that provides a strongly-typed interface over the GCHandle type.
#include <vcclr.h>
聽
ref struct ManagedType
{
聽聽聽 void HelloDotNet()
聽聽聽 {
聽聽聽聽聽聽聽 Console::WriteLine("Hello .NET");
聽聽聽 }
};
聽
struct NativeType
{
聽聽聽 ManagedType m1;聽聽聽聽聽聽聽聽聽 // Error!
聽聽聽
聽聽聽 ManagedType^ m2;聽聽聽聽聽聽聽聽 // Error!
聽聽聽
聽聽聽 gcroot<ManagedType^> m3; // OK
};
聽
void main()
{
聽聽聽 NativeType native;
聽聽聽 native.m3 = gcnew ManagedType;
聽
聽聽聽 native.m3->HelloDotNet();
}
As you can see, gcroot provides a 鈥渟mart鈥?pointer for storing handles in native types. It may be smart but it does not provide automatic cleanup of resources. Specifically, the gcroot destructor makes no attempt to dispose of the managed object鈥檚 resources.
Embed Managed Resource in Native Type
Enter the auto_gcroot class. This native template class wraps a gcroot and provides transfer-of-ownership semantics for managed objects stored in native types. If you鈥檙e looking for a point of reference, think of the auto_ptr template class from the Standard C++ Library which does the same thing for native pointers. The auto_gcroot destructor takes care of 鈥渄eleting鈥?the handle which results in the object鈥檚 IDisposable::Dispose method (if any) being called.
#include <msclr\auto_gcroot.h>
聽
ref struct ManagedType
{
聽聽聽 void HelloDotNet()
聽聽聽 {
聽聽聽聽聽聽聽 Console::WriteLine("Hello .NET");
聽聽聽 }
聽
聽聽聽 ~ManagedType()
聽聽聽 {
聽聽聽聽聽聽聽 Console::WriteLine("dtor");
聽聽聽聽聽聽聽 // Compiler implements Dispose pattern...
聽聽聽 }
};
聽
struct NativeType
{
聽聽聽 msclr::auto_gcroot<ManagedType^> m3; // OK
};
聽
void main()
{
聽聽聽 NativeType native;
聽聽聽 native.m3 = gcnew ManagedType;
聽
聽聽聽 native.m3->HelloDotNet();
}
The NativeType destructor (provided by the compiler) will automatically call the auto_gcroot destructor which will delete the managed object resulting in its destructor being called through its compiler generated Dispose method.
Embed Native Type in Managed Type
Now let鈥檚 turn things around. Let鈥檚 say we want to store a native type as a member of a managed type. The challenge is that the only native type the CLR really supports within managed types is a native pointer. C# programmers use IntPtr but that is only because IntPtr is the CLS compliant way of representing a native pointer and C# tries really hard to remain CLS compliant. The CLR fully supports storing native pointers without losing type information.
struct NativeType
{
};
聽
ref struct ManagedType
{
聽聽聽 NativeType n1; // Error!
聽聽聽 NativeType* n2; // OK
};
That鈥檚 great except that now we have a resource management issue. Recall that C++ does not have the separation of memory and resource management evident in the CLR. The native object pointed to by the ManagedType member needs to be deleted. Here is one solution.
ref struct ManagedType
{
聽聽聽 NativeType* n2; // OK
聽
聽聽聽 ~ManagedType()
聽聽聽 {
聽聽聽聽聽聽聽 if (0 != n2)
聽聽聽聽聽聽聽 {
聽聽聽聽聽聽聽聽聽聽聽 delete n2;
聽聽聽聽聽聽聽聽聽聽聽 n2 = 0;
聽聽聽聽聽聽聽 }
聽聽聽 }
};
Now the ManagedType has a Dispose implementation that will faithfully delete the native object. But this can become tedious and error prone very quickly. A better solution is to use some kind of 鈥渁utomatic鈥?approach. Fortunately C++/CLI support by-value semantics for members so all we need is a managed auto-pointer template class. With such a class the ManagedType becomes really simple.
ref struct ManagedType
{
聽聽聽 AutoPtr<NativeType> n2; // OK
};
ManagedType stores a pointer to a native object and its destructor automatically deletes the object. Woohoo!
The C++ compiler really takes care of a lot of boilerplate code. If you鈥檙e not sure just how much code the compiler is taking care of for you then聽take a look at the compiled assembly in a disassembler.
Although Visual C++ does not provide a managed AutoPtr class, it is reasonably simple to write one. Here is a basic implementation.
template <typename T>
ref struct AutoPtr
{
聽聽聽 AutoPtr() : m_ptr(0)
聽聽聽 {
聽聽聽聽聽聽聽 // Do nothing
聽聽聽 }
聽聽聽 AutoPtr(T* ptr) : m_ptr(ptr)
聽聽聽 {
聽聽聽聽聽聽聽 // Do nothing
聽聽聽 }
聽聽聽 AutoPtr(AutoPtr<T>% right) : m_ptr(right.Release())
聽聽聽 {
聽聽聽聽聽聽聽 // Do nothing
聽聽聽 }
聽聽聽 ~AutoPtr()
聽聽聽 {
聽聽聽聽聽聽聽 if (0 != m_ptr)
聽聽聽聽聽聽聽 {
聽聽聽聽聽聽聽聽聽聽聽 delete m_ptr;
聽聽聽聽聽聽聽聽聽聽聽 m_ptr = 0;
聽聽聽聽聽聽聽 }
聽聽聽 }
聽聽聽 T& operator*()
聽聽聽 {
聽聽聽聽聽聽聽 return *m_ptr;
聽聽聽 }
聽聽聽 T* operator->()
聽聽聽 {
聽聽聽聽聽聽聽 return m_ptr;
聽聽聽 }
聽聽聽 T* Get()
聽聽聽 {
聽聽聽聽聽聽聽 return m_ptr;
聽聽聽 }
聽聽聽 T* Release()
聽聽聽 {
聽聽聽聽聽聽聽 T* released = m_ptr;
聽聽聽聽聽聽聽 m_ptr = 0;
聽聽聽聽聽聽聽 return released;
聽聽聽 }
聽聽聽 void Reset()
聽聽聽 {
聽聽聽聽聽聽聽 Reset(0);
聽聽聽 }
聽聽聽 void Reset(T* ptr)
聽聽聽 {
聽聽聽聽聽聽聽 if (0 != m_ptr)
聽聽聽聽聽聽聽 {
聽聽聽聽聽聽聽聽聽聽聽 delete m_ptr;
聽聽聽聽聽聽聽 }
聽聽聽聽聽聽聽 m_ptr = ptr;
聽聽聽 }
private:
聽聽聽 T* m_ptr;
};
In a future post I may聽provide a few realistic examples of mixing native and managed code, but I hope this introduction has given you a few ideas on how to mix native and managed code and types effectively in C++.
鏉ヨ嚜: http://weblogs.asp.net/kennykerr/archive/2005/07/12/Mixing-Native-and-Managed-Types-in-C_2B002B00_.aspx
When Microsoft brought out the Managed Extensions to C++ with VS.NET 7, C++ programmers accepted it with mixed reactions. While most people were happy that they could continue using C++, nearly everyone was unhappy with the ugly and twisted syntax offered by Managed C++. Microsoft obviously took the feedback it got very seriously and they decided that the MC++ syntax wasn't going to be much of a success.
On October 6th 2003, the ECMA announced the creation of a new task group to oversee development of a standard set of language extensions to create a binding between the ISO standard C++ programming language and Common Language Infrastructure (CLI). It was also made known that this new set of language extensions will be known as the C++/CLI standard, which will be supported by the VC++ compiler starting with the Whidbey release (VS.NET 2005).
*
based syntax which was quite confusing because __gc
pointers were totally different in nature and behavior from unmanaged pointers.
using
namespace System;
void _tmain()
{
Console::WriteLine("Hello World");
}
Well, that doesn't look a lot different from old syntax, except that now you don't need to add a reference to mscorlib.dll because the Whidbey compiler implicitly references it whenever you compile with /clr (which now defaults to /clr:newSyntax).
One major confusion in the old syntax was that we used the * punctuator with unmanaged pointers and with managed references. In C++/CLI Microsoft introduces the concept of handles.
void _tmain()
{
//The ^ punctuator represents a handle
String^ str = "Hello World";
Console::WriteLine(str);
}
The ^ punctuator (pronounced as cap) represents a handle to a managed object. According to the CLI specification a handle is a managed object reference. Handles are the new-syntax equivalent of __gc
pointers in the MC++ syntax. Handles are not to be confused with pointers and are totally different in nature from pointers.
*
punctuator while handles are denoted using the ^
punctuator.
delete
explicitly or else suffer a leak. For handles delete
is optional.
void^
.
new
returns a pointer, a gcnew
returns a handle.
void _tmain()
{
String^ str = gcnew String("Hello World");
Object^ o1 = gcnew Object();
Console::WriteLine(str);
}
The gcnew
keyword is used to instantiate CLR objects and it returns a handle to the object on the CLR heap. The good thing about gcnew
is that it allows us to easily differentiate between managed and unmanaged instantiations.
Basically, the gcnew
keyword and the ^
operator offer just about everything you need to access the BCL. But obviously you'd need to create and declare your own managed classes and interfaces.
CLR types are prefixed with an adjective that describes what sort of type it is. The following are examples of type declarations in C++/CLI :-
refclass RefClass{...};
refstruct RefClass{...};
value class ValClass{...};
value struct ValClass{...};
interfaceclass IType{...};
interfacestruct IType{...};
enumclass Color{...};
enumstruct Color{...};
class Native{...};
struct Native{...};
using
namespace System;
interfaceclass IDog
{
void Bark();
};
refclass Dog : IDog
{
public:
void Bark()
{
Console::WriteLine("Bow wow wow");
}
};
void _tmain()
{
Dog^ d = gcnew Dog();
d->Bark();
}
There, the syntax is now so much more neater to look at than the old-syntax where the above code would have been strewn with double-underscored
聽keywords like __gc
and __interface
.
Boxing is implicit (yaay!) and type-safe. A bit-wise copy is performed and an Object
is created on the CLR heap. Unboxing is explicit - just do a reinterpret_cast
and then dereference.
void _tmain()
{
int z = 44;
Object^ o = z; //implicit boxingint y = *reinterpret_cast<int^>(o); //unboxing
Console::WriteLine("{0} {1} {2}",o,z,y);
z = 66;
Console::WriteLine("{0} {1} {2}",o,z,y);
}
// Output// 44 44 44// 44 66 44
The Object
o
is a boxed copy and does not actually refer the int
value-type which is obvious from the output of the second Console::WriteLine
.
When you box a value-type, the returned object remembers the original value type.
void _tmain()
{
int z = 44;
float f = 33.567;
Object^ o1 = z;
Object^ o2 = f;
Console::WriteLine(o1->GetType());
Console::WriteLine(o2->GetType());
}
// Output// System.Int32// System.Single
Thus you cannot try and unbox to a different type.
void _tmain()
{
int z = 44;
float f = 33.567;
Object^ o1 = z;
Object^ o2 = f;
int y = *reinterpret_cast<int^>(o2);//System.InvalidCastExceptionfloat g = *reinterpret_cast<float^>(o1);
//System.InvalidCastException
}
If you do attempt to do so, you'll get a System.InvalidCastException
. Talk about perfect type-safety! If you look at the IL generated, you'll see the MSIL box
instruction in action. For example :-
void Box2()
{
float y=45;
Object^ o1 = y;
}
gets compiled to :-
.maxstack 1
.locals (float32 V_0, object V_1)
ldnull
stloc.1ldc.r4 45.
stloc.0ldloc.0
box [mscorlib]System.Single
stloc.1ret
According to the MSIL docs, "The box instruction converts the 鈥榬aw鈥?valueType (an unboxed value type) into an instance of type Object (of type O). This is accomplished by creating a new object and copying the data from valueType into the newly allocated object."
Alright, so why would anyone want to use C++/CLI when they can use C#, J# and that VB thingie for writing .NET code? Here are the four reasons I gave during my talk at DevCon 2003 in Trivandrum (Dec 2003).
![]() ![]() ![]() |
Nish is a real nice guy living in Toronto who has been coding since 1990, when he was 13 years old. Originally from sunny Trivandrum in India, he has moved to Toronto so he can enjoy the cold winter and get to play in some snow. He works for The Code Project and handles the Dundas MFC products Ultimate Toolbox, Ultimate Grid and Ultimate TCP/IP that are sold exclusively through The Code Project Storefront. He frequents the CP discussion forums when he is not coding, reading or writing. Nish hopes to visit at least three dozen countries before his human biological mechanism stops working (euphemism used to avoid the use of the d-word here), and regrets that he hasn't ever seen snow until now (will be rectified this December). Oh btw, it must be mentioned that normally Nish is not inclined to speak about himself in the 3rd person. Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy Summer Love and Some more Cricket as well as a programming book 鈥?Extending MFC applications with the .NET Framework. Click here to view Nishant Sivakumar's online profile. |
綆浠?/b> C++綆$悊鎵╁睍鏄竴緇勮璦鎵╁睍錛屽畠甯姪Microsoft Visual C++寮鍙戜漢鍛樹負寰蔣.NET緙栧啓搴旂敤紼嬪簭銆? 綆$悊鎵╁睍鏄湁鐢ㄧ殑錛屽鏋滀綘錛? C++綆$悊鎵╁睍涓哄紑鍙戜漢鍛樺畾浣?NET Framework鎻愪緵浜嗘棤姣旂殑鐏墊椿鎬с備紶緇熺殑闈炵鐞咰++鍜岀鐞咰++浠g爜鍙互鑷敱鍦版販鍚堝湪涓涓?br />搴旂敤紼嬪簭涓傜敤綆$悊鎵╁睍緙栧啓鐨勫簲鐢ㄧ▼搴忓彲浠ュ埄鐢ㄤ袱縐嶄唬鐮佺殑浼樼偣銆備嬌鐢ㄧ鐞嗘墿灞曪紝鐜版湁緇勪歡鍙互鏂逛究鍦板皝瑁呭埌.NET緇勪歡涓紝 浠涔堟槸綆$悊鎵╁睍? 綆$悊鎵╁睍鏄疺isual C++寮鍙戠郴緇熺殑鏂板叧閿瓧鍜屽睘鎬с傚畠浠厑璁稿紑鍙戜漢鍛樺喅瀹氬摢浜涚被鎴栧嚱鏁扮紪璇戜負綆$悊鎴栭潪綆$悊浠g爜銆?br />榪欎簺閮ㄥ垎鐒跺悗灝卞彲浠ュ鉤婊戝湴涓庡叾瀹冮儴鍒嗘垨澶栭儴搴撲氦浜掋? 綆$悊鎵╁睍涔熺敤浜庡湪C++婧愪唬鐮佷腑琛ㄧず.NET綾誨瀷鍜屾蹇點傝繖灝卞厑璁稿紑鍙戜漢鍛樺鏄撳湴緙栧啓.NET搴旂敤紼嬪簭錛岃屾棤闇緙栧啓棰濆浠g爜銆? 涓昏浣跨敤鐜
鍦ㄤ笌.NET闆嗘垚鐨勫悓鏃朵繚鐣欏師鏈夋姇璧勩?
鎵╁睍鍏佽浣犲湪C++涓紪鍐欏湪.NET Framework鎺у埗涓嬭繍琛岀殑綆$悊錛堟垨.NET錛夌被銆傦紙闈炵鐞咰++綾昏繍琛屽湪浼犵粺鐨勫井杞熀浜嶹indows?
鐨勭幆澧冧腑銆傦級涓涓鐞嗙被鏄竴涓唴緗殑.NET綾伙紝鍙互瀹屽叏鍒╃敤.NET Framework銆?
濡傛灉浣犲湪C++浠g爜涓婃湁澶ч噺鎶曡祫錛岀鐞嗘墿灞曞皢甯綘灝嗗畠浠鉤婊戝湴杞Щ鍒?NET騫沖彴涓傚洜涓轟綘鍙互鍦ㄤ竴涓簲鐢ㄧ▼搴?-
綆$悊鎵╁睍鍏佽浣犱粠浠諱綍.NET璇█涓皟鐢–++綾匯備綘闇瑕佺敤鎵╁睍緙栧啓綆鍗曠殑灝佽鍣紝瀹冨皢浣犵殑C++綾誨拰鏂規硶鏆撮湶涓?
浣跨敤綆$悊鎵╁睍錛屼綘鍙互鍒涘緩騫朵粠C++浠g爜涓洿鎺ヨ皟鐢?NET綾匯備綘鍙互緙栧啓灝?NET緇勪歡褰撲綔浠諱綍鍏跺畠綆$悊C++綾葷殑
Visual C++緙栬瘧鍣ㄨ兘鍦ㄧ鐞嗗拰闈炵鐞嗕笂涓嬫枃涓嚜鍔ㄨ岄忔槑鐨勭炕璇戞暟鎹佹寚閽堝拰鎸囦護嫻併傝繖涓繃紼嬫槸鍏佽綆$悊鎵╁睍
涓轟簡浣垮緱鐜板瓨鐨勯潪.NET浠g爜閮藉彲鐢紝寰蔣鐨勮璁′嬌寰桟LR鍙互鍦ㄥ簲鐢ㄧ▼搴忛噷鍚屾椂鍖呭惈鎵樼鍜岄潪鎵樼浠g爜銆侰LR鏀寔涓夌浜掓搷浣滐細
鎵樼浠g爜璋冪敤DLL錛堝氨鏄垜浠鐨勫姩鎬侀摼鎺ュ簱錛変腑鐨勯潪鎵樼鍑芥暟
鎵樼浠g爜浣跨敤鐜板瓨鐨凜OM緇勫緩錛堥潪鎵樼緇勫緩浣滀負COM鏈嶅姟鍣級
闈炴墭綆′唬鐮佷嬌鐢ㄦ墭綆$被鍨嬶紙鎵樼綾誨瀷浣滀負COM鏈嶅姟鍣級
浜掓搷浣滄?BR>鏄惁鍙互鍦?.NET 妗嗘灦紼嬪簭涓嬌鐢?COM 瀵硅薄錛?BR>鏄傛偍鐜板湪閮ㄧ講鐨勪換浣?COM 緇勪歡閮藉彲浠ュ湪鎵樼浠g爜涓嬌鐢ㄣ傞氬父鎯呭喌涓嬶紝鎵闇鐨勮皟鏁存槸瀹屽叏鑷姩榪涜鐨勩?/P>
鐗瑰埆鏄紝鍙互浣跨敤榪愯鏃跺彲璋冪敤鍖呰 (RCW) 浠?.NET 妗嗘灦璁塊棶 COM 緇勪歡銆傛鍖呰灝?COM 緇勪歡鎻愪緵鐨?COM 鎺ュ彛杞崲涓轟笌 .NET 妗嗘灦鍏煎鐨勬帴鍙c傚浜?OLE 鑷姩鍖栨帴鍙o紝RCW 鍙互浠庣被鍨嬪簱涓嚜鍔ㄧ敓鎴愶紱瀵逛簬闈?OLE 鑷姩鍖栨帴鍙o紝寮鍙戜漢鍛樺彲浠ョ紪鍐欒嚜瀹氫箟 RCW錛屾墜鍔ㄥ皢 COM 鎺ュ彛鎻愪緵鐨勭被鍨嬫槧灝勪負涓?.NET 妗嗘灦鍏煎鐨勭被鍨嬨?/P>
鏄惁鍙互鍦?COM 紼嬪簭涓嬌鐢?.NET 妗嗘灦緇勪歡錛?BR>鏄傛偍鐜板湪鍒涘緩鐨勬墭綆$被鍨嬮兘鍙互閫氳繃 COM 璁塊棶銆傞氬父鎯呭喌涓嬶紝鎵闇鐨勯厤緗槸瀹屽叏鑷姩榪涜鐨勩傛墭綆″紑鍙戠幆澧冪殑鏌愪簺鏂扮壒鎬т笉鑳藉湪 COM 涓闂備緥濡傦紝涓嶈兘鍦?COM 涓嬌鐢ㄩ潤鎬佹柟娉曞拰鍙傛暟鍖栨瀯閫犲嚱鏁般備竴鑸紝鎻愬墠紜畾緇欏畾綾誨瀷鎵閽堝鐨勭敤鎴鋒槸涓縐嶈緝濂界殑鍔炴硶銆傚鏋滅被鍨嬮渶瑕佸湪 COM 涓嬌鐢紝鎮ㄥ皢琚檺鍒跺湪浣跨敤 COM 鍙闂殑鐗規с?/P>
榛樿鎯呭喌涓嬶紝鎵樼綾誨瀷鍙兘鏄彲瑙佺殑錛屼篃鍙兘鏄笉鍙鐨勶紝榪欑敱鐢ㄤ簬緙栧啓鎵樼綾誨瀷鐨勮璦鍐沖畾銆?/P>
鐗瑰埆鏄紝鍙互浣跨敤 COM 鍙皟鐢ㄥ寘瑁?(CCW) 浠?COM 璁塊棶 .NET 妗嗘灦緇勪歡銆傝繖涓?RCW錛堣鍙傞槄涓婁竴涓棶棰橈級鐩鎬技錛屼絾瀹冧滑鐨勬柟鍚戠浉鍙嶃傚悓鏍鳳紝濡傛灉 .NET 妗嗘灦寮鍙戝伐鍏蜂笉鑳借嚜鍔ㄧ敓鎴愬寘瑁咃紝鎴栬呭鏋滆嚜鍔ㄦ柟寮忎笉鏄偍鎵闇瑕佺殑錛屽垯鍙互寮鍙戣嚜瀹氫箟鐨?CCW銆?/P>
鏄惁鍙互鍦?.NET 妗嗘灦紼嬪簭涓嬌鐢?Win32 API錛?BR>鏄備嬌鐢?P/Invoke錛?NET 妗嗘灦紼嬪簭鍙互閫氳繃闈欐?DLL 鍏ュ彛鐐圭殑鏂瑰紡鏉ヨ闂湰鏈轟唬鐮佸簱銆?/P>
涓嬮潰鏄?C# 璋冪敤 Win32 MessageBox 鍑芥暟鐨勭ず渚嬶細
using System;
using System.Runtime.InteropServices;
class MainApp
{
[DllImport("user32.dll", EntryPoint="MessageBox")]
public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType);
public static void Main()
{
MessageBox( 0, "鎮ㄥソ錛岃繖鏄?PInvoke錛?, ".NET", 0 );
}
}
-----------------------------------------------------------------------------
浠涔堟槸鎵樼浠g爜鍜屾墭綆℃暟鎹紵
鎵樼浠g爜鏄負闈㈠悜鍏叡璇█榪愯搴撶殑鏈嶅姟緙栧啓鐨勪唬鐮侊紙璇峰弬闃呪滀粈涔堟槸鍏叡璇█榪愯搴擄紵鈥濓級銆備負浜嗛潰鍚戣繖浜涙湇鍔★紝璇ヤ唬鐮佸繀欏誨悜榪愯搴撴彁渚涙渶浣庣駭鍒殑淇℃伅錛堝厓鏁版嵁錛夈傞粯璁ゆ儏鍐典笅錛屾墍鏈?C#銆乂isual Basic .NET 鍜?JScript .NET 浠g爜閮藉彈鎵樼銆傞粯璁ゆ儏鍐典笅錛孷isual Studio .NET C++ 浠g爜涓嶅彈鎵樼錛屼絾緙栬瘧鍣ㄥ彲浠ラ氳繃鎸囧畾鍛戒護琛屽紑鍏?(/CLR) 鏉ヤ駭鐢熸墭綆′唬鐮併?
涓庢墭綆′唬鐮佸瘑鍒囩浉鍏崇殑鏄墭綆℃暟鎹紙鐢卞叕鍏辮璦榪愯搴撶殑鍨冨溇鍥炴敹鍣ㄥ垎閰嶅拰閲婃斁鐨勬暟鎹級銆傞粯璁ゆ儏鍐典笅錛孋#銆乂isual Basic 鍜?JScript .NET 鏁版嵁鍙楁墭綆°傜劧鑰岋紝閫氳繃浣跨敤鐗規畩鐨勫叧閿瓧鍙互灝?C# 鏁版嵁鏍囪涓洪潪鎵樼銆傞粯璁ゆ儏鍐典笅錛孷isual Studio .NET C++ 鏁版嵁涓嶅彈鎵樼錛堝嵆浣垮湪浣跨敤 /CLR 寮鍏蟲椂錛夛紝浣嗗湪浣跨敤 C++ 鎵樼鎵╁睍鏃訛紝鍙互閫氳繃浣跨敤 __gc 鍏抽敭瀛楀皢綾繪爣璁頒負鎵樼銆傛濡傚悕縐版墍鏆楃ず鐨勶紝榪欐剰鍛崇潃鐢ㄤ簬綾誨疄渚嬬殑鍐呭瓨鍙楀瀮鍦懼洖鏀跺櫒鐨勬墭綆°傚彟澶栵紝綾繪垚涓?.NET 妗嗘灦紺懼尯鐨勪竴鍚嶅畬鍏ㄥ弬涓庣殑鎴愬憳錛岃繖鏃㈠甫鏉ヤ簡濂藉錛屼篃甯︽潵浜嗛檺鍒躲傚叾涓竴涓ソ澶勬槸涓庣敤鍏朵粬璇█緙栧啓鐨勭被鐨勬紜簰鎿嶄綔鎬э紙渚嬪錛屾墭綆?C++ 綾誨彲浠ヤ粠 Visual Basic 綾葷戶鎵匡級銆傚叾涓竴涓檺鍒舵槸鎵樼綾誨彧鑳戒粠鍩虹被緇ф壙銆?/P>
--------------------------------------------------------------------------------
浠涔堟槸鍏叡璇█榪愯鏃?(CLR)錛?BR>鍏叡璇█榪愯鏃舵槸 .NET 妗嗘灦搴旂敤紼嬪簭鐨勬墽琛屽紩鎿庛?/P>
瀹冩彁渚涜澶氭湇鍔★紝鍖呮嫭錛?/P>
浠g爜綆$悊錛堝姞杞藉拰鎵ц錛?/P>
搴旂敤紼嬪簭鍐呭瓨闅旂
綾誨瀷瀹夊叏楠岃瘉
IL 鍒版湰鏈轟唬鐮佺殑杞崲
鍏冩暟鎹紙澧炲己鐨勭被鍨嬩俊鎭級璁塊棶
涓烘墭綆″璞$鐞嗗唴瀛?/P>
寮哄埗浠g爜璁塊棶瀹夊叏
寮傚父澶勭悊錛屽寘鎷法璇█寮傚父
鎵樼浠g爜銆丆OM 瀵硅薄鍜岀幇鏈?DLL錛堥潪鎵樼浠g爜鍜屾暟鎹級涔嬮棿鐨勪簰鎿嶄綔
鑷姩榪涜瀵硅薄甯冨眬
瀵瑰紑鍙戜漢鍛樻湇鍔★紙閰嶇疆銆佽皟璇曠瓑錛夌殑鏀寔
浠涔堟槸鍏叡綾誨瀷緋葷粺 (CTS)錛?BR>鍏叡綾誨瀷緋葷粺鏄淇℃伅綾誨瀷緋葷粺錛屽畠琚唴緗湪鍏叡璇█榪愯鏃朵腑錛屾敮鎸佸ぇ澶氭暟緙栫▼璇█涓殑綾誨瀷鍜屾搷浣溿傚叕鍏辯被鍨嬬郴緇熸敮鎸佸ぇ閲忕紪紼嬭璦鐨勫畬鍏ㄥ疄鐜般?/P>
浠涔堟槸鍏叡璇█瑙勮寖 (CLS)錛?BR>鍏叡璇█瑙勮寖鏄竴緇勭粨鏋勫拰闄愬埗錛岀敤浣滃簱緙栧啓鑰呭拰緙栬瘧鍣ㄧ紪鍐欒呯殑鎸囧崡銆傚畠浣夸換浣曟敮鎸?CLS 鐨勮璦閮藉彲浠ュ畬鍏ㄤ嬌鐢ㄥ簱錛屽茍涓斾嬌榪欎簺璇█鍙互鐩鎬簰闆嗘垚銆傚叕鍏辮璦瑙勮寖鏄叕鍏辯被鍨嬬郴緇熺殑瀛愰泦銆傚浜庨偅浜涢渶瑕佺紪鍐欎唬鐮佷緵鍏朵粬寮鍙戜漢鍛樹嬌鐢ㄧ殑搴旂敤紼嬪簭寮鍙戜漢鍛橈紝鍏叡璇█瑙勮寖涔熼潪甯擱噸瑕併傚鏋滃紑鍙戜漢鍛橀伒寰?CLS 瑙勫垯鏉ヨ璁″叕鍏辮闂殑 API錛岄偅涔堝氨鍙互鍦ㄦ敮鎸佸叕鍏辮璦榪愯鏃剁殑浠諱綍鍏朵粬緙栫▼璇█涓緢瀹規槗鍦頒嬌鐢ㄨ繖浜?API銆?/P>
浠涔堟槸 Microsoft 涓棿璇█ (MSIL)錛?BR>MSIL 鏄笌 CPU 鏃犲叧鐨勬寚浠ら泦銆?NET 妗嗘灦紼嬪簭琚紪璇戞垚 MSIL銆傚畠鍖呭惈鍔犺澆銆佸瓨鍌ㄣ佸垵濮嬪寲鍜岃皟鐢ㄥ璞℃柟娉曠殑鎸囦護銆?/P>
涓庡厓鏁版嵁鍜屽叕鍏辯被鍨嬬郴緇熺粨鍚堬紝MSIL 鍏佽鐪熸鐨勮法璇█闆嗘垚銆?/P>
MSIL 鍦ㄦ墽琛屽墠琚漿鎹負鏈哄櫒浠g爜錛岃屼笉鏄竴杈硅В閲婁竴杈規墽琛屻?/P>