Re: UNICODE support
Nick Gorham <[email protected]> Mon, 28 Mar 2016 13:22:48 +0100
| Newsgroups | gmane.comp.db.unixodbc.devel |
|---|---|
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format. --===============1091204469== Content-Type: multipart/alternative; boundary="------------090704020904070004050000" This is a multi-part message in MIME format. --------------090704020904070004050000 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit On 28/03/16 01:35, Igor Korot wrote: > Nick, > > On Sat, Mar 26, 2016 at 2:57 PM, Nick Gorham <[email protected]> wrote: >> On 26/03/16 18:00, Igor Korot wrote: >>> Nick, >>> >>> On Sat, Mar 26, 2016 at 1:36 PM, Nick Gorham <[email protected]> wrote: >>>> On 26/03/16 17:31, Igor Korot wrote: >>>>> Hi, Nick, >>>>> >>>>> On Sat, Mar 26, 2016 at 12:58 PM, Nick Gorham <[email protected]> wrote: >>>>>> On 26/03/16 15:10, Igor Korot wrote: >>>>>>> Hi, (Nick), >>>>>>> Is it enough to do: >>>>>>> >>>>>>> #define UNICODE >>>>>>> >>>>>>> in order to use SQLW-types and functions? >>>>>>> >>>>>>> Or I need to define something else? >>>>>>> >>>>>>> Thank you. >>>>>>> _______________________________________________ >>>>>>> unixODBC-dev mailing list >>>>>>> [email protected] >>>>>>> http://mailman.unixodbc.org/mailman/listinfo/unixodbc-dev >>>>>> You should just be able to use them. Whats not working? >>>>> Check the following code: >>>>> >>>>> [code] >>>>> /* odbc.c >>>>> >>>>> testing unixODBC >>>>> */ >>>>> #include <stdlib.h> >>>>> #include <stdio.h> >>>>> #include <odbcinst.h> >>>>> #include <sqlext.h> >>>>> >>>>> #define SQL_WCHART_CONVERT >>>>> >>>>> int main(int argc,char *argv[]) >>>>> { >>>>> SQLHENV m_henv; >>>>> SQLSMALLINT i = 1, attr_ret; >>>>> SQLWCHAR driverDesc[1024], driverAttributes[256], >>>>> dsn[SQL_MAX_DSN_LENGTH + 1], sqlState[20], >>>>> errMsg[SQL_MAX_MESSAGE_LENGTH], dsnDescr[255]; >>>>> SWORD pcbDSN, pcbDesc; >>>>> SQLINTEGER nativeError; >>>>> SQLSMALLINT cbErrorMsg, descriptionLength; >>>>> SQLUSMALLINT direction = SQL_FETCH_FIRST, direct = >>>>> SQL_FETCH_FIRST; >>>>> >>>>> RETCODE ret = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HENV, >>>>> &m_henv >>>>> ); >>>>> if( ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO ) >>>>> { >>>>> printf( "Error allocating handle\r\n" ); >>>>> while( ( ret = SQLGetDiagRecW( SQL_HANDLE_ENV, m_henv, i, >>>>> sqlState, &nativeError, errMsg, sizeof( errMsg ), &cbErrorMsg ) ) == >>>>> SQL_SUCCESS ) >>>>> { >>>>> printf( "Error is: %s\r\n", errMsg ); >>>>> } >>>>> exit( 0 ); >>>>> } >>>>> else >>>>> { >>>>> ret = SQLSetEnvAttr( m_henv, SQL_ATTR_ODBC_VERSION, (void *) >>>>> SQL_OV_ODBC3, 0 ); >>>>> if( ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO ) >>>>> { >>>>> printf( "Error setting environment\r\n" ); >>>>> while( ( ret = SQLGetDiagRec( SQL_HANDLE_ENV, m_henv, i, >>>>> sqlState, &nativeError, errMsg, sizeof( errMsg ), &cbErrorMsg ) ) == >>>>> SQL_SUCCESS ) >>>>> { >>>>> printf( "Error is: %s\r\n", errMsg ); >>>>> } >>>>> exit( 0 ); >>>>> } >>>>> else >>>>> { >>>>> while( ( ret = SQLDrivers( m_henv, direction, driverDesc, >>>>> sizeof( driverDesc ) - 1, &descriptionLength, driverAttributes, >>>>> sizeof( driverAttributes ), &attr_ret ) ) == SQL_SUCCESS ) >>>>> { >>>>> while( ( ret = SQLDataSources( m_henv, direct, dsn, >>>>> SQL_MAX_DSN_LENGTH, &pcbDSN, dsnDescr, 254, &pcbDesc ) ) == >>>>> SQL_SUCCESS ) >>>>> { >>>>> printf( "Driver description is %s", driverDesc ); >>>>> printf( "DSN description is %s", dsnDescr ); >>>>> direct = SQL_FETCH_NEXT; >>>>> } >>>>> if( ret != SQL_SUCCESS && ret != SQL_NO_DATA ) >>>>> { >>>>> printf( "Error retrieving Data Source" ); >>>>> while( ( ret = SQLGetDiagRec( SQL_HANDLE_ENV, >>>>> m_henv, i, sqlState, &nativeError, errMsg, sizeof( errMsg ), >>>>> &cbErrorMsg ) ) == SQL_SUCCESS ) >>>>> { >>>>> printf( "Error is: %s\r\n", errMsg ); >>>>> } >>>>> break; >>>>> } >>>>> direction = SQL_FETCH_NEXT; >>>>> } >>>>> } >>>>> } >>>>> return 0; >>>>> } >>>>> [/code] >>>>> >>>>> resulted in: >>>>> >>>>> [code] >>>>> igor@IgorDellGentoo ~ $ gcc -DUNICODE odbctest.cpp -o odbctest -lodbc >>>>> odbctest.cpp: In function 'int main(int, char**)': >>>>> odbctest.cpp:30:48: warning: format '%s' expects argument of type >>>>> 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' >>>>> [-Wformat=] >>>>> printf( "Error is: %s\r\n", errMsg ); >>>>> ^ >>>>> odbctest.cpp:42:52: warning: format '%s' expects argument of type >>>>> 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' >>>>> [-Wformat=] >>>>> printf( "Error is: %s\r\n", errMsg ); >>>>> ^ >>>>> odbctest.cpp:52:68: warning: format '%s' expects argument of type >>>>> 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' >>>>> [-Wformat=] >>>>> printf( "Driver description is %s", driverDesc ); >>>>> ^ >>>>> odbctest.cpp:53:63: warning: format '%s' expects argument of type >>>>> 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' >>>>> [-Wformat=] >>>>> printf( "DSN description is %s", dsnDescr ); >>>>> ^ >>>>> odbctest.cpp:61:60: warning: format '%s' expects argument of type >>>>> 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' >>>>> [-Wformat=] >>>>> printf( "Error is: %s\r\n", errMsg ); >>>>> ^ >>>>> [/code] >>>>> >>>>> Any idea what is going on? And how to fix it? >>>>> >>>>> Thank you. >>>> >>>> Err, I think the compiler is telling you, You have a array >>>> >>>> SQLWCHAR errMsg[SQL_MAX_MESSAGE_LENGTH] >>> Well I do have "-DUNICODE" passed to the compiler. >>> So SQLWCHAR should not become "unsigned char", but rather "wchar_t". >>> >>> Am I wrong? >>> >>> Thank you. >> >> Yes. >> >> SQLWCHAR that ODBC uses is a 16 byte type, wchar_t is normally a 32 byte >> type. >> >> I think you may be thinking of SQLTCHAR that will switch between char and >> SQLWCHAR depending on the flag. But either way, the standard library >> (printf) doesn't know or care, %s = char > Taken from C:\Program Files (x86)\Microsoft > SDKs\Windows\v7.0A\Include\sqltypes.h(286: > > [code] > #ifdef _WCHAR_T_DEFINED > typedef wchar_t SQLWCHAR; > #else > typedef unsigned short SQLWCHAR; > #endif > > #ifdef UNICODE > typedef SQLWCHAR SQLTCHAR; > #else > typedef SQLCHAR SQLTCHAR; > #endif /* UNICODE */ > [/code] > > I presume unixODBC uses the same code, right? > > Which means that all I need is to define _WCHAR_T_DEFINED in order for SQLWCHAR > to become wchar_t instead of unsigned short. Generally, no. To quote "/|wchar_t| is compiler-dependent and therefore not very portable. Using it for Unicode binds a program to the character model of a compiler. Instead, it is often better to define and use dedicated data types." /In most cases outside of Windows wchar_t is a 4 byte type. You can build unixODBC to use 4 byte SQLWCHAR, but you will find it won't work with most drivers out there. / / > > Now on related note, char = %c char* = %s, is it not? > Granted I didn't use plain C for a long time, but I think here I'm right. ;-) Yes, I was assuming a shorthand, where %s is char array, I assumed you would know the array part. But the important part of that is that its char, not long, short or int. -- Nick --------------090704020904070004050000 Content-Type: text/html; charset=windows-1252 Content-Transfer-Encoding: 7bit <html> <head> <meta content="text/html; charset=windows-1252" http-equiv="Content-Type"> </head> <body text="#000000" bgcolor="#FFFFFF"> <div class="moz-cite-prefix">On 28/03/16 01:35, Igor Korot wrote:<br> </div> <blockquote cite="mid:CA+FnnTxGqC-wipS6SDNLmTTi=9VC=OxG6xR-HWNfHVHxo0aMTg@mail.gmail.com" type="cite"> <pre wrap="">Nick, On Sat, Mar 26, 2016 at 2:57 PM, Nick Gorham <a class="moz-txt-link-rfc2396E" href="mailto:[email protected]"><[email protected]></a> wrote: </pre> <blockquote type="cite"> <pre wrap="">On 26/03/16 18:00, Igor Korot wrote: </pre> <blockquote type="cite"> <pre wrap=""> Nick, On Sat, Mar 26, 2016 at 1:36 PM, Nick Gorham <a class="moz-txt-link-rfc2396E" href="mailto:[email protected]"><[email protected]></a> wrote: </pre> <blockquote type="cite"> <pre wrap=""> On 26/03/16 17:31, Igor Korot wrote: </pre> <blockquote type="cite"> <pre wrap=""> Hi, Nick, On Sat, Mar 26, 2016 at 12:58 PM, Nick Gorham <a class="moz-txt-link-rfc2396E" href="mailto:[email protected]"><[email protected]></a> wrote: </pre> <blockquote type="cite"> <pre wrap=""> On 26/03/16 15:10, Igor Korot wrote: </pre> <blockquote type="cite"> <pre wrap=""> Hi, (Nick), Is it enough to do: #define UNICODE in order to use SQLW-types and functions? Or I need to define something else? Thank you. _______________________________________________ unixODBC-dev mailing list <a class="moz-txt-link-abbreviated" href="mailto:[email protected]">[email protected]</a> <a class="moz-txt-link-freetext" href="http://mailman.unixodbc.org/mailman/listinfo/unixodbc-dev">http://mailman.unixodbc.org/mailman/listinfo/unixodbc-dev</a> </pre> </blockquote> <pre wrap=""> You should just be able to use them. Whats not working? </pre> </blockquote> <pre wrap=""> Check the following code: [code] /* odbc.c testing unixODBC */ #include <stdlib.h> #include <stdio.h> #include <odbcinst.h> #include <sqlext.h> #define SQL_WCHART_CONVERT int main(int argc,char *argv[]) { SQLHENV m_henv; SQLSMALLINT i = 1, attr_ret; SQLWCHAR driverDesc[1024], driverAttributes[256], dsn[SQL_MAX_DSN_LENGTH + 1], sqlState[20], errMsg[SQL_MAX_MESSAGE_LENGTH], dsnDescr[255]; SWORD pcbDSN, pcbDesc; SQLINTEGER nativeError; SQLSMALLINT cbErrorMsg, descriptionLength; SQLUSMALLINT direction = SQL_FETCH_FIRST, direct = SQL_FETCH_FIRST; RETCODE ret = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HENV, &m_henv ); if( ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO ) { printf( "Error allocating handle\r\n" ); while( ( ret = SQLGetDiagRecW( SQL_HANDLE_ENV, m_henv, i, sqlState, &nativeError, errMsg, sizeof( errMsg ), &cbErrorMsg ) ) == SQL_SUCCESS ) { printf( "Error is: %s\r\n", errMsg ); } exit( 0 ); } else { ret = SQLSetEnvAttr( m_henv, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0 ); if( ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO ) { printf( "Error setting environment\r\n" ); while( ( ret = SQLGetDiagRec( SQL_HANDLE_ENV, m_henv, i, sqlState, &nativeError, errMsg, sizeof( errMsg ), &cbErrorMsg ) ) == SQL_SUCCESS ) { printf( "Error is: %s\r\n", errMsg ); } exit( 0 ); } else { while( ( ret = SQLDrivers( m_henv, direction, driverDesc, sizeof( driverDesc ) - 1, &descriptionLength, driverAttributes, sizeof( driverAttributes ), &attr_ret ) ) == SQL_SUCCESS ) { while( ( ret = SQLDataSources( m_henv, direct, dsn, SQL_MAX_DSN_LENGTH, &pcbDSN, dsnDescr, 254, &pcbDesc ) ) == SQL_SUCCESS ) { printf( "Driver description is %s", driverDesc ); printf( "DSN description is %s", dsnDescr ); direct = SQL_FETCH_NEXT; } if( ret != SQL_SUCCESS && ret != SQL_NO_DATA ) { printf( "Error retrieving Data Source" ); while( ( ret = SQLGetDiagRec( SQL_HANDLE_ENV, m_henv, i, sqlState, &nativeError, errMsg, sizeof( errMsg ), &cbErrorMsg ) ) == SQL_SUCCESS ) { printf( "Error is: %s\r\n", errMsg ); } break; } direction = SQL_FETCH_NEXT; } } } return 0; } [/code] resulted in: [code] igor@IgorDellGentoo ~ $ gcc -DUNICODE odbctest.cpp -o odbctest -lodbc odbctest.cpp: In function 'int main(int, char**)': odbctest.cpp:30:48: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' [-Wformat=] printf( "Error is: %s\r\n", errMsg ); ^ odbctest.cpp:42:52: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' [-Wformat=] printf( "Error is: %s\r\n", errMsg ); ^ odbctest.cpp:52:68: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' [-Wformat=] printf( "Driver description is %s", driverDesc ); ^ odbctest.cpp:53:63: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' [-Wformat=] printf( "DSN description is %s", dsnDescr ); ^ odbctest.cpp:61:60: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'SQLWCHAR* {aka short unsigned int*}' [-Wformat=] printf( "Error is: %s\r\n", errMsg ); ^ [/code] Any idea what is going on? And how to fix it? Thank you. </pre> </blockquote> <pre wrap=""> Err, I think the compiler is telling you, You have a array SQLWCHAR errMsg[SQL_MAX_MESSAGE_LENGTH] </pre> </blockquote> <pre wrap=""> Well I do have "-DUNICODE" passed to the compiler. So SQLWCHAR should not become "unsigned char", but rather "wchar_t". Am I wrong? Thank you. </pre> </blockquote> <pre wrap=""> Yes. SQLWCHAR that ODBC uses is a 16 byte type, wchar_t is normally a 32 byte type. I think you may be thinking of SQLTCHAR that will switch between char and SQLWCHAR depending on the flag. But either way, the standard library (printf) doesn't know or care, %s = char </pre> </blockquote> <pre wrap=""> Taken from C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\sqltypes.h(286: [code] #ifdef _WCHAR_T_DEFINED typedef wchar_t SQLWCHAR; #else typedef unsigned short SQLWCHAR; #endif #ifdef UNICODE typedef SQLWCHAR SQLTCHAR; #else typedef SQLCHAR SQLTCHAR; #endif /* UNICODE */ [/code] I presume unixODBC uses the same code, right? Which means that all I need is to define _WCHAR_T_DEFINED in order for SQLWCHAR to become wchar_t instead of unsigned short.</pre> </blockquote> <br> Generally, no. To quote "<em><code>wchar_t</code> is compiler-dependent and therefore not very portable. Using it for Unicode binds a program to the character model of a compiler. Instead, it is often better to define and use dedicated data types."<br> <br> </em>In most cases outside of Windows wchar_t is a 4 byte type. You can build unixODBC to use 4 byte SQLWCHAR, but you will find it won't work with most drivers out there. <em><br> </em> <blockquote cite="mid:CA+FnnTxGqC-wipS6SDNLmTTi=9VC=OxG6xR-HWNfHVHxo0aMTg@mail.gmail.com" type="cite"> <pre wrap=""> Now on related note, char = %c char* = %s, is it not? Granted I didn't use plain C for a long time, but I think here I'm right. ;-)</pre> </blockquote> <br> Yes, I was assuming a shorthand, where %s is char array, I assumed you would know the array part. But the important part of that is that its char, not long, short or int.<br> <br> -- <br> Nick<br> </body> </html> --------------090704020904070004050000-- --===============1091204469== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ unixODBC-dev mailing list [email protected] http://mailman.unixodbc.org/mailman/listinfo/unixodbc-dev --===============1091204469==--