• <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>
            C++-----勇者無敵  
            流媒體、分布式實(shí)時(shí)系統(tǒng)、外掛、設(shè)計(jì)模式、C#
            日歷
            <2008年7月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789
            統(tǒng)計(jì)
            • 隨筆 - 4
            • 文章 - 0
            • 評論 - 1
            • 引用 - 0

            導(dǎo)航

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案(4)

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             
            被C#調(diào)用的DLL一般只需要把導(dǎo)出的函數(shù)以適當(dāng)?shù)男问匠尸F(xiàn)即可調(diào)用,比如
            extern "C" __declspec(dllexport)
            BOOL Integrate3 (){...},這樣的函數(shù),在C#里面聲明如:

            [DllImport("xxx.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
                    public static extern bool Integrate3();,這里的調(diào)用相對是簡單的,而有些數(shù)據(jù)類型則必須通過MarshalAs來做托管類型的轉(zhuǎn)換,如:

            extern "C" __declspec(dllexport)
            BOOL Integrate (LPCWSTR file1, LPCWSTR file2, LPCWSTR outputFile){...}

            由于數(shù)據(jù)類型不一致,所以在聲明時(shí)要注意把類型轉(zhuǎn)換過來。

            [DllImport("xxx.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
                    public static extern bool Integrate([In, MarshalAs(UnmanagedType.LPWStr)]string file1,
                        [In, MarshalAs(UnmanagedType.LPWStr)]string file2, [In, MarshalAs(UnmanagedType.LPWStr)]string outputFile);

            這樣調(diào)用基本是沒有問題,重點(diǎn)在于數(shù)據(jù)類型的轉(zhuǎn)換。多試過幾次了就不問題了。

            另外一個(gè)小小的實(shí)踐經(jīng)驗(yàn)就是在C#中調(diào)試C++的DLL,知道了就是一句話,不知道就要搞半天,在C#項(xiàng)目屬性中“啟用調(diào)試項(xiàng)”中一項(xiàng):“啟用非托管代碼調(diào)試”,鉤上這個(gè),就萬事大吉了,就像你調(diào)試一般的程序一樣。

            C#調(diào)用C++的DLL時(shí),參數(shù)傳遞便成了一個(gè)問題。今天我碰到的一個(gè)問題是,在C++中導(dǎo)出的函數(shù)的參數(shù)是string類型的,在C#中通過string的參數(shù)調(diào)用時(shí),便會出現(xiàn)該內(nèi)存已損壞或不能讀取的異常信息。后來我把C++的導(dǎo)出函數(shù)的參數(shù)由string改為LPTSTR類型,也即char*類型,然后在C#中對應(yīng)的參數(shù)改為StringBuilder類型,既解決了傳進(jìn)去的參數(shù)問題,又解決了傳出參數(shù)的問題。

            DllImport知識拓展:DllImport 
             .net 框架程序可以通過靜態(tài) DLL 入口點(diǎn)的方式來訪問本機(jī)代碼庫。DllImport 屬性用于指定包含外部方法的實(shí)現(xiàn)的dll 位置。

            DllImport 屬性定義如下:
              
            namespace System.Runtime.InteropServices
            {
             [AttributeUsage(AttributeTargets.Method)]
             public class DllImportAttribute: System.Attribute
             {
              public DllImportAttribute(string dllName) {...}
              public CallingConvention CallingConvention;
              public CharSet CharSet;
              public string EntryPoint;
              public bool ExactSpelling;
              public bool PreserveSig;
              public bool SetLastError;
              public string Value { get {...} }
             }
            }
              
              說明:
              
             1、DllImport只能放置在方法聲明上。 
                2、DllImport具有單個(gè)定位參數(shù):指定包含被導(dǎo)入方法的 dll 名稱的 dllName 參數(shù)。 
                3、DllImport具有五個(gè)命名參數(shù):
                 a、CallingConvention 參數(shù)指示入口點(diǎn)的調(diào)用約定。如果未指定 CallingConvention,則使用默認(rèn)值 CallingConvention.Winapi。
                 b、CharSet 參數(shù)指示用在入口點(diǎn)中的字符集。如果未指定 CharSet,則使用默認(rèn)值 CharSet.Auto。
               c、EntryPoint 參數(shù)給出 dll 中入口點(diǎn)的名稱。如果未指定 EntryPoint,則使用方法本身的名稱。
               d、ExactSpelling 參數(shù)指示 EntryPoint 是否必須與指示的入口點(diǎn)的拼寫完全匹配。如果未指定 ExactSpelling,則使用默認(rèn)值 false。
               e、PreserveSig 參數(shù)指示方法的簽名應(yīng)當(dāng)被保留還是被轉(zhuǎn)換。當(dāng)簽名被轉(zhuǎn)換時(shí),它被轉(zhuǎn)換為一個(gè)具有 HRESULT 返回值和該返回值的一個(gè)名為 retval 的附加輸出參數(shù)的簽名。如果未指定    PreserveSig,則使用默認(rèn)值 true。
                  f、SetLastError 參數(shù)指示方法是否保留 Win32"上一錯(cuò)誤"。如果未指定 SetLastError,則使用默認(rèn)值 false。 
             4、它是一次性屬性類。
             5、此外,用 DllImport 屬性修飾的方法必須具有 extern 修飾符。

            下面是 C# 調(diào)用 Win32 MessageBox 函數(shù)的示例:
              
            using System;
            using System.Runtime.InteropServices;
            class MainApp
            {

                 //通過DllImport引用user32.dll類。MessageBox來自于user32.dll類
             [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 );
             }
            }
            面向?qū)ο蟮木幊陶Z言幾乎都用到了抽象類這一概念,抽象類為實(shí)現(xiàn)抽象事物提供了更大的靈活性。C#也不例外, C#通過覆蓋虛接口的技術(shù)深化了抽象類的應(yīng)用。欲了解這方面的知識,請看下一節(jié)-覆蓋虛接口

            這里講述的是C#調(diào)用標(biāo)準(zhǔn)動態(tài)庫的問題, 在我以前的文件中講到過, C#調(diào)用Win32API, 原理是一樣的. 這里我詳細(xì)講解用C寫一個(gè)標(biāo)準(zhǔn)的動態(tài)庫, 然后讓C#調(diào)用. (本篇適合初學(xué)者, 中間沒有任何冗余代碼, 簡潔明了)
            軟件環(huán)境: VC6.0(當(dāng)然其他版本的VC5也可以)
            1.制作標(biāo)準(zhǔn)動態(tài)庫


            __declspec(dllexport) int __cdecl add(int, int);//這一句是聲明動態(tài)庫輸出一個(gè)可供外不調(diào)用的函數(shù)原型.
            int add(int a,int b) {//實(shí)現(xiàn)這個(gè)函數(shù)
            return a+b;
            }


            以上簡單3行代碼,聲明一個(gè)add的方法, 輸入?yún)?shù)是兩個(gè)int參數(shù),返回這兩個(gè)數(shù)之和. 保存為MyLib.c
            然后執(zhí)行編譯命令.
            H:\XSchool\C#-School\HowTo>cl /LD MyLib.c
            Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86
            Copyright (C) Microsoft Corp 1984-1998. All rights reserved.

            MyLib.c
            Microsoft (R) Incremental Linker Version 6.00.8447
            Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

            /out:MyLib.dll
            /dll
            /implib:MyLib.lib
            MyLib.obj
               Creating library MyLib.lib and object MyLib.exp

            確信有以上輸出, 說明編譯成功生成了動態(tài)庫.

            2.編寫C-Sharp程序調(diào)用該動態(tài)庫
            using System;
            using System.Runtime.InteropServices;//這是用到DllImport時(shí)候要引入的包

            public class InvokeDll {
            [DllImport("MyLib.dll", CharSet=CharSet.Auto)]
            static extern int add(int a,int b);//聲明外部的標(biāo)準(zhǔn)動態(tài)庫, 跟Win32API是一樣的.

            public static void Main() {
            Console.WriteLine(add(10,30));
            }
            }
            保存為InvokeDll.cs文件, 與MyLib.dll置于同一目錄, 編譯該文件.
            H:\XSchool\C#-School\HowTo>csc invokedll.cs
            將生成Invokedll.exe, 可以執(zhí)行該文件.
            以上是C-Sharp調(diào)用標(biāo)準(zhǔn)動態(tài)庫的全過程, 本來覺得很簡單的東西, 一直都沒有想寫, 碰巧今日遇一朋友問及此事, 就順便寫了下來.

            posted on 2008-07-30 16:54 李明坤 閱讀(6278) 評論(1)  編輯 收藏 引用
            評論:
            • # re: C#中調(diào)試C++的DLL[未登錄]  haha Posted @ 2015-06-24 11:53
              你好,我也遇到C#調(diào)用C++DLL的情況,但是有所不同的是,我引用的這個(gè)C++DLL又引用了另外一個(gè)C++DLL,我可以調(diào)試跟到第一層C++DLL,卻無法調(diào)試跟到第二個(gè)C++DLL,不知這個(gè)問題怎么解決,求教一下  回復(fù)  更多評論   


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


             
            Copyright © 李明坤 Powered by: 博客園 模板提供:滬江博客
            久久99久久成人免费播放| 2022年国产精品久久久久| 亚洲国产一成久久精品国产成人综合 | 久久天天躁狠狠躁夜夜网站 | 精品久久久久久无码人妻热| 欧美与黑人午夜性猛交久久久| 99精品国产综合久久久久五月天 | 久久精品久久久久观看99水蜜桃 | 久久久久久久97| 久久99精品国产一区二区三区| 欧美久久一区二区三区| 99国产欧美久久久精品蜜芽| 日日狠狠久久偷偷色综合免费| avtt天堂网久久精品| 奇米影视7777久久精品人人爽| 91精品国产91久久| 久久久久99精品成人片直播| 久久综合一区二区无码| 国产精品99久久久久久宅男| 99久久久精品免费观看国产| 99久久99久久精品国产片果冻| 久久嫩草影院免费看夜色| 国产亚洲精午夜久久久久久| 91精品国产综合久久久久久| 狠狠色婷婷久久一区二区| 久久精品桃花综合| 四虎影视久久久免费| 久久久久国产日韩精品网站| 亚洲成色999久久网站| 狠狠久久亚洲欧美专区| 久久久无码精品亚洲日韩蜜臀浪潮| 久久成人国产精品免费软件| 久久久午夜精品福利内容| 无夜精品久久久久久| 亚洲欧美日韩精品久久亚洲区| 欧美色综合久久久久久| 日韩AV毛片精品久久久| 久久国产精品无| 精品久久人人爽天天玩人人妻| 国产成人精品三上悠亚久久| 亚洲国产精品无码久久SM|