This example illustrates how the charset ‘argument’ to [sysimport] can be used to provide explicitly ask for ANSI or Unicode versions of a particular unmanaged function – in this case, the GetSystemDirectory in the Win32 API. The different versions of GetSystemDirectory pass back in the parameter a string in different forms, ANSI or Unicode; however, Platform Invocation Services transforms this into an NGWS runtime string, based on the usage of “ansi”, “unicode” or “auto” on charset.
#import <mscorlib.dll> typedef unsigned __int32 UINT; [sysimport(dll="kernel32", charset="ansi")] extern "C" UINT GetSystemDirectoryA(StringBuilder* lpBuf, UINT uSize); [sysimport(dll="kernel32", charset="unicode")] extern "C" UINT GetSystemDirectoryW(StringBuilder *lpBuf, UINT uSize); [sysimport(dll="kernel32", name="GetSystemDirectory", charset="auto")] UINT MyMethod(StringBuilder *lpBuf, UINT uSize); #if _UNICODE [sysimport(dll="kernel32", charset="unicode")] extern "C" UINT GetSystemDirectory(StringBuilder *lpBuf, UINT uSize); #else [sysimport(dll="kernel32", charset="ansi")] extern "C" UINT GetSystemDirectory(StringBuilder *lpBuf, UINT uSize); #endif #define MAX_STRING_PATH 256 int main(void) { StringBuilder *pSysDir = new StringBuilder(MAX_STRING_PATH); GetSystemDirectoryW(pSysDir, MAX_STRING_PATH); Console::WriteLine(pSysDir); GetSystemDirectoryA(pSysDir, MAX_STRING_PATH); Console::WriteLine(pSysDir); MyMethod(pSysDir, MAX_STRING_PATH); Console::WriteLine(pSysDir); GetSystemDirectory(pSysDir, MAX_STRING_PATH); Console::WriteLine(pSysDir); return 0; }
This program defines four managed methods, called:
Note that we specify each function with extern “C” – this tells VC7 to emit the plain, unmangled name of the method that follows, into the object file. If you miss this out, then VC7 will mangle the name, writing out a string that begins “?GetSystemDirectoryA@@YA_”. So the program will compile and link ok, but at runtime PInvoke will not be able to find that function.