{"id":490,"date":"2010-12-23T15:56:34","date_gmt":"2010-12-23T15:56:34","guid":{"rendered":"https:\/\/ibex.tech\/visualcpp\/?p=490"},"modified":"2022-02-17T06:24:04","modified_gmt":"2022-02-17T06:24:04","slug":"pinvoke-platform-invoke","status":"publish","type":"post","link":"https:\/\/ibex.tech\/visualcpp\/unmanaged-code\/pinvoke-platform-invoke","title":{"rendered":"P\/Invoke (Platform Invoke)"},"content":{"rendered":"<pre><code>\r\nSystem::Runtime::InteropServices\r\n<\/code><\/pre>\n<p><em>Chapter 22\/23 of the &#8216;Pro Visual C++\/CLI and the .NET 3.5 Platform&#8217; book is an excellent resource for understanding P\/Invoke (and an excellent VC++ book generally).<\/em><\/p>\n<p>Used when making calls out of the .NET managed environment to unmanaged .DLLs.  P\/Invoke finds the DLL, loads it into memory, marshals its arguments (converts from managed to native) so the DLL can understand the call, makes the call to the DLL function and than marshals the return value (converting from native to managed).<\/p>\n<h4>Good Resources<\/h4>\n<p><a href=\"http:\/\/pinvoke.net\/\" target=\"_blank\" rel=\"noopener\">http:\/\/pinvoke.net\/<\/a><\/p>\n<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa719104%28VS.71%29.aspx\" target=\"_blank\" rel=\"noopener\">http:\/\/msdn.microsoft.com\/en-us\/library\/aa719104%28VS.71%29.aspx<\/a><\/p>\n<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/eyzhw3s8.aspx\" target=\"_blank\" rel=\"noopener\">http:\/\/msdn.microsoft.com\/en-us\/library\/eyzhw3s8.aspx<\/a><\/p>\n<h4>DllImport<\/h4>\n<p>(Same as DllImportAttribute)<br \/>\nDllImport provides a simple way to make calls to native code from a managed application.  Copy the .dll file into your project exe directory.<\/p>\n<pre><code>\r\n\tDllImport(L\"MyDllName.dll\")]\r\n\t\/\/Create the function prototype here\r\n<\/code><\/pre>\n<h4>Reference Values<\/h4>\n<p>Some functions might take arguments that return a value.  Just use the &#8216;%&#8217; as you normally would, but make sure you are not passing a handle (e.g. int %value is fine, but String ^%text is not).<\/p>\n<p>Keywords such as &#8216;out&#8217; don&#8217;t work for managed C &#8211; the % character is how you tell the compiler a value is coming returned.<\/p>\n<p>When porting VB code look for ByRef.  Usually values are passed as ByVal, but if ByRef is used then it means this is a returned variable.<\/p>\n<h4>Data Marshalling<\/h4>\n<p>Usually when using P\/Invoke you don&#8217;t have to worry about marshalling as in most cases the managed and unmanaged formats of data types are the same.  However there is nothing stopping you specifically defining how parameters are to be marshalled using MarshalAsAttribute in the function prototype you create for the DLL import.<\/p>\n<h5>Variables<\/h5>\n<p>bool &#8211; Bool (Win32 BOOL type)<\/p>\n<p>char &#8211; Char (1 byte signed integer)<\/p>\n<p>short &#8211; Int16 (2 byte signed integer)<\/p>\n<p>long &#8211; Int32 (4 byte signed integer)<\/p>\n<p>__int64 &#8211; Int64 (8 byte signed integer)<\/p>\n<p>unsigned char &#8211; Byte (1 byte unsigned integer)<\/p>\n<p>unsigned short &#8211; UInt16 (2 byte unsigned integer)<\/p>\n<p>unsigned int or\u00a0unsigned long &#8211; UInt32 (4 byte unsigned integer)<\/p>\n<p>unsigned __int64 &#8211; UInt64 (8 byte unsigned integer)<\/p>\n<h5>Strings<\/h5>\n<p>If you use String^ when defining the function prototype then this correctly maps to null terminated wchar_t arrays &#8211; i.e. you can use String^.  However as an example here&#8217;s how you would do it if you used System::String in the function prototype, effectively doing the data marshalling yourself:<\/p>\n<pre><code>\r\n\tString ^MyString = L\"Hello\";\r\n\tpin_ptrmy_string = &amp;(MyString-&gt;ToCharArray()[0]);\r\n\tSomeDllFunction(my_string);\r\n<\/code><\/pre>\n<h4>Some Examples<\/h4>\n<h5>Forcing our application form to the foreground<\/h5>\n<p>Outside of function \/ in header file:<\/p>\n<pre><code>\r\n\t[System::Runtime::InteropServices::DllImport(L\"user32.dll\")]\r\n\tstatic System::IntPtr SetForegroundWindow(System::IntPtr  hWnd);\r\n<\/code><\/pre>\n<p>In function:<\/p>\n<pre><code>\r\n\tSetForegroundWindow(this-&gt;Handle);\t\t\/\/Can test return bool value if we want\r\n<\/code><\/pre>\n<h5>Misc<\/h5>\n<pre><code>\r\n\t[System::Runtime::InteropServices::DllImport(L\"ivbind.dll\")]\r\n\t\/\/int IvBindRegisterEvents (const char *pszIpAddress);\r\n\tstatic System::Int32 IvBindRegisterEvents (String ^pszIpAddress); \r\n\r\n\t[System::Runtime::InteropServices::DllImport(L\"ivbind.dll\")]\r\n\t\/\/int IvBindSendEvent (const char *pszIpAddress, int nPort, const FILETIME *pTime, int nEventNum, const char *pData, int nSize);\r\n\tstatic System::Int32 IvBindSendEvent (String ^pszIpAddress, System::Int32 nPort, System::DateTime ^pTime,\r\n\t\tSystem::Int32 nEventNum, String ^pData, System::Int32 nSize);\r\n<\/code><\/pre>\n<h5>MSDN C++ Examples<\/h5>\n<pre><code>\r\npublic:\r\n\t[DllImport(S\"KERNEL32.DLL\", EntryPoint=S\"MoveFileW\",  SetLastError=true,\r\n\tCharSet=CharSet::Unicode, ExactSpelling=true,\r\n\tCallingConvention=CallingConvention::StdCall)]\r\n\tstatic bool MoveFile(String* src, String* dst);\r\n\r\n\t[DllImport(L\"winspool.Drv\", EntryPoint=\"StartDocPrinterW\", SetLastError=true, CharSet=CharSet::Unicode, ExactSpelling=true, CallingConvention=CallingConvention::StdCall)]\r\n\tSystem::Boolean StartDocPrinter(\r\n\t\t\t\t\tSystem::IntPtr hPrinter,\r\n\t\t\t\t\tint level,\r\n\t\t\t\t\t[MarshalAs(UnmanagedType::LPWStr)] String ^pDocName,\r\n\t\t\t\t\t[MarshalAs(UnmanagedType::LPWStr)] String ^pOutputFile,\r\n\t\t\t\t\t[MarshalAs(UnmanagedType::LPWStr)] String ^pDataType);\r\n\r\n\t[DllImport(L\"winmm.dll\")]\r\n\tstatic System::IntPtr timeSetEvent(\r\n\t\tUInt32\t\t\tuDelay,\r\n\t\tUInt32\t\t\tuResolution,\r\n\t\t[MarshalAs(UnmanagedType::FunctionPtr)] MMTimerProc ^lpTimeProc,\r\n\t\tUInt32\t\t\tdwUser,\r\n\t\tInt32\t\t\t\tfuEvent\r\n\t\t);\r\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>System::Runtime::InteropServices Chapter 22\/23 of the &#8216;Pro Visual C++\/CLI and the .NET 3.5 Platform&#8217; book is an excellent resource for understanding P\/Invoke (and an excellent VC++ book generally). Used when making calls out of the .NET managed environment to unmanaged .DLLs. P\/Invoke finds the DLL, loads it into memory, marshals its arguments (converts from managed to [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[],"class_list":["post-490","post","type-post","status-publish","format-standard","hentry","category-unmanaged-code"],"_links":{"self":[{"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/posts\/490","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/comments?post=490"}],"version-history":[{"count":12,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/posts\/490\/revisions"}],"predecessor-version":[{"id":1623,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/posts\/490\/revisions\/1623"}],"wp:attachment":[{"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/media?parent=490"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/categories?post=490"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/tags?post=490"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}