csharp互操作

Platform Invoke(P/Invoke),即平台调用,主要用于调用C库函数和Windows API using System; // 使用平台调用技术进行互操作性之前,首先需要添加这个命名空间 using System.Runtime.InteropServices; namespace 平台调用Demo { class Program { // 在托管代码中对非托管函数进行声明,并且附加平台调用所需要属性 // 在默认情况下,CharSet为CharSet.Ansi // 指定调用哪个版本的方法有两种——通过DllImport属性的CharSet字段和通过EntryPoint字段指定 // 在托管函数中声明注意一定要加上 static 和extern 这两个关键字 [DllImport("user32.dll")] public static extern int MessageBox1(IntPtr hWnd, String text, String caption, uint type); // 在默认情况下,CharSet为CharSet.Ansi [DllImport("user32.dll")] public static extern int MessageBoxA(IntPtr hWnd, String text, String caption, uint type); // 在默认情况下,CharSet为CharSet.Ansi [DllImport("user32.dll")] public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type); // 第一种指定方式,通过CharSet字段指定 [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern int MessageBox2(IntPtr hWnd, String text, String caption, uint type); // 通过EntryPoint字段指定 [DllImport("user32.dll", EntryPoint="MessageBoxA")] public static extern int MessageBox3(IntPtr hWnd, String text, String caption, uint type); [DllImport("user32.dll", EntryPoint = "MessageBoxW")] public static extern int MessageBox4(IntPtr hWnd, String text, String caption, uint type); static void Main(string[] args) { // 在托管代码中直接调用声明的托管函数 // 使用CharSet字段指定的方式,要求在托管代码中声明的函数名必须与非托管函数名一样 // 否则就会出现找不到入口点的运行时错误 //MessageBox1(new IntPtr(0), "Learning Hard", "欢迎", 0); // 下面的调用都可以运行正确 //MessageBoxA(new IntPtr(0), "Learning Hard", "欢迎", 0); //MessageBox(new IntPtr(0), "Learning Hard", "欢迎", 0); // 使用指定函数入口点的方式调用 //MessageBox3(new IntPtr(0), "Learning Hard", "欢迎", 0); // 调用Unicode版本的会出现乱码 MessageBox4(new IntPtr(0), "Learning Hard", "欢迎", 0); } } } C++ Introp, 主要用于Managed C++(托管C++)中调用C++类库 第二部分主要向大家介绍了第一种互操作性技术,然后我们也可以使用C++ Interop技术来实现与非托管代码进行交互。 然而C++ Interop 方式有一个与平台调用不一样的地方,就是C++ Interop 允许托管代码和非托管代码存在于一个程序集中,甚至同一个文件中。 C++ Interop 是在源代码上直接链接和编译非托管代码来实现与非托管代码进行互操作的,而平台调用是加载编译后生成的非托管DLL并查找函数的入口地址来实现与非托管函数进行互操作的。 C++ Interop使用托管C++来包装非托管C++代码,然后编译生成程序集,然后再托管代码中引用该程序集,从而来实现与非托管代码的互操作。 ...

2025年7月22日 · 2 分钟 · 261 字

不能在控制元件上呼叫Invoke

在Window窗體程式開發的時候,如果使用多執行緒程式設計,在子執行緒中訪問主執行緒窗體內的控制元件,就需要使用控制元件的Control.Invoke方法或者BeginInvoke方法。但是有時候因為Window執行速度太快,尤其是你寫程式碼的時候在InitializeComponent();完成之前起了一個執行緒去執行某些操作,涉及到窗體控制元件的,當你在呼叫Control.Invoke的時候,就可能出現 “在建立視窗控制代碼之前,不能在控制元件上呼叫 Invoke 或 BeginInvoke 解決的辦法就是讓執行緒等待,直到視窗控制代碼建立完畢: while (!this.IsHandleCreated) { ; } this.BeginInvoke(new ProListIndexChangedDelegate(GetProLyric)); //根據不同情況也可以: if (this.IsHandleCreated) BeginInvoke(new ProListIndexChangedDelegate(GetProLyric)); 有一個更巧妙的方法,只要在BeginInvoke方法的呼叫語句前再加一句:IntPtr i = this.Handle;就OK了,這比死迴圈配合this.IsHandleCreated的判斷方法更簡潔,因為this.Handle這個屬性本身就對應一個方法,取不到控制代碼,程式就不會向下進行。

2025年7月22日 · 1 分钟 · 22 字