来源:www.cncfan.com | 2006-8-30 | (有2344人读过)
class PInvokeApp { [DllImport("user32.dll", CharSet=CharSet.Ansi)] //CharSet.Ansi指定Ansi版本的函数(MessageBoxA),CharSet.Unicode指定Unicode版本的函数(MessageBoxW) static extern int MessageBox(int hWnd, string msg, string caption, int type); //声明DLL中的函数 //[DllImport("user32.dll", EntryPoint="MessageBoxA")] //用这种方法使用不同的函数名 //static extern int MsgBox(int hWnd, string msg, string caption, int type); //[DllImport("user32.dll", CharSet=CharSet.Unicode)] //调用Unicode版的DLL函数 //static extern int MessageBox(int hWnd, [MarshalAs(UnmanagedType.LPWStr)]string msg, // [MarshalAs(UnmanagedType.LPWStr)]string caption, int type); //将LPWStr翻译为string型,缺省情况系统只将LPStr翻译成string public static void Main() { MessageBox(0, "Hello, World!", "CaptionString", 0); //调用DLL中的函数 } } 例2,使用回调: class CallbackApp { [DllImport("user32.dll")] static extern int GetWindowText(int hWnd, StringBuilder text, int count);
delegate bool CallbackDef(int hWnd, int lParam);
[DllImport("user32.dll")] static extern int EnumWindows(CallbackDef callback, int lParam);
static bool PrintWindow(int hWnd, int lParam) { StringBuilder text = new StringBuilder(255); GetWindowText(hWnd, text, 255); Console.WriteLine("Window Caption: {0}", text); return true; }
static void Main() { CallbackDef callback = new CallbackDef(PrintWindow); EnumWindows(callback, 0); } } 关键字unsafe指定标记块在非控环境中运行。该关键字可以用于所有的方法,包括构造函数和属性, 甚至还有方法中的代码块。关键字fixed负责受控对象的固定(pinning)。Pinning是一种动作,向 垃圾收集器(Garbage Collector, GC)指定一些不能被移动的对象。为了不在内存中产生碎片,.NET 运行环境把对象四处移动,以便于最有效地利用内存。使用fixed后指定对象将不会被移动,所以就 可以用指针来访问它。 C#中只能得到值类型、数组和字符串的指针。在数组的情况下,第一个元素必须是值类型,因为C# 实际上是返回一个指向数组第一个元素的指针,而不是返回数组自身。 & 取一个变量的内存地址(即指向该变量的指针) * 取指针所指变量的值 -> 取成员 例: using System; class UnsafeApp { public static unsafe void GetValues(int* x, int* y) { *x = 6; *y = 42; }
public static unsafe void Main() { int a = 1; int b = 2; GetValues(&a, &b); } } fixed语法为:fixed(type* ptr = expression) statements 其中type也可以为非控类型,也可是void;expression是任何产生一个type指针的表达式; statements是应用的代码块。例: fixed (int* f = &foo.x) //foo是Foo类的一个实例,x是Foo类的一个int属性 { SetFooValue(f); //SetFooValue方法的定义为unsafe static void SetFooValue(int* x) } 传统的COM组件可以通过互操作层(COM Interop)与.NET运行环境交互。互操作层处理在托管运行环境和非托管区域 中的COM组件操作之间传递所有的消息。 要使COM组件能在.NET环境中使用,必须为COM组件生成元数据。.NET运行环境用元数据层业判断类型信息。在运行时刻 使用类型信息,以便生成RCW(Runtime Callable Wrapper,运行时可调用包装)。当.NET应用程序与COM对象交互时, RCW处理对COM对象的装载和调用。RCW还完成许多其他的工作,如管理对象标识、对象生存周期以及接口缓冲区。 对象生存周期管理十分关键,因为.NET GC把对象到处移动,并且当对象不再使用时,自动处理这些对象。RCW服务告诉 .NET,应用程序正与托管.NET组件交互,同时又使非托管COM组件“觉得”COM对象是被传统的COM客户端调用的。 为了为COM组件生成元数据包装,必须使用tlbimp.exe(TypeLib Importer)工具: tlbimp some_COM.tlb /out:som_COM.dll
|