青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 67  文章 - 171  trackbacks - 0
<2008年2月>
272829303112
3456789
10111213141516
17181920212223
2425262728291
2345678

常用鏈接

留言簿(10)

隨筆分類

隨筆檔案

連接資料

最新隨筆

搜索

  •  

最新隨筆

最新評論

您也使用托管C++嗎?
  轉向.NET后,手頭上往往仍有舊的模塊要重用。也許這些模塊是Delphi寫的,也許是C/C++寫的,或者是其它編程語言……為了能把它們移植到.NET下,或者是在.NET中調用,To be or not to be, that is a question。
  在這里,我筆記了幾個在工作中遇到的幾個場景。不過,這里不包括完全使用C#來重寫原來用C++編寫的程序這種變態的需求。當你被要求做這種事的時候,請三思而后行……這簡直是種非人的折磨。

您也使用托管C++嗎?  如沐楓林

  場景一:在.NET中調用WindowsAPI或DLL。

  這是比較普遍的需求。一般來說,簡單的函數調用,大可直接用C#/VB.NET,經過DllImport屬性包裝出函數來調用。如:

[DllImport("KERNEL32.DLL", EntryPoint="MoveFileW",   SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern bool MoveFile(String src, String dst);

  由于WindowsAPI用到的人實在是多,因此有一個專門的wiki站點,收集這方面的資料:http://www.pinvoke.net/,對于常用的函數甚至有完整的應用例子和幫助。當然,如果你有相應的資料和例子,你也可以貢獻你的力量,給其它人幫助。

  場景二:用托管C++包裝現有的DLL,供C#調用

  當函數的參數或返回值比較復雜,或函數比較多的時候,這種方法對與人來說,實在是一個折磨。常常這些接口和定義就要用掉幾千行的代碼,而且還不能保證是正確的。這些錯誤往往在運行時才能顯現出來,甚至有些錯誤會引起內存泄漏,或其它更為隱蔽的錯誤。
  在這種情況下,使用C++/Managed代碼來包裝,就成了最合理的選擇。因為托管C++代碼可以直接引用原有的頭文件,直接調用非托管函數,而不需要聲明。這樣,既減少了工作量,又避免引入錯誤。缺點是,這種方法會增加一個DLL。要注意的是托管字符串和非托管字符串是有區別的,并需要轉換(特別要注意的Unicode字符串和多字節字符串的轉換)。

  仍以MoveFile為例吧,這樣比較簡單:


#include <windows.h>
#include <vcclr.h>

using namespace System;

namespace wrapper
{
     public ref class ApiWrapper {
     public:
         bool static MoveFile(String ^ lpExistingFileName, String ^ lpNewFileName )
         {
             pin_ptr<const wchar_t> src = PtrToStringChars(lpExistingFileName);
             pin_ptr<const wchar_t> dst = PtrToStringChars(lpNewFileName);
             return ::MoveFile(src, dst);
         }
     };
}
  然后在C#中,引用上面代碼生成的DLL文件,就可以直接調用了:
wrapper.ApiWrapper.MoveFile(@"c:\debug.log", @"c:\debug.txt");
  假如原有的代碼是基于COM的,那么太好了,VisualStudio等IDE會自動生成一個用于包裝的dll,供你調用。當然因特殊需要而手工編碼的是另一回事。

  場景三:現有C++原代碼,包裝后供C#調用。

  C++的原代碼,實際上可以直接編譯成托管代碼。MFC也好ATL也好……這樣看起來在.NET中最強大的編程語言就是C++了:它不僅可以編寫托管程序,甚至可以將標準C++的代碼也編譯成托管程序!其實VC++最強大的地方不止如此,它還在于能夠編寫混合了托管和非托管的代碼的程序!!!這樣最大的好處不僅可以將關鍵代碼直接編譯成非托管的代碼,還可以避免被反編譯。
  
  假設現有C++代碼如下:
class UnmanagedClass {
public:
     LPCWSTR GetPropertyA() { return L"Hello!"; }
     void MethodB( LPCWSTR ) {}
};  我們只要再增加一個包裝類到工程文件中:namespace wrapper
{
     public ref class ManagedClass {
     public:
         // Allocate the native object on the C++ Heap via a constructor
         ManagedClass() : m_Impl( new UnmanagedClass ) {}

         // Deallocate the native object on a destructor
         ~ManagedClass() {
             delete m_Impl;
         }

     protected:
         // Deallocate the native object on the finalizer just in case no destructor is called
         !ManagedClass() {
             delete m_Impl;
         }

     public:
         property String ^   get_PropertyA {
             String ^ get() {
                 return gcnew String( m_Impl->GetPropertyA());
             }
         }

         void MethodB( String ^ theString ) {
             pin_ptr<const WCHAR> str = PtrToStringChars(theString);
             m_Impl->MethodB(str);
         }

     private:
         UnmanagedClass * m_Impl;
     };
}
  然后,改變編譯選項為“使用公共語言擴展 /clr”就可以了。這樣,我們把代碼編譯成DLL文件就可以供.NET其它語言調用了。
  最后,C#中可以象如下的代碼一樣調用C++類了:ManagedClass mc = new ManagedClass();
mc.MethoB("Hello");
string s = mc.get_PropertyA;
  場景四:如何在托管C++代碼中混合托管和非托管代碼

  很簡單,只要從#pragma unmanaged編譯指示開始的程序,一率編譯成非托管代碼;要想恢復成托管代碼,只要使用#pragma managed就可以了。如:
  #pragma unmanaged

#include <iostream>
using namespace std;

template<typename T>
void f(T t){
     cout << t << endl;
}

#pragma managed

using namespace System;

void m(String ^ s){
     Console::WriteLine(s);
}

void main(){
     f("Hello");
     m("World");
}  
  生成exe文件后,用反編譯程序查看 f 函數:[PreserveSig, MethodImpl(MethodImplOptions.Unmanaged, MethodCodeType=MethodCodeType.Native), SuppressUnmanagedCodeSecurity]
public static unsafe void modopt(CallConvCdecl) f<char const *>(sbyte modopt(IsSignUnspecifiedByte) modopt(IsConst)*);  
  看不到源碼,而方法屬性標記為Unmanaged。
  如果沒有加上#pragma unmanaged,反編譯得到的 f 函數為:internal static unsafe void modopt(CallConvCdecl) f<char const *>(sbyte modopt(IsSignUnspecifiedByte) modopt(IsConst)* t)
{
       std.basic_ostream<char,std::char_traits<char> >.<<(std.operator<<<struct std::char_traits<char> >(*((basic_ostream<char,std::char_traits<char> >* modopt(IsImplicitlyDereferenced)*) &__imp_std.cout), t), (basic_ostream<char,std::char_traits<char> >* modopt(IsImplicitlyDereferenced) modopt(CallConvCdecl) *(basic_ostream<char,std::char_traits<char> >* modopt(IsImplicitlyDereferenced))) __unep@?endl@std@@$$FYAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z);
}

  其中的函數內容一目了然。如果你的函數沒有調用operator等不好理解的類庫,那么反編譯出來的代碼簡直和源碼沒差別。

  場景五:不想要DLL,能不能直接把C++源代碼與C#源代碼一起編譯成一個單獨的Assembly呢?

  當然是可以的。具體參見:讓C++源碼和C#源碼一起生成單一的Assembly

  開心一刻:我只會C++不懂.NET不懂C#,怎么編寫.NET程序?

  很簡單,你照樣用你的C++寫你的程序,然后測試沒有錯誤后,將編譯選項改為/clr,好了,Rebuild,你的程序現在是.NET了。

  惡搞:“我想問一下,在能將現有的C++代碼直接進行封裝,被C#進行調用,而不是去調用DLL,也就是不生成DLL,就在C#下能直接調用VC的工程源文件不?”

  我想,提問的人是不是指,現有c++源碼,但不想費勁去轉換成C#源碼,但又想能與C#一起編譯。
  于是我就給了一個極其變態的方法,不過,個人是不建議使用這種變態的方法啊。方法如下:
  1 先將C++源碼,改用CLR編譯選項,編譯成.NET的Assembly(DLL文件)。
  2 然后用reflector等反編譯軟件,反編譯成C#代碼,并導出(reflector有專門的導出插件)。
  3 將導出的C#代碼,添加上新寫的C#代碼一起編譯。
  
  這種方法生成的代碼很是恐怖,強烈建議不要把C++源碼就這么丟了,否則后果自負。

posted on 2008-08-15 16:36 cpsprogramer 閱讀(5128) 評論(3)  編輯 收藏 引用 所屬分類: VC++

FeedBack:
# re: 您也使用托管C++嗎?[未登錄] 2008-08-15 19:08 ZZ
c++本身也變態,不要用托管的  回復  更多評論
  
# re: 您也使用托管C++嗎? 2008-08-17 17:48 dell筆記本
軟件的移植簡直是一種折磨,托管C++到很有趣  回復  更多評論
  
# re: 您也使用托管C++嗎? 2008-08-18 12:05 WINZHENG
我現在是用C#,但是CEO交給我了兩個VC的程序,讓我優化這個VC程序,我該從什么地方著手,謝謝  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              六月婷婷一区| 亚洲视频在线视频| 一本色道精品久久一区二区三区 | 免费观看国产成人| 欧美在线999| 国产精品啊啊啊| 亚洲国产电影| 影音先锋国产精品| 欧美在线视频一区二区| 亚洲影音先锋| 欧美日韩理论| 亚洲人成人99网站| 亚洲日本激情| 免费一级欧美在线大片| 免费不卡中文字幕视频| 国产综合色产| 久久成人在线| 久久久青草婷婷精品综合日韩| 国产精品国产a级| 亚洲精品中文字| 一本大道久久a久久精品综合| 久久久久青草大香线综合精品| 久久精品人人做人人综合 | 亚洲伊人第一页| 欧美精品日本| 亚洲精选一区| 亚洲视频一区二区在线观看 | 亚洲欧洲美洲综合色网| 91久久精品美女高潮| 美女视频黄a大片欧美| 另类亚洲自拍| 亚洲国产精品久久91精品| 美女久久一区| 亚洲精品欧美精品| 亚洲视频二区| 国产欧美日本| 久久美女性网| 亚洲激情视频在线播放| 亚洲视频导航| 国产精品尤物| 久久久夜夜夜| 91久久久久| 午夜精品久久久久久| 国产日韩在线视频| 久久久久久91香蕉国产| 欧美激情一区二区三区高清视频| 亚洲日本欧美在线| 欧美日韩精品一区二区三区四区 | 欧美激情综合色综合啪啪| 亚洲精品在线三区| 性久久久久久久久久久久| 国内精品久久久久久 | 久久精品道一区二区三区| 欧美fxxxxxx另类| 一本色道久久综合狠狠躁篇怎么玩| 欧美色精品天天在线观看视频 | 亚洲视频碰碰| 老司机67194精品线观看| 亚洲精品一区二区网址| 国产精品成人免费| 久久久欧美精品sm网站| 99re6热只有精品免费观看| 久久精品首页| 在线视频欧美日韩精品| 国产亚洲一二三区| 欧美精品一区二区三区蜜桃| 亚洲欧美日韩一区二区| 亚洲电影成人| 久久精品人人做人人综合| 亚洲区第一页| 国产亚洲成av人片在线观看桃| 欧美超级免费视 在线| 亚洲欧美国产不卡| 亚洲激情在线播放| 久久夜色精品一区| 亚洲一区bb| 亚洲国产精品999| 国产精品社区| 欧美伦理视频网站| 久久久99久久精品女同性| 9色精品在线| 亚洲大胆视频| 久久久综合视频| 亚洲综合精品一区二区| 亚洲欧洲美洲综合色网| 国产日韩欧美在线| 国产精品草莓在线免费观看| 女人香蕉久久**毛片精品| 欧美一区二区三区另类| 中日韩美女免费视频网址在线观看| 欧美国产亚洲另类动漫| 久久亚洲春色中文字幕| 欧美在线观看一区二区| 亚洲一区二区精品视频| 亚洲美女免费视频| 亚洲黄色在线视频| 亚洲第一在线综合网站| 国产亚洲精品成人av久久ww| 国产精品美女在线| 国产精品夫妻自拍| 欧美日韩三级电影在线| 欧美片第一页| 欧美日本国产一区| 欧美激情视频在线播放| 欧美激情按摩在线| 欧美成人免费观看| 欧美jizz19hd性欧美| 开心色5月久久精品| 久久久久久日产精品| 久久久久**毛片大全| 欧美一区二区在线看| 性欧美8khd高清极品| 欧美一区影院| 久久久久久久高潮| 久久久免费观看视频| 久久亚洲色图| 鲁大师成人一区二区三区| 麻豆精品国产91久久久久久| 美女国产一区| 欧美激情在线免费观看| 欧美日韩精品中文字幕| 欧美日韩天天操| 国产精品视频网| 国产综合一区二区| 亚洲黄色在线看| 一区二区三区产品免费精品久久75| 一区二区精品在线| 欧美一级大片在线观看| 久久久久久久欧美精品| 欧美大片一区二区| 日韩亚洲不卡在线| 性做久久久久久久久| 久久久综合免费视频| 欧美激情麻豆| 国产精品亚洲а∨天堂免在线| 国产真实久久| 亚洲美女91| 欧美在线视频免费播放| 欧美成人伊人久久综合网| 亚洲精品在线视频观看| 亚洲中无吗在线| 老司机午夜免费精品视频| 欧美日韩国产色综合一二三四| 国产农村妇女毛片精品久久莱园子| 一区视频在线看| 亚洲影院污污.| 久久久综合精品| 亚洲精品乱码久久久久久蜜桃麻豆| 亚洲男人第一av网站| 久久综合网hezyo| 国产精品青草久久| 亚洲激情视频在线播放| 欧美伊人久久| 亚洲精品黄色| 亚洲欧美亚洲| 欧美人牲a欧美精品| 国产一区二区三区在线观看精品| 亚洲美女电影在线| 久久岛国电影| 亚洲人午夜精品| 久久九九国产精品| 国产精品亚洲一区| 99香蕉国产精品偷在线观看| 久久亚洲国产精品一区二区 | 欧美二区乱c少妇| 亚洲欧美国产另类| 欧美日韩无遮挡| 亚洲精品影视在线观看| 久久精品成人| 亚洲一二三四区| 欧美精品在线视频观看| 亚洲狠狠丁香婷婷综合久久久| 久久九九电影| 亚洲一本视频| 国产精品国内视频| 一区二区三区|亚洲午夜| 欧美freesex8一10精品| 欧美在线观看你懂的| 国产精品日日摸夜夜摸av| 99精品欧美| 亚洲国产精品电影在线观看| 久久久久久9999| 国产一区在线播放| 欧美专区第一页| 午夜精品久久久久久99热软件| 欧美小视频在线| 国产精品99久久不卡二区| 亚洲国产精品精华液2区45| 久久久99免费视频| 黄色一区三区| 久久久久久穴| 久久国产精品99国产精| 狠狠爱综合网| 免费精品视频| 美女国内精品自产拍在线播放| 亚洲国产精品va在看黑人| 久久偷窥视频| 久久这里只精品最新地址| 亚洲国产日日夜夜| 亚洲国产婷婷综合在线精品 |