非託管C/C++ 代碼:struct A{int a;} html
託管代碼:struct A{int a;} class A{int a;}非託管C/C++代碼 | A | A* | A** |
A爲值類型 | A | ref A | IntPtr a |
A爲引用類型 | N/A | A | ref A |
BOOL WINAPI CreateProcess( _In_opt_ LPCTSTR lpApplicationName, _Inout_opt_ LPTSTR lpCommandLine, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment, _In_opt_ LPCTSTR lpCurrentDirectory, _In_ LPSTARTUPINFO lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation );
(opt 可選的輸入參數)c++
Public static extern bool CreateProcess(
[In] string applicationName,
[In,Out] StringBuilder commandName,
[In] ref SECURITY_ATTRIBUTES processAttributes,
[In] ref SECURITY_ATTRIBUTES threadAttributes,
[In] bool inheritHandles,
[In] uint creationFlags,
[In] IntPtr lpEnvironment,
[In] string currentDirectory,
[In] ref STARTUP_INFO startupInfo,
[Out] out PROCESS_INFORMATION processInformation
); api
Dll在第一次調用的時候自動加載,不會自動被釋放,加載不到或者找不到函數就會拋出異常app
Dll不會自動被卸載,建議作法生命一個外部調用類 DLL會伴隨外部調用類一塊兒被清理卸載函數
若是須要手段管理DLL生命週期,只能手動調用LoadLibrary/GetProcAddressui
部分API接收函數指針做爲參數spa
EnumWindows(WNDENUMPROC IpEnumFunc,LPARAM lPararm) 指針
.NET 程序能夠經過P/Invoke調用 EnumWindows API調試
CLR可以將Delegate 轉換爲函數指針,EnumWindows 來回調這個函數指針code
[UnmanagedFunctionPointer(CallingConvention.Winapi)] delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam); EnumWindow(new EnumWindowProc(MyEnumWindow), IntPtr.Zero);
class Program { /// Return Type: BOOL->int ///hwnd: HWND->HWND__* ///lParam: LPARAM->LONG_PTR->int [UnmanagedFunctionPointerAttribute(CallingConvention.Winapi)] public delegate bool WNDENUMPROC(IntPtr hwnd, IntPtr lParam); class NativeMethods { [DllImport("User32.dll",CallingConvention=CallingConvention.Winapi)] public static extern int GetWindowText(IntPtr hwnd, StringBuilder text, int count); /// Return Type: BOOL->int ///lpEnumFunc: WNDENUMPROC ///lParam: LPARAM->LONG_PTR->int [DllImportAttribute("user32.dll", EntryPoint = "EnumWindows")] [return: MarshalAsAttribute(UnmanagedType.Bool)] public static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, int lParam); } private static bool WNDENUMPROC_Callback(IntPtr hwnd, IntPtr lParam) { StringBuilder text = new StringBuilder(255); NativeMethods.GetWindowText(hwnd, text, 255); Console.WriteLine("窗口名:" + text + ",id=" + hwnd.ToInt32() + ",lParam=" + lParam); return true; } static void Main(string[] args) { WNDENUMPROC myWNDENUMPROC = new WNDENUMPROC(WNDENUMPROC_Callback); NativeMethods.EnumWindows(myWNDENUMPROC,22); Console.Read(); } }
找不到DLL通常他會到當前目錄去找 或者系統目錄去找 DLL若是實在沒法差錯可使用全路徑+dll名不推薦最好是放相對路徑
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <Windows.h> /*自定義*/ typedef struct Mytype { int i; char *s; double d; struct Mytype *p; }Mytype; int TestInt(int a,int b) { return a + b; } void TestIntPtr(int *i) { *i = *i * -1; } char * TestCharPtr(char *a,char *b) { return strcat(a, b); } void TestStructPtr(Mytype *p) { p->i++; p->d++; } void TestPtrPtr(int **a,int length) { *a = (int*)malloc(sizeof(int)*length); memset(*a, 0, sizeof(int)* length); } void TestArray(int *a, int length) { for (int i = 0; i < length; i++) { a[i]++; } } void TestCallback(void(*pf)()) { pf(); } int TestCharWidth(char *s) { return strlen(s); }
文件名 Source.cpp
LIBRARY "PInvoke" EXPORTS TestInt TestIntPtr TestCharPtr TestStructPtr TestPtrPtr TestArray TestCallback TestCharWidth
文件名 Source.def
class Program { [StructLayoutAttribute(LayoutKind.Sequential)] public struct Mytype { /// int public int i; /// char* [MarshalAsAttribute(UnmanagedType.LPStr)] public string s; /// double public double d; /// Mytype* public System.IntPtr p; } /// Return Type: void public delegate void Callback(); static void CallbackFunction() { Console.WriteLine("callback invoked"); } /// Return Type: int ///a: int ///b: int [DllImportAttribute("Pinvoke.dll", EntryPoint = "TestInt", CallingConvention = CallingConvention.Cdecl)] public static extern int TestInt(int a, int b); /// Return Type: void ///i: int* [DllImportAttribute("Pinvoke.dll", EntryPoint = "TestIntPtr", CallingConvention = CallingConvention.Cdecl)] public static extern void TestIntPtr(ref int i); /// Return Type: char* ///a: char* ///b: char* [DllImportAttribute("Pinvoke.dll", EntryPoint = "TestCharPtr", CallingConvention = CallingConvention.Cdecl)] public static extern System.IntPtr TestCharPtr(System.IntPtr a, System.IntPtr b); /// Return Type: void ///p: Mytype* [DllImportAttribute("Pinvoke.dll", EntryPoint = "TestStructPtr", CallingConvention = CallingConvention.Cdecl)] public static extern void TestStructPtr(ref Mytype p); /// Return Type: void ///a: int** ///length: int [DllImportAttribute("Pinvoke.dll", EntryPoint = "TestPtrPtr", CallingConvention = CallingConvention.Cdecl)] public static extern void TestPtrPtr(ref System.IntPtr a, int length); /// Return Type: void ///a: int* ///length: int [DllImportAttribute("Pinvoke.dll", EntryPoint = "TestArray", CallingConvention = CallingConvention.Cdecl)] public static extern void TestArray(int[] a, int length); /// Return Type: void ///pf: Anonymous_5afb5371_1680_4be9_99a9_ab5bd7ded029 [DllImportAttribute("Pinvoke.dll", EntryPoint = "TestCallback", CallingConvention = CallingConvention.Cdecl )] public static extern void TestCallback(Callback pf); /// Return Type: int ///s: char* [DllImportAttribute("Pinvoke.dll", EntryPoint = "TestCharWidth", CallingConvention = CallingConvention.Cdecl)] public static extern int TestCharWidth( IntPtr s); static void Main(string[] args) { Console.WriteLine("TestInt:" + TestInt(11, 2)); // TestIntPtr int i = 22; TestIntPtr(ref i); Console.WriteLine("TestIntPtr:" + i); // TestCharPtr IntPtr helloPtr = Marshal.StringToHGlobalAnsi("啊阿斯達斯的阿薩德+"); IntPtr worldPtr = Marshal.StringToHGlobalAnsi("+阿薩德阿薩德"); IntPtr helloWorldPtr = TestCharPtr(helloPtr, worldPtr); string helloWorld = Marshal.PtrToStringAnsi(helloWorldPtr); Console.WriteLine("TestCharPtr:" + helloWorld); //helloPtr = Marshal.StringToHGlobalUni("啊阿斯蒂芬a"); //worldPtr = Marshal.StringToHGlobalUni("阿薩德阿薩德"); //helloWorldPtr = TestCharPtr(helloPtr, worldPtr); //helloWorld = Marshal.PtrToStringUni(helloWorldPtr); //Console.WriteLine("TestCharPtr01:" + helloWorld); // Marshal.FreeCoTaskMem() Marshal.FreeHGlobal(helloPtr); Marshal.FreeHGlobal(worldPtr); // Marshal.FreeHGlobal(helloWorldPtr); // 由於helloWorldPtr和helloPtr指向的是同一地址,因此再次釋放會報錯 // TestCharWidth string a = "a的"; IntPtr aPtr = Marshal.StringToHGlobalAnsi(a); // Ansi int len = TestCharWidth(aPtr); Console.WriteLine("TestCharWidth:" + len); a = Marshal.PtrToStringAnsi(aPtr); Marshal.FreeHGlobal(aPtr); aPtr = Marshal.StringToHGlobalUni(a); // Unicode len = TestCharWidth(aPtr); // 值是1,strlen沒有正確處理unicode,因此不要使用strlen測量unicode字符串的長度 Console.WriteLine("TestCharWidth:" + len); a = Marshal.PtrToStringUni(aPtr); Marshal.FreeHGlobal(aPtr); // TestStructPtr Mytype myType = new Mytype { i = 0, d = 1.1, s = a, p = IntPtr.Zero }; TestStructPtr(ref myType); Console.WriteLine("Mytype->i:" + myType.i); Console.WriteLine("Mytype->d:" + myType.d); // TestArray int[] array = new int[] { 1, 2, 3 }; TestArray(array, array.Length); for (int z = 0; z < array.Length; z++) { Console.WriteLine("array[{0}]" + array[z], z); } // TestCallback TestCallback(CallbackFunction); Console.Read(); } }