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:
[DllImport("User32.dll", EntryPoint = "FindWindow")]
extern "C" IntPtr FindWindow(String^ lpszWndClass,
String^ lpszWndName);
The compiler has this to say:
Quoteerror 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'
But that's exactly what MSDN claims you must do! The example MSDN provided is as follows:
using namespace System::Runtime::InteropServices;
[DllImport("user32.dll")]
extern "C" IntPtr MessageBox(int hWnd, String* pText,
String* pCaption unsigned int uType);
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?
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:
[DllImport("user32")]
extern System::IntPtr FindWindow(String^ className, String^ wndName);
Usage:
void main()
{
IntPtr p;
p = FindWindow(nullptr, "Test - Microsoft Visual Studio");
}
Note that p is not declared with handle syntax (^) because it is a stack-type.
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.
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.
Quote from: Dyndrilliac on February 11, 2008, 12:20 PM
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.
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.