|
-
March 28th, 2012, 11:30 AM
#16
Re: Learn C++ from C
 Originally Posted by RipRage
Hi Experts;
I also forgot to mention, what is the best way to use the C++ STL with the windows API. Since the API is built using C, i would like to know if it possible to pass std::wstring and std::vectors etc to parameters that take for example PTSTR, LPWTSR etc for some of the common functions contained within the API,
Or since this is C++, shall i stop using the API and start learning MFC ?
Thanks in advance?
MFC won't completely shield you from the API, but it does make writing Windows programs much, much easier.
I don't know your motivation for learning C++, but if I were starting out now and wanting to write Windows apps, I'd be learning C# and .Net rather than C++ and MFC.
-
March 28th, 2012, 03:14 PM
#17
Re: Learn C++ from C
I also forgot to mention, what is the best way to use the C++ STL with the windows API. Since the API is built using C, i would like to know if it possible to pass std::wstring and std::vectors etc to parameters that take for example PTSTR, LPWTSR etc for some of the common functions contained within the API,
The STL is not compatible with the Win API. At least not the way you are indicating that you want to use it.
If your primary motivation is to write Windows apps, I agree with GCDE, concentrating on C# would be the preferred route.
If you are concentrating on Systems or embedded development, I'd stick with C++.
"Effective teaching is the essence of leadership..."
"There is no substitute for a carefully thought-out design."
If you have found this post to be useful, please Rate it.
-
March 28th, 2012, 03:26 PM
#18
Re: Learn C++ from C
 Originally Posted by mlgoff
The STL is not compatible with the Win API. At least not the way you are indicating that you want to use it.
I wouldn't go quite that far. Certainly some care is needed, but the two can be used together.
Let's say a WinAPI function has a LPCWSTR parameter. This is Microsoft-ese for "Long pointer to const wide character string," AKA const wchar_t*.
The std::wstring class has a c_str() method which returns exactly this type. So, no problem there.
If it were a LPWSTR instead, (wchar_t*, no const) then the c_str() method would not be appropriate. However, there are still two appropriate options.
For any vector<T> v which is non-empty, &v[0] is a T* which represents the vector as an array. (Trying to access v[0] can cause a crash if v is empty.) Therefore, we can simply copy the std::wstring into a std::vector<wchar_t> and then pass it to the WinAPI function as such.
In C++11, the string class is guaranteed to be contiguous, so one could do the same thing with the wstring s directly (pass &s[0]) without bothering with the vector.
-
March 28th, 2012, 04:26 PM
#19
Re: Learn C++ from C
Hi Lindley
 Originally Posted by Lindley
The std::wstring class has a c_str() method which returns exactly this type. So, no problem there.
If it were a LPWSTR instead, (wchar_t*, no const) then the c_str() method would not be appropriate. However, there are still two appropriate options.
For any vector<T> v which is non-empty, &v[0] is a T* which represents the vector as an array. (Trying to access v[0] can cause a crash if v is empty.) Therefore, we can simply copy the std::wstring into a std::vector<wchar_t> and then pass it to the WinAPI function as such.
Thank you! this was the answer i was hoping for.
One last thing, the methods you mention above work for input parameters to a function, but what can you use for output ? i.e a function argument of pStringBuf [out] StringBufSize [in]
My knowledge of C would make me do something like this:
Code:
WCHAR IpStr[INET6_ADDRSTRLEN];
if (!::InetNtopW(AF_INET6, SockAddr, IpStr, INET6_ADDRSTRLEN))
return NULL;
Would i continue like this and then assign std::wstring to the buffer, or is it possible to use std::vector as an output buffer to a function like above ?
Thanks in advance :-)
-
March 28th, 2012, 04:35 PM
#20
Re: Learn C++ from C
So long as you use the resize() method (not reserve) to allocate the desired amount of space beforehand, you can certainly use a vector as an output buffer in this way. The only time you cannot is if the buffer is returned to you as a pointer rather than passed in as a parameter.
In general, however, if you need a buffer of a size known at compile time, then a standard array is a more efficient choice than a vector. (Under C++11, you can use a std::array<T> if you prefer.)
When you are working in C++ rather than C, there is a notion of an "output iterator" which is an even more flexible way of doing things.
-
March 28th, 2012, 05:33 PM
#21
Re: Learn C++ from C
Thank you for your helpful comments Lindley, very much appreciated!
I will certainly have a play with this, it may seem silly to use C++ with the Windows API, but because i know the API quite well from programming in C, i thought i would use it in trying to gather a better understanding of C++. Now i just need to drop my C habits ;-)
Thanks again!
-
March 29th, 2012, 08:54 AM
#22
Re: Learn C++ from C
Hi Lindley,
Would it be possible for you to please confirm / correct me on this small code snippet below? I just want to be reassured i have taken in what you have stated in the comments above and have it right ;-)
This seems to work correctly:
Code:
int wmain ()
{
/* Store IP address as an std::array<T> */
std::array<wchar_t, INET_ADDRSTRLEN> IpBuf;
/* IP string to convert to binary form */
std::wstring IpStr = L"192.168.2.1";
SOCKADDR SockAddr;
/* Convert to binary form */
if (!::InetPton(AF_INET, &IpStr[0], &SockAddr))
return NULL;
/* Convert to readable string form */
if (!::InetNtopW(AF_INET, &SockAddr, &IpBuf[0], INET_ADDRSTRLEN))
return NULL;
std::wcout << IpBuf.data() << std::endl;
return 0;
}
Looking forward to your reply.
Regards
Dan.
-
March 29th, 2012, 10:13 AM
#23
Re: Learn C++ from C
I think that should be okay, with the caveat that in this day and age, you should strongly consider coding for IPv6 rather than IPv4.
I will certainly have a play with this, it may seem silly to use C++ with the Windows API, but because i know the API quite well from programming in C, i thought i would use it in trying to gather a better understanding of C++. Now i just need to drop my C habits ;-)
In my opinion, the biggest advantage of C++ over C is the simplification of memory management. Use of C-style APIs vs C++ APIs is a marginal difference by comparison, so I have no issue with you using C++ containers with WinAPI if that's what you like.
Last edited by Lindley; March 29th, 2012 at 10:20 AM.
-
March 29th, 2012, 10:29 AM
#24
Re: Learn C++ from C
 Originally Posted by RipRage
This seems to work correctly:
You should be calling WSAGetLastError() if there is an error in those socket functions.
Regards,
Paul McKenzie
-
March 29th, 2012, 11:54 AM
#25
Re: Learn C++ from C
 Originally Posted by Lindley
I think that should be okay
That is good! at least i can start to apply C++ to the things i already know. i have been making wrappers for some of the Windows API functions and using them in classes to try and get the hang of the whole OOP approach and seem to being going OK.
 Originally Posted by Lindley
you should strongly consider coding for IPv6 rather than IPv4
Yes i agree, that was just some untested code i typed in to the forum.
 Originally Posted by Paul McKenzie
You should be calling WSAGetLastError() if there is an error in those socket functions.
Thanks Paul, again just some basic code to test out the std::array and std::wstring
-
March 29th, 2012, 01:01 PM
#26
Re: Learn C++ from C
One suggestion. When calling InetPton, the second parameter is const, so I would suggest passing IpStr.c_str() instead of &IpStr[0]. There are two reasons for this.
First, as I mentioned before, while the &v[0] trick will work fine with non-empty vectors, its applicability to strings is theoretically limited to C++11 which not all compilers in wide use support. In practice, I don't think there are many std::string implementations out there which don't store the string contiguously, but prior to C++11 this was a possibility, so it's best not to rely on it if you want to be compatible with C++03.
Second, the function is probably expecting a NULL-terminated string, and there is no guarantee that std::string will use null-termination internally unless you explicitly request the C-style presentation of it with c_str().
-
March 29th, 2012, 05:34 PM
#27
Re: Learn C++ from C
Ok, Thanks Lindley, you have taught me a lot!
One last question in regards to constructors and destructors, its it good practice to include initialization functions such as WSAStartup() or under COM CoInitializeEx() in the constructor ?
My main concern is that there may be a possibility either one of those functions could possible fail. Calling there associate cleanup functions WSACleanup() or COM's CoUninitialize() in the destructor seems OK, although again, they could possible fail.
Regards,
-
March 29th, 2012, 05:46 PM
#28
Re: Learn C++ from C
 Originally Posted by RipRage
Ok, Thanks Lindley, you have taught me a lot!
One last question in regards to constructors and destructors, its it good practice to include initialization functions such as WSAStartup() or under COM CoInitializeEx() in the constructor ?
My main concern is that there may be a possibility either one of those functions could possible fail. Calling there associate cleanup functions WSACleanup() or COM's CoUninitialize() in the destructor seems OK, although again, they could possible fail.
Regards,
Is it ever appropriate to call WSAStartup() more than once? If not, you would need to control the creation of the type which calls it on construction, perhaps using the singleton or factory pattern.
If you ever have a case where construction of an object can fail, there are two primary ways to handle it. The first is to set a field in the object to indicate it is invalid. Make this query-able and check it in every method so that you can fail gracefully or print an error message if someone attempts to use an invalid object. For instance, std::ifstream does this if you attempt to construct it with an invalid filename.
The second is in some ways simpler: throw an exception. That way, no invalid object can be created in the first place. This will close your program unless you handle it, of course.
Don't ever throw an exception in a destructor, however.
-
March 29th, 2012, 11:13 PM
#29
Re: Learn C++ from C
 Originally Posted by RipRage
Calling there associate cleanup functions WSACleanup() or COM's CoUninitialize() in the destructor seems OK,
No, it is not OK to call these in the destructor, unless your destructor catches the exceptions these functions may throw.
As Lindley pointed out, you never let an exception thrown in a destructor exit the destructor. You have to catch any and all of these exceptions within the destructor. This includes your code, or any other function and/or library function that may throw an exception.
So basically, you want to strive to make sure that your destructor is a "nothrow" function. If you had to call one of these throwable functions in the destructor, the one proper to code the destructor would be this:
Code:
~SomeClass::SomeClass()
{
try
{
// any function that can throw goes here
}
catch( some exception )
{
// non-throwing calls must go here
}
catch (some other exception)
{
// non-throwing calls must go here
}
//...etc... additional catch() blocks for all other exceptions you know about
}
Regards,
Paul McKenzie
-
March 30th, 2012, 02:25 PM
#30
Re: Learn C++ from C
Hi Paul,
Thank you for your post. If its not to much trouble could you show me a working example ? the reason why i ask is because i am making a function fail deliberately like WSACleanup() in the destructor but i am unable to catch the exception...
Regards,
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|