<li id="kueim"></li>
<abbr id="kueim"><tr id="kueim"></tr></abbr>
  • <ul id="kueim"></ul>
    <ul id="kueim"></ul>
    
    
    <strike id="kueim"><rt id="kueim"></rt></strike>
  • 長沙快付新聞資訊
    您當(dāng)前的位置是: 首頁->技術(shù)資訊->.net網(wǎng)站技術(shù)問題

    C#中通過dllimport引入并調(diào)用C的庫

    首發(fā): 長沙快付 版權(quán)所有,未經(jīng)許可嚴(yán)禁轉(zhuǎn)載
     一、寫一個(gè)最簡單的C函數(shù)并編譯成動(dòng)態(tài)庫
    嗯,直入正題,我們先用GVIM寫一個(gè)很簡單的C函數(shù):
    GVIM寫一個(gè)很簡單的C函數(shù)
    然后用GCC對它進(jìn)行編譯(注意:這里是使用Windows中的GCC,采用MinGW安裝,如有不懂如何使用的讀者,可以移步到《如何安裝使用MinGW》進(jìn)行學(xué)習(xí))。
    用GCC對它進(jìn)行編譯
    然后就出現(xiàn)了一個(gè)編譯好的庫,我們C這邊的工作就基本完成了。
     
    二、如何通過Dllimport引入C寫的庫
    如何引入一個(gè)非C#的庫,通常的方法就是采用DllImport,通過P/Invoke機(jī)制進(jìn)行引入。當(dāng)然在Mono上除了使用Dllimport外,還有另外的方式引入,這里我們不作任何探討。
    我們新建一個(gè)控制臺程序,然后寫上我們的程序:
     
     1 namespace demo2
     2 {
     3     internal class Program
     4     {
     5         private static void Main(string[] args)
     6         {
     7             var cLib = new CLib();
     8             var p = CLib.SayHello();
     9             var str = Marshal.PtrToStringAuto(p);
    10             Console.WriteLine(str);
    11             Console.ReadKey();
    12         }
    13     }
    14 
    15     internal class CLib
    16     {
    17         [DllImport("你的so文件路徑/demo1.so")]
    18         public extern static IntPtr SayHello();
    19     }
    20 }
    按下F6編譯之后,我們在運(yùn)行編譯好的exe文件:
    通過Dllimport引入C寫的庫
    瞧,成功調(diào)用了C的函數(shù)了,SO Easy,這里要注意一點(diǎn)的,也是很多童鞋經(jīng)常會(huì)犯的錯(cuò)誤,那就是我們需要找到控制臺bin里的exe,雙擊運(yùn)行,不能直接在VS中按F5調(diào)試運(yùn)行,否則是無法看到C語言輸出的東西的。
     
    三、關(guān)于參數(shù)傳遞
     
    關(guān)于C/C#之間的參數(shù)傳遞,這里水比較深,拋開數(shù)組、結(jié)構(gòu)體等復(fù)雜類型不說,就簡單類型(int、char等)而言我私以為可以分為兩個(gè)部分,其一就是C#向C語言的參數(shù)傳遞,另外就是C語言向C#的return。
    我們先對C#->C的傳遞方式進(jìn)行講解,同樣的我們也繼續(xù)上demo。
    我們定義了一個(gè)計(jì)算加法并輸出的函數(shù),然后修改我們C#的源代碼為:
    using System;
    using System.Runtime.InteropServices;
     
    namespace demo2
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                var a = 10;
                var b = 20;
                var cLib = new CLib();
                unsafe
                {
                    CLib.Add(&a, &b);
                }
                Console.ReadKey();
            }
        }
     
        internal class CLib
        {
            [DllImport("你的路徑/c/demo1.so")]
            public unsafe extern static IntPtr Add(int* a,int* b);
        }
    }
    按下F6之后運(yùn)行exe文件:
    C/C#之間的參數(shù)傳遞
    Oh~Year。同樣沒有問題。
    我們在此基礎(chǔ)上,試試字符串,同樣的,我們在C語言這里添加一個(gè)新函數(shù):
    C/C#之間的參數(shù)傳遞添加
    同樣的C#這里也進(jìn)行改造:
    using System;
    using System.Runtime.InteropServices;
     
    namespace demo2
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                var str = "你好,我是小蝶驚鴻";
     
                unsafe
                {
                    fixed (char* p = str)
                    {
                        CLib.Say(p);
                    }
                }
                Console.ReadKey();
            }
        }
     
        internal class CLib
        {
            [DllImport("你的地址/demo1.so")]
            public unsafe extern static IntPtr Say(char* input);
        }
     
    然后再重新生成so文件,重新編譯C#,并點(diǎn)擊exe運(yùn)行:
    重新生成so文件
    可以看出,程序立馬報(bào)了個(gè)錯(cuò)誤,具體原因就不跟各位讀者探討了,大概就是字符串沒有結(jié)束符,造成printf讀取完字符串本身之后還繼續(xù)的讀其他內(nèi)存,造成了越界。我們把代碼小改一下,由外部傳入一個(gè)字符串的長度。這里還需要注意一點(diǎn),那就是在C語言中,char只占一個(gè)字節(jié)而C#中的char則是兩個(gè)字節(jié),由C#傳入的字符串還需要轉(zhuǎn)換一下。修改后的代碼如下圖所示:
    由C#傳入的字符串還需要轉(zhuǎn)換修改的代碼
    同樣的C#代碼也跟著修改: 
    using System;
    using System.Runtime.InteropServices;
     
    namespace demo2
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                var str = "hi,i am xiaodiejinghong";
     
                unsafe
                {
                    fixed (char* p = str)
                    {
                        int length = str.Length;
                        CLib.Say(p, &length);
                    }
                }
                Console.ReadKey();
            }
        }
     
        internal class CLib
        {
            [DllImport("E:/ASP/Mono/project/嵌入技術(shù)/c/demo1.so", CallingConvention = CallingConvention.StdCall)]
            public unsafe extern static IntPtr Say(char* input, int* length);
        }
    }
    編譯后再次運(yùn)行:
    C#中通過dllimport引入并調(diào)用C的庫編譯
    程序正常無誤。至此,C#向C傳遞參數(shù)部分暫且講解完畢,下面我們再講解C#如何接收從C函數(shù)返回的信息。
     
    可能有讀者認(rèn)為直接使用Return即可,在某種程度上,確實(shí)是可以使用Return,譬如返回一個(gè)在C中寫死了的字符串(那是因?yàn)榫幾g器已經(jīng)把這段固定字串當(dāng)成常量存儲(chǔ)起來),但如若需要返回一串動(dòng)態(tài)的字串,這種直接Return的方式就行不通了(字符串離開函數(shù)之后被回收,不信可以試試)。我們需要使用一些其他方法來接收從C返回的資源,在這里,我們要給各位讀者介紹的方式是通過在C#中給出一個(gè)容器,并把它的指針傳入C中,C需要返回的東西都存放到改容器中,這樣想返回的東西就不會(huì)被C回收掉了。
     
    我們的C示例代碼如下:
    C#中通過dllimport引入并調(diào)用C的庫c示例代碼
    C#的代碼如下: 
    using System;
    using System.Runtime.InteropServices;
     
    namespace demo2
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                var str1 = "hi,";
                var str2 = "i am xiaodiejinghong ";
                var l1 = str1.Length;
                var l2 = str2.Length;
                var output = new char[l1 + l2];
                unsafe
                {
                    fixed (char* p1 = str1) fixed (char* p2 = str2) fixed (char* op = output)
                    {
                        CLib.Merge(p1, &l1, p2, &l2, op);
                        Console.WriteLine(Marshal.PtrToStringAnsi((IntPtr)op));
                    }
                }
                Console.ReadKey();
            }
        }
     
        internal class CLib
        {
            [DllImport("你的路徑/demo1.so", CallingConvention = CallingConvention.StdCall)]
            public unsafe extern static IntPtr Merge(char* input1, int* length1, char* input2, int* length2, char* output);
        }
    }
    重新編譯后運(yùn)行:
    C#中通過dllimport引入并調(diào)用C的庫合并成功
    成功合并了。 
    至此,本篇內(nèi)容就到此結(jié)束,關(guān)于C/C#互調(diào)混合編程的水很深,對各方面的要求都很高,可以說,能夠玩轉(zhuǎn)的人必定是雙料達(dá)人。
    • 最新簽約客戶
    • 最新上線網(wǎng)站
    為什么選擇長沙快付公司?

    8年專業(yè)做網(wǎng)站經(jīng)驗(yàn)
    幫助您解決各種需求,并得到滿意方案

    效果滿意后付款
    預(yù)付30%定金,效果讓您滿意后,付全款

    資深用戶體驗(yàn)設(shè)計(jì)師
    秉承"一切以用戶價(jià)值為依歸"理念,重視用戶體驗(yàn),專為企業(yè)需求進(jìn)行定制

    采用國際標(biāo)準(zhǔn)結(jié)構(gòu)建站
    DIV+CSS國際標(biāo)準(zhǔn)構(gòu)建網(wǎng)頁,可有效提高網(wǎng)站訪問速度、提高網(wǎng)站頁面的可維護(hù)

    實(shí)現(xiàn)網(wǎng)絡(luò)營銷[SEO]最大化
    網(wǎng)站程序中融入SEO,有效降低企業(yè)成本

    分享到:
    主站蜘蛛池模板: 四虎国产精品免费观看| 国产一在线精品一区在线观看| 国内精品久久久久久野外| 国产精品多p对白交换绿帽| 久久久久夜夜夜精品国产| 一本一道精品欧美中文字幕| 91久久精品国产成人久久| 精品人妻码一区二区三区| 国产精品高清一区二区人妖| 人妻少妇看A偷人无码精品| 北条麻妃国产九九九精品视频| 91精品国产福利在线导航| 亚洲日韩国产精品乱| 精品无码综合一区| 国产成人精品免高潮在线观看 | 亚洲精品免费视频| 国产成人无码精品一区二区三区| 午夜精品久久久久久久无码| 国产专区日韩精品欧美色| 99久久夜色精品国产网站| 久久精品国产精品青草| 91国在线啪精品一区| 国产精品久久久亚洲| 精品无码久久久久国产| 人妻少妇精品视中文字幕国语| 亚洲国产成人精品无码久久久久久综合| 国产麻豆精品入口在线观看| 国产一成人精品福利网站| 国产成人无码久久久精品一| 国产精品水嫩水嫩| 国产精品美女久久久久| 国产精品自在线拍国产| 国产亚洲精品精华液| 国产精品亚洲片在线观看不卡 | 久久久99精品一区二区| 国产一区二区精品久久岳| 国语自产精品视频| 久久国产乱子伦精品免费午夜| 久久91精品综合国产首页| 欧美精品区一级片免费播放| 欧美午夜精品久久久久久浪潮|