Valhalla Legends Forums Archive | .NET Platform | [C++/CLI] MSDN's Erroneous Interop documentation?

AuthorMessageTime
Dyndrilliac
I've been porting some old C++ code to C++/CLI, and with that comes porting vast amounts of the Win32 Platform SDK. I instantly started having issues performing the most basic tasks according to the MSDN documentation. Example:[code][DllImport("User32.dll", EntryPoint = "FindWindow")]
extern "C" IntPtr FindWindow(String^ lpszWndClass,
String^ lpszWndName);[/code]The compiler has this to say:[quote]error C2526: 'FindWindow' : C linkage function cannot return C++ class 'System::IntPtr'
1>        c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll : see declaration of 'System::IntPtr'[/quote]But that's exactly what MSDN claims you must do! The example MSDN provided is as follows:[code]using namespace System::Runtime::InteropServices;
[DllImport("user32.dll")]
    extern "C" IntPtr MessageBox(int hWnd, String* pText,
    String* pCaption unsigned int uType);[/code]I've also found that according to the compiler, '*' is an illegal indirection type for types of System::String. Is the documentation just flat-out wrong and untrustworthy, or am I missing something?
February 11, 2008, 2:04 AM
Myndfyr
First of all, why would you import MessageBox, when the System::Windows::Forms::MessageBox class already does that for you?

Secondly, System.String cannot be accessed via the * (pointer) operator in C++/CLI - it would be accurate I believe in MC++, but C++/CLI syntax (.NET 2.0) uses the ^ operator, for GC handles.  The appropriate decorator is String^.

Anyway, this was what I found to be the appropriate import:
[code]
[DllImport("user32")]
extern System::IntPtr FindWindow(String^ className, String^ wndName);
[/code]
Usage:

[code]
void main()
{
IntPtr p;
p = FindWindow(nullptr, "Test - Microsoft Visual Studio");

}
[/code]

Note that p is not declared with handle syntax (^) because it is a stack-type.
February 11, 2008, 3:50 PM
Dyndrilliac
Well, I wasn't trying to import MessageBox - it is simply what MSDN used for their example. I just don't understand why the documentation at MSDN is so flawed. How is it that they got the C linkage specifier to work, and I couldn't, with the same code? At any rate, thanks for the suggestion. I will try leaving out the "C", as per your example. I may just go back to the system I was using, including windows.h and simply utilizing it in non-managed code. But, I've been trying to avoid all those loader-lock scenarios MSDN talks about, and figured that making my assemblies pure MSIL would do the trick and be even more helpful down the road.
February 11, 2008, 6:20 PM
K
If you're code isn't too low level and you want to make it all managed, I would suggest moving it over to C#.  C++/CLI is loads better than the old Managed C++, but I still wouldn't choose to use it unless you have to.
February 11, 2008, 6:41 PM
Myndfyr
[quote author=Dyndrilliac link=topic=17315.msg176301#msg176301 date=1202754053]
Well, I wasn't trying to import MessageBox - it is simply what MSDN used for their example. I just don't understand why the documentation at MSDN is so flawed. How is it that they got the C linkage specifier to work, and I couldn't, with the same code? At any rate, thanks for the suggestion. I will try leaving out the "C", as per your example. I may just go back to the system I was using, including windows.h and simply utilizing it in non-managed code. But, I've been trying to avoid all those loader-lock scenarios MSDN talks about, and figured that making my assemblies pure MSIL would do the trick and be even more helpful down the road.
[/quote]
I think you might be looking at MC++ documentation as opposed to C++/CLI.  .NET 2.0 (the part with C++/CLI) solved the loader-lock problem, and it explains why you have String* as opposed to String^.

As K said, you should probably stick with C# if you're porting an app to managed code.
February 11, 2008, 8:06 PM

Search