extern "C" AFX_EXT_API LPCTSTR WINAPI GetString()
{
LPCTSTR lpcstr ;
CString str = _T("xxx");
lpcstr =str;
return lpcstr ;
}
and i call this function in my program
extern "C" LPCTSTR WINAPI TestString();
void CMainFrame::OnGetString()
{
/......
/.....
LPCTSTR lpc;
lpc = GetString();
}
but i dont get the string i always get the ansi chars, any help thanks in
advance
another thing why i cant use CString in post of LPCTSTR if i use it i got
this warning
warning C4190: '<Unknown>' has C-linkage specified, but returns UDT
'CString' which is incompatible with C
thanks again
> extern "C" AFX_EXT_API LPCTSTR WINAPI GetString()
> {
> LPCTSTR lpcstr ;
> CString str = _T("xxx");
> lpcstr =str;
>
> return lpcstr ;
> }
The above code is wrong.
In fact, CString 'str' instance is built on the stack (it is a local
automatic variable). So, when function GetString() terminates, this variable
'str' (which is local to function body) is *destroyed*.
So, its content (the string) is lost.
What is safe to do is to return a CString instance:
CString GetString()
{
CString str = ...
....
return str;
}
> another thing why i cant use CString in post of LPCTSTR if i use it i got
> this warning
> warning C4190: '<Unknown>' has C-linkage specified, but returns UDT
> 'CString' which is incompatible with C
The warning is clear: you say that your function as a C interface, but you
are using a C++ class (CString) in that interface, and so you are
introducing a C++ element (CString class) into a pure C interface, and that
is not possible.
If you really want a C interface, you should consider passing the buffer
from the caller (i.e. the caller allocates a string buffer, and the called
function fills it):
<code>
extern "C" AFX_EXT_API void WINAPI GetString( TCHAR * destBuffer, size_t
destSizeInBytes )
{
// Check destination buffer
ASSERT( destBuffer != NULL );
ASSERT( destSizeInBytes != 0 );
CString str;
....
work with your str instance ...
...
//
// Return string to the caller,
// copying the string into caller's buffer.
//
// Use a safe string function to avoid buffer overruns.
//
StringCbCopy(
destBuffer, // destination buffer
destSizeInBytes, // its size in bytes
str // source string
);
}
</code>
You can use the above code like this:
// Get string into local buffer
TCHAR theString[ 300 ];
GetString( theString, sizeof(theString) );
HTH,
Giovanni
I would recomand against expressing size in bytes.
Most Windows APIs taking strig length string count string elements.
The "safe string APIs" (with StringCbCopy) are unfortunate exceptions
to the rule (and even there, I am not sure the doc is not wrong).
It is confusing to use two conventions, and strsafe.h makes things
worse by undefining stuff like _sntprintf (which takes an element count).
So when you do
TCHAR buff[10];
_sntprintf( buff, 10, _T("%d"), value );
and you switch to strsafe.h, _sntprintf gets undefined and the error is:
_sntprintf_instead_use_StringCbPrintf_or_StringCchPrintf
Which takes the size in bytes.
(and I don't program like that, that was just an example,
I use _sntprintf( buff, _countof(buff), ... :-)
--
Mihai Nita [Microsoft MVP, Visual C++]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email
I imagined that someone would point out that ;-)
Initially, I tended to use the StringCchXxx versions (in those rare cases
when a CString was not possible to use, like having C interface DLLs with a
C++ implementation - it's fine to use CString inside thte DLL, but at the
interface you must pass data to a string buffer like in case of the OP).
However, I decided to use StringCbXxx versions after reading that post on
Larry Osterman's blog:
<cite>
If you use the Cb version of the safe String functions then you're safe
regardless of the type of temp.
</cite>
Of course, _countof() is fine, too...
> TCHAR buff[10];
> _sntprintf( buff, 10, _T("%d"), value );
...
> (and I don't program like that, that was just an example,
> I use _sntprintf( buff, _countof(buff), ... :-)
Of course :-)
However, I don't lke _sntprintf(), becuase of that:
http://msdn.microsoft.com/en-us/library/2ts7cx93(VS.71).aspx
<cite>
This function does not guarantee NULL termination,
so ensure it is followed by sz[ ARRAYSIZE(sz) - 1] = 0.
</cite>
Instead, with StringXxx NUL termination is guaranteed.
Giovanni
>hi,
>i have a extension dll with this functuon
>
>extern "C" AFX_EXT_API LPCTSTR WINAPI GetString()
>{
> LPCTSTR lpcstr ;
> CString str = _T("xxx");
> lpcstr =str;
>
> return lpcstr ;
>}
That function returns a pointer to memory that is freed when the function
returns. IOW, it returns a dangling pointer, which is a fatal flaw.
>and i call this function in my program
>extern "C" LPCTSTR WINAPI TestString();
>
>void CMainFrame::OnGetString()
>{
>/......
>/.....
> LPCTSTR lpc;
> lpc = GetString();
>}
>but i dont get the string i always get the ansi chars, any help thanks in
>advance
>
>another thing why i cant use CString in post of LPCTSTR if i use it i got
>this warning
>warning C4190: '<Unknown>' has C-linkage specified, but returns UDT
>'CString' which is incompatible with C
To return CString, get rid of the extern "C". Why do you think you need to
use it? Your CMainFrame::OnGetString certainly doesn't need it. Note that
to share C++ objects between modules like this, the modules should all link
to the same CRT DLL. This is true for extension DLLs and their clients
anyway.
Also get rid of AFX_EXT_API and replace it with something like:
#if COMPILING_X_DLL
#define X_EXPORT __declspec(dllexport)
#else
#define X_EXPORT __declspec(dllimport)
#endif
Then replace "X" with a suitably unique identifier, which may be as simple
as the name of your DLL, and add COMPILING_X_DLL to your preprocessor
macros /D section. If you look in your extension DLL's preprocessor
options, you will probably find a "COMPILING_X_DLL" macro already defined
for you. You need to do this so that one extension DLL can use another; if
they all use AFX_EXT_API, there's no way it can work.
--
Doug Harrison
Visual C++ MVP
>
>"Mihai N." <nmihai_y...@yahoo.com> ha scritto nel messaggio
>news:Xns9AC91419...@207.46.248.16...
>>> GetString( TCHAR * destBuffer, size_t destSizeInBytes )
>>
>> I would recomand against expressing size in bytes.
>> Most Windows APIs taking strig length string count string elements.
>> The "safe string APIs" (with StringCbCopy) are unfortunate exceptions
>> to the rule (and even there, I am not sure the doc is not wrong).
>
>I imagined that someone would point out that ;-)
>
>Initially, I tended to use the StringCchXxx versions (in those rare cases
>when a CString was not possible to use, like having C interface DLLs with a
>C++ implementation - it's fine to use CString inside thte DLL, but at the
>interface you must pass data to a string buffer like in case of the OP).
>
>However, I decided to use StringCbXxx versions after reading that post on
>Larry Osterman's blog:
>
>http://blogs.msdn.com/larryosterman/archive/2007/03/09/what-s-wrong-with-this-code-sample-the-answer.aspx
>
><cite>
>
>If you use the Cb version of the safe String functions then you're safe
>regardless of the type of temp.
>
></cite>
I wouldn't use either one because there is nothing to force you to check
the return value. At least the "safe string" functions in the CRT invoke a
default error handler when they fail, which makes it harder to ignore
failures. That said, the primary value of all these functions is they
require the user to pay lip service to size constraints, but IME, people
who can't write correct code with functions like strcpy just make different
mistakes with the "safe string" functions, like passing sizeof(p) as a
count, where p is a pointer. When MS made the big push to these functions
years ago, I reported several such bugs in the updated MSDN.
Even more misguided was what MS did to lstrcpy and friends back in the
Win95 or NT4 days. Those functions originally would crash the system on
NULL pointers and such, but MS added SEH handlers so they would return NULL
instead, because they didn't think failures in functions like this should
crash the system, as I recall from an MSJ article contemporaneously written
by one of the standard luminaries. The problem was, *NOBODY* checked return
values for functions like lstrcpy, so they turned a formerly crashing bug
into a silent bug. The Windows "safe string" functions can do much the same
thing, because they don't force the user to check return values, and I
would expect lots of people don't check return values and write recovery
code because it's so clumsy to do.
So sprintf, snprintf, snprintf_s.
How many tries does someone needs for such a simple API?
Back to the problem at hand, if one prefers StringXxx to _sntprintf_s
the new API can nicely hide that:
void GetString( TCHAR * destBuffer, size_t destSizeInTChars )
{
...
StringCbCopy(
destBuffer, // destination buffer
destSizeInTChars * sizeof(TCHAR), // its size in bytes
str // source string
);
...
It's even easier to use StringCchCopy:
void GetString( TCHAR * destBuffer, size_t destSizeInTChars )
{
...
StringCchCopy(
destBuffer, // destination buffer
destSizeInTChars, // its size in chars
str // source string
);
...
}
To me, I prefer the StringXxx functions because it allows me the freedom to
specify size in either bytes or characters, whichever is more convenient.
-- David
> And now you also have _sntprintf_s, which is also supposed to be safe.
>
> So sprintf, snprintf, snprintf_s.
> How many tries does someone needs for such a simple API?
:-)
Giovanni
Instead they get rid of the things I use like atlrx.h :o)
Tom
"Giovanni Dicanio" <giovanni...@invalid.com> wrote in message
news:OJTDvB21...@TK2MSFTNGP05.phx.gbl...
> Instead they get rid of the things I use like atlrx.h :o)
:-))
ATL Server Library was made shared-source (a kind of open-source license) by
Microsoft, and now lives on CodePlex.
There was a post announcing that on VC++ Team Blog, you may search the web
about that.
G
Tom
"Giovanni Dicanio" <giovanni...@invalid.com> wrote in message
news:%23PZLMi5...@TK2MSFTNGP06.phx.gbl...
> Yeah, I know. Easy enough to find, but it broke several of my programs a
> while back before I figured it out.
I agree with you.
I did not like that decision of removing stuff from VS.
(Or, at least, there should be a clear error message, like "Can't fine
header file Xxx.h; please download it from web site Yyy.com".)
G
Tom
"Giovanni Dicanio" <giovanni...@invalid.com> wrote in message
news:%23NYKe25...@TK2MSFTNGP06.phx.gbl...