Click here to Skip to main content
13,557,860 members
Click here to Skip to main content
Add your own
alternative version


24 bookmarked
Posted 21 Nov 2004
Licenced MPL

OpenClient++: C++ wrapper for Sybase Open Client library

, 21 Nov 2004
Rate this:
Please Sign up or sign in to vote.
OpenClient++ is a thread safe, cross platform C++ wrapper for Sybase Open Client API.


Sybase Open Client is the interface (API) between client applications and Sybase database server. In fact, it allows client applications to communicate to any database server which supports Tabular Data Stream (TDS) protocol. Currently, Microsoft SQL server and Sybase database server support TDS protocol. Open Client API can be thought of having two components.

  1. Programming Interface component implemented in C programming language which allows a user to build applications to communicate to Server. It contains Client-Library, DB-Library and CS-Library.
    • DB-Library, a collection of routines for use in writing client applications. DB-Library includes a bulk copy library and the two-phase commit special library.
    • Client-Library, a collection of routines for use in writing client applications. Client-Library is a new library, designed to accommodate cursors and other advanced features in the SYBASE 10.0 product line.
    • CS-Library, a collection of utility routines that are useful to both client and server applications. All Client-Library applications will include at least one call to CS-Library, because Client-Library routines use a structure which is allocated in CS-Library.
  2. Open Client Network services includes network library which provides support for specific network protocols such as TCP/IP or DCENet. For more information, see

Tabular Data Stream protocol was developed by Sybase to provide client-server communication between Sybase client and Server. You can get protocol specifications from Sybase or see


I wanted to learn the Open Client library to access Sybase ASE server (12_5) from my client application. The best way I found was to implement C++ wrapper which can provide thread safe, cross platform interface similar to MySQL++ or other database library. Current version of OpenClient++ library provides following features using Client-Library (CT_LIB and CS_LIB routines):

  • C++ API
  • Thread Safe access
  • Cross platform (Windows and Linux)
  • Error Handling: it provides error handling using C++ Exception handling as well as traditional way where return values of function call is checked. Exception handling can be enabled/disabled at library level or individual class level.
  • Following SQL commands are supported:
    1. SELECT
    2. UPDATE
    3. DELETE
    4. INSERT
  • Good documentation generated using DOxygen.

Interface Design:

Following classes are implemented to develop this library.

  1. Context:
    • Context: It is a singleton class which provides the instance of itself. It stores CS_CONTEXT structure and provides thread safe access context of client-library. It provides methods to set the debug level, enabled/disable exception handling, and call back function settings for error handling.
    • ContextException: It is an exception class for Context class. It is derives from the standard "Exception" class.
  2. Connection:
    • Connection: It’s a wrapper class for CS_CONNECTION structure. It stores connection parameters and establishes connection with server.
    • ConnectException: It is an exception class for Connection class. It is derived from the standard "Exception" class.
  3. Command:
    • Command: It’s a wrapper class for CS_COMMAND structure. It stores the SQL command string and type of command. It also builds and executes the commands using ct_command() and ct_send() functions of Client-Library.
    • CommandException: It is an exception class for Command class. It is derived from the standard "Exception" class.
  4. Query:
    • Query: It executes the command string, processes the result received from the server, and stores it into a RecordSet.
    • QueryException: It is an exception class for Query class. It is derived from the standard "Exception" class.
  5. Record Set:
    • Record: It’s a wrapper class for COLUMN_DATA structure. It stores information about columns and its value.
    • RecordSet: It stores the Record class objects, number of row updates, query success/failure, transaction ID and command ID.
  6. Utility classes:
    • Mutex: It provides the synchronized access to Context class object. It is implemented in two different header files.
      1. Mutex.h: Mutex class implementation for Linux.
      2. MutexWin.h: Mutex class implementation for Windows.
    • template<class T> Lock: It provides the guard lock functionality for Mutex class which avoids indefinite mutex locking in error condition.

Here is the diagram showing relationship among the classes:

Class Digram


The simple usage of this library involves the following steps:

  • Set up the environment variables: get the instance of Context class which is a singleton class and set the environment variables like debug level, exception handling and error display. It provides the default call back functions to display the errors on the terminal. You can write your own custom call back functions and set it to context.
  • Connect to the server: connection class provides multiple constructor and connect() methods to pass connection information.
  • Create a Query Object: Connection class provides the method GetQuery() which creates the Query object by setting this as member variable.
  • Send a Command: Query object provides the method Execute() to send a command to the Server, it processes the result received from the server, stores into RecordSet, and returns the RecordSet object.
  • Result Processing: RecordSet object provides GetRecordsCount() method which returns total number of Records available. It provides GetRecord(index) method to retrieve the Record class object using which you can retrieve field name and value.
int main()
    try {
        // Get the context instance
        Context* pInstance = Context::GetInstance();
        std::cout << "Initialized the Context" << std::endl;
    }catch(ContextException &e) {
        std::cout << e.what() << std::endl;
        return -1;
    try {
        // Set the debug level to all
        // Set the call back handles for CS, CT and SRV libs
        pInstance->SetCallbackHandler(Context::SRV_LIB, servermsg_callback);
    }catch(ContextException &e) {
        std::cout << e.what() << std::endl;
    // Initialize the connection object
    Connection oConn("TestDB", "username", "password", "servername");
    try {
        // connect to server
    }catch (ConnectionException &e) {
        std::cout << e.what() << std::endl;
        return -1;
    // Get the instance of Query class
    Query q = oConn.GetQuery();
    try {
        char sCommandBuff[256] = "";
        string sCmd;
        // execute the command untill userinput is "q"
        while(sCmd != "q") {
            std::cout << ">";
            std::cin.getline(sCommandBuff, 256);
            string sCmd = sCommandBuff;
            if(sCmd == "q")
            // Execute the query
            RecordSet &result = q.Execute(sCmd);
            if(result.IsSuccess()) {
                for(int i =0; i < result.GetRecordsCount(); i++) {
                    // Get the record
                    Record *pRecord = result.GetRecord(i);
                    for(int j =0 ; j < pRecord->GetFieldsCount(); j++) {
                        std::cout << "Column:"
                                  << result.GetFieldName(j) 
                                  << "    Value:" 
                                  << pRecord->GetFieldValue(j) 
                                  << std::endl;
                 std::cout << result.GetMessage()<< std::endl;
                 std::cout << "Result:"<<(bool)result
                            << " NumRows:" << result.GetRowsRead() 
                            << " CmdNum:" << result.GetCommandId()
                            << "Transaction Id:" 
                            << result.GetTransState() << std::endl;
             }else {
                 // print failure condition
                 std::cout << result.GetMessage() << std::endl;
                 std::cout << "Result:"<<(bool)result
                            << " NumRows:" << result.GetRowsRead() 
                            << " CmdNum:" << result.GetCommandId()
                            << "Transaction Id:" 
                            << result.GetTransState() << std::endl;
        } // while end
     }catch (QueryException &e) {
         std::cout << e.what() << std::endl;
      return 0;


Your comments, suggestions and rating for this article are appreciated.


This article, along with any associated source code and files, is licensed under The Mozilla Public License 1.1 (MPL 1.1)


About the Author

Rohit Joshi
Software Developer
United States United States
Rohit Joshi is a software engineer working for a telecom company in USA. He has development expirience using C, C++ ,C#, VoiceXML, ASR, IMAP, LDAP, HTTP, SIP, H323 on unix/linux and platforms.

You may also be interested in...


Comments and Discussions

QuestionDo I need the libct.dll to use this wrapper? Pin
AnneZ25-Sep-07 9:23
memberAnneZ25-Sep-07 9:23 
AnswerRe: Do I need the libct.dll to use this wrapper? Pin
Rohit Joshi26-Sep-07 4:46
memberRohit Joshi26-Sep-07 4:46 
AnswerRe: Do I need the libct.dll to use this wrapper? Pin
Rohit Joshi26-Sep-07 4:47
memberRohit Joshi26-Sep-07 4:47 
GeneralRe: Do I need the libct.dll to use this wrapper? Pin
AnneZ26-Sep-07 5:02
memberAnneZ26-Sep-07 5:02 
GeneralRe: Do I need the libct.dll to use this wrapper? Pin
Rohit Joshi27-Sep-07 8:44
memberRohit Joshi27-Sep-07 8:44 
GeneralRe: Do I need the libct.dll to use this wrapper? Pin
mindplaytm25-Oct-07 9:37
membermindplaytm25-Oct-07 9:37 
GeneralRe: Do I need the libct.dll to use this wrapper? Pin
ttttnht19-Jun-08 6:05
memberttttnht19-Jun-08 6:05 
QuestionCould you send me a project? Pin
hubei_121820-Jul-07 18:22
memberhubei_121820-Jul-07 18:22 
Generala problem Pin
hubei_121820-Jul-07 18:17
memberhubei_121820-Jul-07 18:17 
GeneralMemory leak Pin
Lukasz Kurylo17-Apr-07 23:51
memberLukasz Kurylo17-Apr-07 23:51 
GeneralRe: Memory leak Pin
Rohit Joshi18-Apr-07 3:30
memberRohit Joshi18-Apr-07 3:30 
GeneralRe: Memory leak Pin
dave_dave19-Mar-12 22:28
memberdave_dave19-Mar-12 22:28 
GeneralQuestion about wrapper Pin
vasjos15-Nov-05 8:26
membervasjos15-Nov-05 8:26 
GeneralMore methods Pin
elecoest29-Apr-05 1:52
memberelecoest29-Apr-05 1:52 
GeneralAnything like this in C# Pin
Pink Floyd7-Apr-05 7:54
memberPink Floyd7-Apr-05 7:54 
GeneralRe: Anything like this in C# Pin
Rohit Joshi14-Apr-05 13:03
memberRohit Joshi14-Apr-05 13:03 
Questionthreadsafe? Pin
anybody anyone16-Mar-05 4:28
memberanybody anyone16-Mar-05 4:28 
AnswerRe: threadsafe? Pin
Anonymous16-Mar-05 14:14
sussAnonymous16-Mar-05 14:14 
AnswerRe: threadsafe? Pin
Rohit Joshi16-Mar-05 14:21
memberRohit Joshi16-Mar-05 14:21 
GeneralSupport for cursor Pin
Anonymous21-Nov-04 8:48
sussAnonymous21-Nov-04 8:48 
GeneralRe: Support for cursor Pin
Rohit Joshi21-Nov-04 9:34
memberRohit Joshi21-Nov-04 9:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04-2016 | 2.8.180515.1 | Last Updated 21 Nov 2004
Article Copyright 2004 by Rohit Joshi
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid