在写一些对操作系统依赖性很强的东西时,调用windows API是很经常的。调用API就有托管与非托管交互的问题发生。非托管API返回的对象在托管环境下用IntPtr对象可以接收并传递给其它需要的非托管API,而非托管返回的结构数据可以通过在托管里面定义结构类型来接收使用。但是如果需要把托管下的对象传送给非托管API作为参数,然后再取回,就需要用到GCHandle结构了。

看代码:

  1using System;
  2using System.Threading; 
  3using System.Runtime.InteropServices; 
  4
  5    /**//// <summary>
  6    /// Win32IOCPSample 的摘要说明。
  7    /// iocp的示范列子,一个成功传递引用类型参数到非托管环境的例子
  8    /// </summary>
  9    public class Win32IOCPSample
 10    {
 11        public Win32IOCPSample(int maxThread)
 12        {
 13            try 
 14            
 15                // Create an IO Completion Port for Thread Pool use 
 16                GetHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, IntPtr.Zero, maxThread); 
 17            
 18                // Test to make sure the IO Completion Port was created 
 19                if (GetHandle == 0) 
 20                    throw new Exception("Unable To Create IO Completion Port"); 
 21            } 
 22            catch 
 23            
 24                throw new Exception("Unhandled Exception"); 
 25            } 
 26        }
 27
 28        [DllImport("Kernel32")]
 29        private static extern void CloseHandle(UInt32 handle);
 30        [DllImport("Kernel32")]
 31        private static extern UInt32 CreateIoCompletionPort(UInt32 fileHandle, UInt32 existingCompletionPort,IntPtr completionKey, int numberOfConcurrentThreads);
 32        [DllImport("Kernel32")]
 33        private static extern bool PostQueuedCompletionStatus(UInt32 completionPort, int numberOfBytesTransferred,IntPtr completionKey, IntPtr overlapped);
 34        [DllImport("Kernel32")]
 35        private static extern bool GetQueuedCompletionStatus(UInt32 completionPort, ref int numberOfBytes,ref IntPtr completionKey, ref IntPtr overlapped,UInt32 milliseconds);
 36 
 37        private const UInt32 INVALID_HANDLE_VALUE = 0xffffffff; 
 38        private const UInt32 INIFINITE = 0xffffffff; 
 39        public    static readonly Int32 SHUTDOWN_IOCPTHREAD = 0x7fffffff; 
 40        public delegate void USER_FUNCTION(object iValue); 
 41        private UInt32 m_hHandle; 
 42        private UInt32 GetHandle { get { return m_hHandle; } set { m_hHandle = value; } } 
 43
 44        private Boolean m_bDisposeFlag; 
 45
 46        /**//// <summary>
 47        /// 释放标志
 48        /// </summary>
 49        private Boolean IsDisposed { get { return m_bDisposeFlag; } set { m_bDisposeFlag = value; } } 
 50        ~Win32IOCPSample() 
 51        
 52            if (!IsDisposed) 
 53                Dispose(); 
 54        } 
 55 
 56        public void Dispose() 
 57        
 58            unsafe 
 59            
 60                // Close the IOCP Handle 
 61                CloseHandle(GetHandle); 
 62            } 
 63        } 
 64        public object getEvent()
 65        {
 66            int uiNumberOfBytes=0; 
 67            object obj=null;
 68            try 
 69            
 70                //声明接收对象的指针
 71                IntPtr key=IntPtr.Zero;
 72                IntPtr ovp=IntPtr.Zero;
 73                
 74                // Wait for an event 
 75                //取回对象指针
 76                if(GetQueuedCompletionStatus(GetHandle, ref uiNumberOfBytes, ref key, ref ovp, INIFINITE)==true)
 77                
 78
 79                    if(key!=IntPtr.Zero && ovp!=IntPtr.Zero)
 80                    {
 81                        //把指针转换会GCHandle对象
 82                        GCHandle gcKey=(GCHandle)key;
 83                        GCHandle gcOvp=(GCHandle)ovp;
 84                        // Was this thread told to shutdown 
 85                        if (ovp!=IntPtr.Zero && gcOvp.Target.ToString().Equals(SHUTDOWN_IOCPTHREAD.ToString())) 
 86                        {
 87                            gcOvp.Free();
 88                            gcKey.Free();
 89
 90                            return obj;
 91                        }
 92                        //通过GCHandle对象取得其所表示的对象
 93                        obj=gcOvp.Target;
 94
 95                        gcOvp.Free();
 96                        gcKey.Free();
 97                    }
 98                }
 99            }
100            catch(Exception ex)
101            {
102                throw ex;
103            }
104            return obj;
105        }
106
107        public void PostEvent(object iValue) 
108        
109            try 
110            
111                // Only add work if we are not disposing 
112                if (IsDisposed == false) 
113                
114                    
115                    int i=0;
116                    //取托管对象的句柄
117                    GCHandle gcValue=GCHandle.Alloc(iValue);
118                    GCHandle gcKey=GCHandle.Alloc(i);
119                    // Post an event into the IOCP Thread Pool 
120                    //把对象句柄作为参数传递给api
121                    PostQueuedCompletionStatus(GetHandle, 4, (IntPtr)gcKey, (IntPtr)gcValue); 
122                } 
123            } 
124            catch (Exception e) 
125            
126                throw e; 
127            } 
128            catch 
129            
130                throw new Exception("Unhandled Exception"); 
131            } 
132        }   
133    }

代码是调用了iocp的其中几个api(什么是iocp和为什么这么调用,日后再说),代码里面:
public void PostEvent(object iValue) 和   public object getEvent()两个方法,分别就是把对象传递给非托管和从非托管取回对象的方法。其中比较关键的是GCHandle结构所起的作用。它提供从非托管内存访问托管对象的方法。

就是通过它来完成把托管对象传递给非托管环境的,具体的方法在代码可以很清楚看到。下面是测试代码:

 1static Win32IOCPSample w;
 2public static void Main(string[] args) 
 3
 4    
 5    w=new Win32IOCPSample(2);
 6
 7    for(int i=0; i<5;i++)
 8    {
 9        Thread t=new Thread(new ThreadStart(worker));
10        t.IsBackground=true;
11        t.Start();
12    }
13    
14    for(int i =1;i<20;i++) 
15    
16        w.PostEvent(ExTimer.GetExactNow()); 
17    } 
18
19    for(int i =0;i<5;i++) 
20    
21        w.PostEvent(Win32IOCPSample.SHUTDOWN_IOCPTHREAD);
22    }
23    Thread.Sleep(100); 
24
25
26    Console.ReadLine();
27    w.Dispose(); 
28
29
30static public void worker()
31{
32    while(true)
33    {
34        try
35        {
36            object obj=w.getEvent();
37
38            Console.Write(qp.Duration(1).ToString()+"\r\n");
39            if(obj==null) break;
40
41            Console.WriteLine("Value: {0}", obj.ToString()); 
42
43            Thread.Sleep(500);
44        }
45        catch(Exception ex)
46        {
47            Console.WriteLine("ex: {0}", ex.ToString()); 
48        }
49    }
50}

整个列子就是这么一回事。这是1.1使用的办法。其它更高版本还没有深入接触。如果谁有其他方法,欢迎分享。

转载于:https://www.cnblogs.com/baoli/archive/2008/01/06/1027446.html

一个成功传递引用类型参数到非托管环境的例子相关推荐

  1. 【C++】函数 指针类型参数 与 引用类型参数 对比 ( 修改外部变量需要传入的参数要求 | 参数作返回值 )

    文章目录 I . 博客总结 . 指针与引用类型参数 II . 指针作为参数和返回值 III . 引用参数简介 IV . 引用作为参数和返回值 I . 博客总结 . 指针与引用类型参数 1 . 讨论问题 ...

  2. C# 托管资源和非托管资源(Dispose、析构函数)

    https://www.cnblogs.com/herenzhiming/articles/9691524.html 资源分类: 托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内 ...

  3. 非托管C++程序中调用C#的dll

    刚去的新公司分配了我一个项目需求,将PPT文件(包括*.ppt和*.pptx)转换成多张png图片.由于以前只有native C++的经验,在网上逛了多圈后,发现都是使用C#实现这个功能的,被这个需求 ...

  4. C# 托管资源和非托管资源

    原文地址:http://blog.csdn.net/zlwzlwzlw/article/details/7918633 托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内存资源.托 ...

  5. Windbg教程-调试非托管程序的基本命令上

    Windbg是跟visual studio差不多的一个调试器,可以用来调试非托管程序(native application),也可以调试托管程序(managed application).它比VS强的 ...

  6. .NET中的托管资源与非托管资源

    托管资源指的是.NET可以自动进行回收的资源,主要是指托管堆上分配的内存资源.托管资源的回收工作是不需要人工干预的,有.NET运行库在合适调用垃圾回收器进行回收. 非托管资源指的是.NET不知道如何回 ...

  7. Window Services的调试和非托管dll的引用及其他一些注意问题

    一个asp.net项目,客户提出需求,需要增加即时短信提醒功能:因为项目中使用到GPRS模块做无线通讯,还可以用作发送短信,就用了这个GPRS模块发短信提醒: 这个即时短信提醒功能,计划用window ...

  8. C#Maeshal类——托管资源和非托管资源转换

    C#--Marshal.StructureToPtr方法简介 http://blog.csdn.net/livelylittlefish/article/details/2423764         ...

  9. 托管代码C#调用非托管C++ API, 封送嵌套结构体数组

    一.前言: 最近这两天由于项目需要,提供给客户的C++ 动态库需要返回自定义结构体数组,网上也查了很多资料, 推荐一本书, <精通.NET互操作:P/Invoke.C++ Interop和COM ...

最新文章

  1. TEASOFT辅助服务程序UDPCopy 功能介绍
  2. 【UIKit】表格自定义单元格(UITableViewCll)
  3. IOS学习笔记 O2
  4. 时间序列的异常值处理
  5. CUDA学习笔记之程序优化
  6. 再分享 5 个 vs 调试技巧
  7. C语言函数库:动态库和静态库优缺点比较
  8. chinaunix-索引资料
  9. POJ-3621 Sightseeing Cows 01分数(参数搜索)规划问题-最优比率环
  10. Java网络编程(精简版)
  11. html中支持的常用中文字体
  12. echarts 实现自定义tooltip提示框浮层内容显示
  13. java-php-python-ssm在线装机报价系统计算机毕业设计
  14. TCP的乱序和丢包判断(附Reordering更新算法)-实例case
  15. DHCP的原理与配置
  16. 股票入门:什么是股票指数,什么是大盘指数
  17. C# 文字转换最简单的方法
  18. java代码条形码链接网址_Java在PDF中添加条形码
  19. 文字转换片假字_平假名与片假名
  20. Tekla二次开发——AutoCAD导入Tekla

热门文章

  1. C语言:用typedef定义结构
  2. pandas:read_excel()和to_excel函数解析
  3. 剪切音乐有什么简单的制作方法
  4. 基于Selenium+Python的web自动化测试框架(附框架源码+项目实战)
  5. CodeForces-893B(Beautiful Divisors)
  6. 飞桨CPU版的PaddlePaddle安装总结
  7. Java B组蓝桥杯第八届国赛:生命游戏
  8. 前端 get 请求 拼接数组转换成字符串
  9. 3dmax如何拆分模型_3dmax怎么切割模型(3D模型怎么剪切)
  10. 监控硬盘和普通硬盘有多大差别?