Entry PointfNative FromDLL Exact Spellingtrue

SetLastError=false)] void fNativeFromDLL_NoGLE();

While you'll have to write some extra code, this approach will help you avoid the trouble of getting incorrect Win32 error values for all other imported functions, while still benefiting from a fast inlined thunk without the overhead of GetLastError-caching. Notice that the custom P/Invoke function is called fNativeFromDLL_NoGLE instead of just fNativeFromDLL. This prevents naming conflicts with the native function. The information about the entry point's name is provided via the EntryPoint and the ExactSpelling properties of the DllImportAttribute.

To avoid these naming conflicts, I recommend defining the P/Invoke function in a namespace or managed class, as shown here:

namespace NativeFuncs {

[System::Security::SuppressUnmanagedCodeSecurity] [System::Runtime::InteropServices::DllImport( "kernel32.dll", SetLastError=false)]

void fNativeFromDll(DWORD frequency, DWORD duration);

Writing a custom P/Invoke function in C++/CLI is often much easier than writing an equivalent function in other languages. Since native types can seamlessly be used in C++/CLI, you can simply copy the native function declaration and replace some native declaration aspects with equivalent managed aspects. As an example, have a look at the declaration of Beep inwinbase.h:

WINBASEAPI BOOL WINAPI Beep(

_in DWORD dwFreq,

_in DWORD dwDuration

In this code, the macro WINBASEAPI evaluates to_declspec(dllimport). The managed equivalent of_declspec(dllimport) is the DllImportAttribute. Therefore, you must remove the WINBASEAPI macro and apply the DllImportAttribute instead. The WINAPI macro evaluates to_stdcall. It is used to specify the calling convention of Beep. Instead of using this native calling convention, your P/Invoke function must apply the DllImportAttribute as shown here:

namespace Win32Native {

using namespace System::Runtime::InteropServices;

[System::Security::SuppressUnmanagedCodeSecurity] [DllImport("kernel32.dll", SetLastError=false,

CallingConvention = CallingConvention::StdCall)] void Beep(DWORD frequency, DWORD duration);

The default setting for the CallingConvention property of the DllImportAttribute is CallingConvention::WinApi. This setting is used to specify that the default calling convention of the platform's system APIs should be chosen. For the Win32 API, this is_stdcall. Since

Beep is a function of the system API, it is also possible to keep this default setting instead of specifying CallingConvention = CallingConvention::StdCall.

Was this article helpful?

0 0

Post a comment