• 拖不托管是浮云——飘过托管的边界


      写这篇博文为了说明如何"托管"与'"非托管"互用问题。具体来讲包括:如何在托管代码中使用非托管代码、如何在托管代码中使用非托管dll、如何在非托管代码中使用托管dll以及托管代码。直接给出最直接的描述---代码。

      1.托管代码中使用非托管代码

    给出个可行示例,简单的说明下下面这段代码的功能--“灰度化”图像。 

    //托管代码调用非托管代码
    //DebugLZQ以前写的
    //unsafe{}中代码为非托管代码
    private void pointer_Click(object sender, EventArgs e)
            {
                if (curBitmap != null)
                {
                    myTimer.ClearTimer();
                    myTimer.Start();
                    Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
                    System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
                    byte temp = 0;
                    unsafe
                    {
                        byte* ptr = (byte*)(bmpData.Scan0);
                        for (int i = 0; i < bmpData.Height; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]);
                                ptr[0] = ptr[1] = ptr[2] = temp;
                                ptr += 3;
                            }
                            ptr += bmpData.Stride - bmpData.Width * 3;
                        }
                    }
                    curBitmap.UnlockBits(bmpData);
                    myTimer.Stop();
                    timeBox.Text = myTimer.Duration.ToString("####.##") + " 毫秒"; 
                    Invalidate();
                }
            }

    为了使程序能正确执行,需要设置项目的属性生成为:“允许不安全代码”。

    这样程序就可正常运行,效果如下:

     

       2.托管代码中使用非托管dll

      前面在讲计时器的时候提到过,下面给出一个完整可用的高性能计时器,顺便给出调用非托管dll的示例。代码如下: 

    using System;
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    using System.Threading;
    //DebugLZQ
    //www.cnblogs.com/DebugLZQ
    //这是使用的一个计时器,拿这个来说明如何在托管代码中使用非托管dll
    namespace gray
    {
        internal class HiPerfTimer
        {
            [DllImport("Kernel32.dll")]
            private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
    
            [DllImport("Kernel32.dll")]
            private static extern bool QueryPerformanceFrequency(out long lpFrequency);
    
            private long startTime, stopTime;
            private long freq;
    
            // Constructor
            public HiPerfTimer()
            {
                startTime = 0;
                stopTime = 0;
    
                if (QueryPerformanceFrequency(out freq) == false)
                {
                    // high-performance counter not supported
                    throw new Win32Exception();
                }
            }
    
            // Start the timer
            public void Start()
            {
                // lets do the waiting threads there work
                Thread.Sleep(0);
    
                QueryPerformanceCounter(out startTime);
            }
    
            // Stop the timer
            public void Stop()
            {
                QueryPerformanceCounter(out stopTime);
            }
    
            // Returns the duration of the timer (in milliseconds)
            public double Duration
            {
                get
                {
                    return (double)(stopTime - startTime) * 1000 / (double)freq;
                }
            }
    
            public void ClearTimer()
            {
                startTime = 0;
                stopTime = 0;
            }
        }
    }

    用法很简单:

    private HiPerfTimer myTimer=new HiPerfTimer();
    myTimer.Start();
    myTimer.Stop();
    myTimer.Duration//wanted

    再写一个例子

    using System;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    using System.Threading;
    
    namespace PInvoke
    {
        class Program
        {
            static void Main(string[] args)
            {
                if (!MessageBeep(0))
                {
                    //不会执行
                    Int32 err = Marshal.GetLastWin32Error();
                    throw new Win32Exception(err);
                }
            }
    
            [DllImport("User32.dll")]
            private static extern Boolean MessageBeep(UInt32 beepType);
        }
    }

    3-4.非托管代码中调用托管dll、写托管代码。

    前一篇博文谈到CLR宿主的时候,遇到过这个问题,托管Assembly代码如下:

    using System;
    
    namespace NET.MST.Eighth.SimpleAssembly
    {
        /// <summary>
        /// 一个简单的“托管”程序集,功能是输出传入的字符串
        /// </summary>
        public class SimpleAssembly
        {
            static int WriteString(String s)
            {
                Console.WriteLine("CLR Host Output:" + s);
                return 1;
            }
        }
    }

    在非托管代码中加载CLR运行托管代码,代码如下:

    //DebugLZQ
    //http://www.cnblogs.com/DebugLZQ
    //C++工程中加载CLR,运行托管代码
    #include "stdafx.h"
    #include <windows.h>
    //这里定义加载哪个版本的CLR
    #include <MSCorEE.h>    
    
    #pragma   comment(lib,"MSCorEE.lib")
    
    //加载CLR,从而运行托管代码
    void main(int argc, _TCHAR* argv[])
    {
        ICLRRuntimeHost *pHost;
        HRESULT hr=CorBindToRuntimeEx(
            NULL,
            NULL,
    ,
            CLSID_CLRRuntimeHost,
            IID_ICLRRuntimeHost,
            (PVOID*)&pHost);
    
        
        pHost->Start();
    
        ICLRControl* clrControl = NULL;
        hr = pHost->GetCLRControl(&clrControl);
    
        DWORD* returnvalue=NULL;
    
        //开始运行托管代码
        pHost->ExecuteInDefaultAppDomain(
         L"..\\..\\..\\SimpleAssembly\\bin\\Debug\\SimpleAssembly.dll",
         L"NET.MST.Eighth.SimpleAssembly.SimpleAssembly",
         L"WriteString",
         L"http://www.cnblogs.com/DebugLZQ",
         returnvalue);
        
        system("pause");
        //结束时卸载CLR
    }

    程序运行结果如下:

       文章旨在给出了一种“托管”--“非托管”互相调用的切实可行的方法,没有什么可圈可点的地方,请“牛人”勿喷击DebugLZQ。当然,如果你觉得这篇博文对你有帮助,请点击下面的“绿色通道”---“关注DebugLZQ”,共同交流进步~

  • 相关阅读:
    主机访问虚拟机网络服务失败
    关于接收者为指针的方法
    slice的部分说明
    ES基础知识
    静态语言和动态语言
    数据库设计三大范式
    SparkSQL小例子
    spark小例子
    spark 分析作者发布文章的总阅读量
    spark和hadoop差异
  • 原文地址:https://www.cnblogs.com/DebugLZQ/p/2636919.html
Copyright © 2020-2023  润新知