Re: UNICODE support
Igor Korot <[email protected]> Mon, 28 Mar 2016 10:57:10 -0400
| Newsgroups | gmane.comp.db.unixodbc.devel |
|---|---|
| Message-ID | <CA+FnnTzCck27nr9KzoyECgBy0Hd=xhpPMnVres3wxqBy8WKkDA@mail.gmail.com> |
Nick, On Mon, Mar 28, 2016 at 8:22 AM, Nick Gorham <[email protected]> wrote: > 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. OK, so basically what you are saying is: "Its not possible to write a portable code which uses MS ODBC manager and unixODBC". Because looking at my code, it looks like _WCHAR_T_DEFINED is defined. ;-) It would be nice if the Development manual was updated with this info. > > 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. Yes, but "char *" is just a dynamically allocated array of characters. Thank you. > > -- > Nick > > _______________________________________________ > unixODBC-dev mailing list > [email protected] > http://mailman.unixodbc.org/mailman/listinfo/unixodbc-dev > _______________________________________________ unixODBC-dev mailing list [email protected] http://mailman.unixodbc.org/mailman/listinfo/unixodbc-dev