Discussion:
Using TCHAR with pcap and sockets (send/recv/setsockopt)
(too old to reply)
Rayne
2010-02-08 09:21:17 UTC
Permalink
Hi all,

I'm using Visual Studio .NET 2003, and I'm trying to write a program
that can compile in both Unicode and Multi-Byte. Hence, the use of
TCHAR. However, I'm getting errors on pcap functions and socket
functions:

error C2664: 'pcap_findalldevs': cannot convert parameter 2 from
'TCHAR[256]' to 'char *'
error C2664: 'pcap_lookupnet: cannot convert parameter 1 from
'TCHAR[5]' to 'const char *'
error C2664: 'pcap_loop: cannot convert parameter 3 from 'void
(_TUCHAR *, const pcap_pkthdr *, const _TUCHAR *)' to 'pcap_handler'
error C2664: 'pcap_open_live': cannot convert parameter 5 from
'TCHAR[256]' to 'char *'
error C2664: 'pcap_open_offline: cannot convert parameter 1 from
'TCHAR *' to 'const char *'

error C2664: 'recv': cannot convert parameter 2 from 'TCHAR *' to
'char *'
error C2664: 'send': cannot convert parameter 2 from 'TCHAR *' to
'const char *'
error C2664: 'setsockopt': cannot convert parameter 4 from 'const
TCHAR *' to 'const char *'

Please advise.

Thank you.

Regards,
Rayne
David Lowndes
2010-02-08 09:37:33 UTC
Permalink
Post by Rayne
I'm using Visual Studio .NET 2003, and I'm trying to write a program
that can compile in both Unicode and Multi-Byte. Hence, the use of
TCHAR. However, I'm getting errors on pcap functions and socket
error C2664: 'pcap_findalldevs': cannot convert parameter 2 from
'TCHAR[256]' to 'char *'
Presumably because that function doesn't have a Unicode version.
Post by Rayne
Please advise.
You can't blindly convert everything in your application to use TCHAR.
If a function only accepts single byte characters, then that's what
you have to give it. If those then need conversion to TCHAR to match
up with other aspects if your application you'll find the A2T and T2A
family of macros useful.

Dave
Giovanni Dicanio
2010-02-08 11:02:24 UTC
Permalink
Post by David Lowndes
Post by Rayne
I'm using Visual Studio .NET 2003, and I'm trying to write a program
[...]
Post by David Lowndes
If those then need conversion to TCHAR to match
up with other aspects if your application you'll find the A2T and T2A
family of macros useful.
To build on Dave's post, I would suggest the newer CA2T and CT2A from ATL
7+, (instead of the old ATL 3 <X>2<Y> helpers); they have some advantages,
like those explained here:

http://msdn.microsoft.com/en-us/library/87zae4a3(VS.80).aspx

Giovanni
David Lowndes
2010-02-08 11:36:23 UTC
Permalink
Post by Giovanni Dicanio
To build on Dave's post, I would suggest the newer CA2T and CT2A from ATL
7+, (instead of the old ATL 3 <X>2<Y> helpers); they have some advantages,
Indeed, they are the ones to use these days. I only mentioned the
others since typing those into the MSDN index get you straight to the
help that references the new ones.

Dave
Rayne
2010-02-09 02:10:23 UTC
Permalink
Thank you for all the suggestions.

I'm trying to use the A2T macro for my pcap_loop callback function
"got_packet".

So I have

void got_packet(u_char *cuser, const struct pcap_pkthdr *header, const
u_char *cpacket)
{
_TUCHAR *user, *packet;
user = A2T(cuser);
packet = A2T(cpacket);
...
}

But I have the error messages for the 2 A2T conversions:

error C3861: 'A2T': identifier not found, even with argument-dependent
lookup

Putting my cursor over the A2T shows "#define A2T A2W", so I don't get
why I'm getting the error.

Is there some compiler setting or header files I should include?

Thank you.

Regards,
Rayne
Rayne
2010-02-09 02:14:29 UTC
Permalink
Just to add, I've tried CA2T, and I still get the same errors.
Rayne
2010-02-09 03:17:15 UTC
Permalink
I'm really confused by this unicode vs multi-byte thing.

Say I'm compiling my program in Unicode (but ultimately, I want a
solution that is independent of the character set used).

1) Will all 'char' be interpreted as wide characters?

2) If I have a simple printf statement, i.e. printf("Hello World\n");
with no character strings, can I just leave it be without using
_tprintf and _T("...")? If the printf statement includes a character
string, then I should use _tprintf and _T("..."), i.e. _tprintf("Hello
%s\n", name); ?

3) If I have a text file (saved in the default format, i.e. without
changing the default character set used) that I want to read into a
buffer, can I still use char instead of TCHAR? Especially if I'm
reading it character by character, i.e. by incrementing the character
pointer?

Thank you.
Ulrich Eckhardt
2010-02-09 08:27:25 UTC
Permalink
Post by Rayne
I'm really confused by this unicode vs multi-byte thing.
Say I'm compiling my program in Unicode (but ultimately, I want a
solution that is independent of the character set used).
1) Will all 'char' be interpreted as wide characters?
No. The datatypes '[[un]signed] char' and 'wchar_t' never change their
actual type. What does change is what 'TCHAR' etc resolves to and
accordingly all APIs using it.
Post by Rayne
2) If I have a simple printf statement, i.e. printf("Hello World\n");
with no character strings, can I just leave it be without using
_tprintf and _T("...")?
Yes.
Post by Rayne
If the printf statement includes a character string, then I should use
_tprintf and _T("..."), i.e. _tprintf("Hello %s\n", name); ?
No, not necessarily. Take a look at '%hs' and '%ls' placeholders. Note that
printf() has limited functionality, using wprintf() would be a more
versatile alternative. However, then you can also drop the whole
TCHAR-thing completely, which IMHO is not just an alternative but should be
the goal, unless you have to support win9x.
Post by Rayne
3) If I have a text file (saved in the default format, i.e. without
changing the default character set used) that I want to read into a
buffer, can I still use char instead of TCHAR?
Yes. However: You could read the bytes in a text file, but without knowing
the encoding you can not interpret it. The 'default character set' you
mention is not universally fixed, but depends on the OS setup.

Actually, using TCHAR for files is a Damn Bad Idea(tm). The problem, just
like with network protocols, is that you don't know the actual encoding. It
might be the configured multibyte encoding or it could end up as
little-endian UTF-16, depending on the program it was written with. Without
knowing the encoding, you can not reliably parse such a file. You as a
programmer should decide the encoding as part of your design. Even if you
just say ASCII (which excludes any chars >= 127) that is fine, too. If you
need further Unicode features, I'd suggest you switch to UTF-8, which is
the the most common variant.

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Ulrich Eckhardt
2010-02-09 08:52:43 UTC
Permalink
Post by Rayne
2) If I have a simple printf statement, i.e. printf("Hello World\n");
with no character strings, can I just leave it be without using
_tprintf and _T("...")? If the printf statement includes a character
string, then I should use _tprintf and _T("..."), i.e. _tprintf("Hello
%s\n", name); ?
I forgot one thing in my post: Do not mix printf() and wprintf(). Since
_tprintf() resolves to wprintf() or printf() depending on whether _UNICODE
is #defined, that in effect means that you also shouldn't mix any of the
three with the others.

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Giovanni Dicanio
2010-02-09 09:04:28 UTC
Permalink
Post by Rayne
I'm really confused by this unicode vs multi-byte thing.
You are right. It can be kind of confusing when you start.


As a side note, I would like to suggest you a couple of links on
CodeProject:

"The Complete Guide to C++ Strings, Part I - Win32 Character Encodings"
http://www.codeproject.com/KB/string/cppstringguide1.aspx

"StdioFile-derived class for multibyte and Unicode reading and writing"
http://www.codeproject.com/KB/files/stdiofileex.aspx


Giovanni
Rayne
2010-02-09 03:39:01 UTC
Permalink
Post by Rayne
Just to add, I've tried CA2T, and I still get the same errors.
After including <atlbase.h> and USES_CONVERSION, I get the following
errors for the 2 lines
user = CA2T(cuser);
packet = CA2CT(cpacket);

error C2440: 'type cast': cannot convert from 'const u_char *' to
'ATL::CA2WEX<>'
error C2440: 'type cast': cannot convert from 'u-char *' to
'ATL::CA2WEX<>'
Ulrich Eckhardt
2010-02-09 08:15:55 UTC
Permalink
Post by Rayne
Post by Rayne
Just to add, I've tried CA2T, and I still get the same errors.
After including <atlbase.h> and USES_CONVERSION, I get the following
errors for the 2 lines
user = CA2T(cuser);
packet = CA2CT(cpacket);
error C2440: 'type cast': cannot convert from 'const u_char *' to
'ATL::CA2WEX<>'
error C2440: 'type cast': cannot convert from 'u-char *' to
'ATL::CA2WEX<>'
Stop guessing. Look up the documentation at msdn.microsoft.com, it
explicitly tells you what header to include and what libs to link with. It
also tells you how to use it etc.

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Giovanni Dicanio
2010-02-09 08:51:49 UTC
Permalink
Post by Rayne
I'm trying to use the A2T macro for my pcap_loop callback function
"got_packet".
We suggested against A2T macro.
Consider using CA2T.
Post by Rayne
So I have
void got_packet(u_char *cuser, const struct pcap_pkthdr *header, const
u_char *cpacket)
{
_TUCHAR *user, *packet;
user = A2T(cuser);
packet = A2T(cpacket);
Please use TCHAR instead of _TUCHAR (this is the first time I read this kind
of type).
Moreover, I have no idea what u_char is.

Assuming that you have 'const char * cuser', 'const char * cpacket', you can
write code like this:

CA2T user( cuser );
CA2T packet( cpacket );

Now, you can use 'user' and 'packet' wherever a 'const TCHAR *' (i.e.
LPCTSTR) is required.
Post by Rayne
error C3861: 'A2T': identifier not found, even with argument-dependent
lookup
[...]
Post by Rayne
Is there some compiler setting or header files I should include?
In the page whose link was posted above in this thread:

http://msdn.microsoft.com/en-us/library/87zae4a3(VS.80).aspx
Post by Rayne
Requirements
Header file: AtlBase.h, AtlConv.h (declared in AtlConv.h)
So, you just need to #include <AtlBase.h> and <AtlConv.h> (a good place to
do that is "StdAfx.h" precompiled header).

HTH,
Giovanni
Alex Blekhman
2010-02-09 09:35:27 UTC
Permalink
Post by Rayne
Thank you for all the suggestions.
I'm trying to use the A2T macro for my pcap_loop callback
function "got_packet".
So I have
void got_packet(u_char *cuser, const struct pcap_pkthdr *header, const
u_char *cpacket)
{
_TUCHAR *user, *packet;
user = A2T(cuser);
packet = A2T(cpacket);
...
}
Well, it seems you've ignored my other post even though it
describes your case. I looked up the `pcap_loop' function and it
seems that you don't need any conversions at all. The type
`u_char' is used as a substitute for a byte, i.e. actual data is
binary.

Alex
Rayne
2010-02-10 10:22:45 UTC
Permalink
Post by Alex Blekhman
Post by Rayne
Thank you for all the suggestions.
I'm trying to use the A2T macro for my pcap_loop callback
function "got_packet".
So I have
void got_packet(u_char *cuser, const struct pcap_pkthdr *header, const
u_char *cpacket)
{
_TUCHAR *user, *packet;
user = A2T(cuser);
packet = A2T(cpacket);
...
}
Well, it seems you've ignored my other post even though it
describes your case. I looked up the `pcap_loop' function and it
seems that you don't need any conversions at all. The type
`u_char' is used as a substitute for a byte, i.e. actual data is
binary.
Alex
Sorry, I must have missed your post.

So after reading all the suggestions, I think that my initial approach
is wrong, in that I simply tried to convert all char and char * to
TCHAR.

So under what circumstances would I need the conversion, besides when
using string functions like strlen and strcat, APIs that have the A/W
versions and filenames longer than MAX_PATH characters?

Thank you.

Regards,
Rayne
Alex Blekhman
2010-02-10 11:05:27 UTC
Permalink
Post by Rayne
So under what circumstances would I need the conversion, besides
when using string functions like strlen and strcat, APIs that
have the A/W versions and filenames longer than MAX_PATH
characters?
You need the conversion for textual data only which you're going
to interpret and process as a text. For example, your program
accepts both Unicode and ANSI textual files as an input. But you
don't want to duplicate processing code to deal separately with
Unicode and ANSI files. So, naturally you convert all input to
Unicode first (if necessary), then you process the text as Unicode
all the way along.

However, in C language for ages people use `char' as a synonym to
byte to store binary data. So, not every buffer of char's requires
conversion. You need to know your data.

Alex

Ulrich Eckhardt
2010-02-08 10:30:05 UTC
Permalink
Post by Rayne
I'm using Visual Studio .NET 2003, and I'm trying to write a program
that can compile in both Unicode and Multi-Byte. Hence, the use of
TCHAR. However, I'm getting errors on pcap functions and socket
error C2664: 'pcap_findalldevs': cannot convert parameter 2 from
'TCHAR[256]' to 'char *'
I guess this deals with bytes.
Post by Rayne
error C2664: 'recv': cannot convert parameter 2 from 'TCHAR *' to
'char *'
error C2664: 'send': cannot convert parameter 2 from 'TCHAR *' to
'const char *'
Same.

You need to convert. Things like USES_CONVERSION/CT2A and similar stuff
help, maybe MultibyteToWideChar/WideCharToMultibyte, if you need to go more
low-level.

TCHAR is _not_ a sane choice for use in a network protocol, in case you were
wondering, rather use UTF-8.

Uli
--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
Alex Blekhman
2010-02-08 10:59:20 UTC
Permalink
Post by Rayne
I'm using Visual Studio .NET 2003, and I'm trying to write a
program that can compile in both Unicode and Multi-Byte. Hence,
the use of TCHAR. However, I'm getting errors on pcap functions
[...]
In addition to David's and Ulrich's answers. Many times C
functions treat `char' type as a mere substitution for bytes. So,
quite often when char* parameter is required, then the intention
is to receive/fill a buffer with binary data. In that case you
need to know how to interpret the data instead of converting it
from/to multi-byte and wide characters.

HTH
Alex
Loading...