Thread: Converting a C structure into a C++ class

  1. #1
    Registered User deadpoet's Avatar
    Join Date
    Jan 2004
    Posts
    50

    Converting a C structure into a C++ class

    Experts, I have been racking my brain over this one for the past two days. It should be simple but for the life of me I cannot figure it out. I want to convert the following structure into a class:

    Code:
    #define SIOC_SERIAL    _IOR('S', 254, struct scsi_serial)
    
    struct scsi_serial{
        ubit8  device_type;         // SCSI Device Type.
        ubit8  page_code;          // SCSI Page Code.
        ubit8  reserved;             // SCSI Reserved.
        ubit8  page_length;       // SCSI Page Length.
        ubit8  serial[252];          // SCSI Serial Number.
    };
    The above mentioned structure is from the HPUX 11i scsi.h and scsi_ctl.h files.

    The closest that I have been able to come is as follows:

    Code:
    /**************************************************
     **
     ** Filename: cdskinfo2.h
     **
     ** Purpose:
     **
    **************************************************/
    
    #ifndef _CDSKINFO2_H_
    #define _CDSKINFO2_H_
    #include <string>
    #include <fcntl.h>
    #include <errno.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    
    #define SIOC_SERIAL    _IOR('S', 254, struct scsi_serial)
    
    struct scsi_serial{
        ubit8  device_type;        // SCSI Device Type.
        ubit8  page_code;          // SCSI Page Code.
        ubit8  reserved;           // SCSI Reserved.
        ubit8  page_length;        // SCSI Page Length.
        ubit8  serial[252];        // SCSI Serial Number.
    };
    
    class CdskInfo{
     public:
        /* Data Members */
        char device_name[256];        // SCSI Device Name.
        struct scsi_serial sn;
    
        // Constructor
        CdskInfo( char *s );
    
        /* Public Methods */
        void print_device_name();
        void dump();
        int open_device();
    };
    #endif
    Code:
    /**************************************************
     **
     ** Filename: cdskinfo2.c
     **
     ** Purpose:
     **
     **************************************************/
    #include "cdskinfo2.h"
    
    CdskInfo::CdskInfo( char *s ){
        int fd, ret;
        strcpy( device_name, s );
        open_device();
    }
    
    void CdskInfo::print_device_name(){
        printf ( "SCSI_DEVICE_NAME=%s\n", device_name );
    }
    
    void CdskInfo::dump(){
        printf ( "SCSI_DEVICE_NAME=%s\n", device_name );
        printf ( "SCSI_SERIAL_NUMBER=%s\n", sn.serial );
    }
    
    int CdskInfo::open_device ( ){
        int fd, ret;
        if ( ( fd = open( device_name, O_RDONLY | O_NDELAY ) ) <= 0 ){
            perror( "Open Error" );
            return ( -1 );
        }
    
        if ( ( ret = ioctl( fd, SIOC_SERIAL, &sn ) ) != 0 ){
            perror( "SIOC_SERIAL Error" );
            return ( -1 );
        }
        return ( ret );
    }
    Code:
    /**************************************************
     **
     ** Filename: cdskinfo_main.cc
     **
     ** Purpose:
     **
    **************************************************/
    
    #include <iostream.h>
    #include <cstdlib>
    #include "cdskinfo2.h"
    
    int main ( int argc, char *argv[] ) {
    
        CdskInfo sserial( argv[1] );
    
        sserial.print_device_name();
        sserial.dump();
    
      exit( 0 );
    }
    The above source compiles and runs fine but it is not quite what I am trying to accomplish. My main desire is to eliminate the need to physically define the scsi_serial structure all to gether and just have a "pure" class based on this structure. One of the biggest hurdles I have had in this conversion is with the ioctl statement.

    Can anyone help me in solving this problem.

    Thanks in advance,

    DeadPoet

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Consider the following:
    Code:
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    struct Test
    {
        char c;
        int i;
        char str[20];
        float f;
    };//Test
    
    void print_Test(const Test *t)
    {
        cout << "c = " << t->c << endl
             << "i = " << t->i << endl
             << "f = " << t->f << endl
             << "str = " << t->str << endl;
    }//print_Test
    
    class CTest : public Test
    {
    public:
        CTest()
        {
            c = 'X';
            i = 69;
            f = 2.5;
            strcpy(str, "Hello");
        }//constructor
    
        void print() 
        {
            print_Test(this);
        }//print
    };//CTest
    
    int main()
    {
        CTest t;
        t.print();
        print_Test(&t);
        
        return 0;
    }//main
    gg

  3. #3
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    Specifically, what is the difficulty with ioctl()?

    Kuphryn

  4. #4
    Registered User deadpoet's Avatar
    Join Date
    Jan 2004
    Posts
    50
    Kuphryn and All Others,

    Consider the following code changes from the original posted source--All modifications are noted by CHANGE_MADE_HERE.

    Code:
    /*************************************************
     **
     ** Filename: cdskinfo3.h
     **
     ** Purpose:
     **
     *************************************************/
    #ifndef _CDSKINFO2_H_
    #define _CDSKINFO2_H_
    #include <string>
    #include <fcntl.h>
    #include <errno.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <sys/scsi.h>
    
    /* CHANGE_MADE_HERE */
    #define SIOC_SERIAL    _IOR('S', 254, class CdskInfo)
    
    /* CHANGE_MADE_HERE */
    /* Structure commented and now defined as Data Members */
    /*
    struct scsi_serial{
        ubit8  device_type;        // SCSI Device Type.
        ubit8  page_code;          // SCSI Page Code.
        ubit8  reserved;           // SCSI Reserved.
        ubit8  page_length;        // SCSI Page Length.
        ubit8  serial[252];        // SCSI Serial Number.
    };
    */
    
    class CdskInfo{
     public:
        /* Data Members */
    
        char device_name[256];        // SCSI Device Name.
        
            /* CHANGE_MADE_HERE */
        //    struct scsi_serial sn;
        
        /* CHANGE_MADE_HERE */
        ubit8  device_type;        // SCSI Device Type.
        ubit8  page_code;          // SCSI Page Code.
        ubit8  reserved;           // SCSI Reserved.
        ubit8  page_length;        // SCSI Page Length.
        ubit8  serial[252];        // SCSI Serial Number.
    
        // Constructor
    
        CdskInfo( char *s );
    
        /* Public Methods */
        void print_device_name();
        void dump();
        int open_device();
    };
    
    #endif
    Code:
    /*************************************************
     **
     ** Filename: cdskinfo3.c
     **
     ** Purpose:
     **
     *************************************************/
    #include "cdskinfo2.h"
    
    CdskInfo::CdskInfo( char *s ){
        int fd, ret;
        strcpy( device_name, s );
        open_device();
    }
    
    void CdskInfo::print_device_name(){
        printf ( "SCSI_DEVICE_NAME=%s\n", device_name );
    }
    
    void CdskInfo::dump(){
        printf ( "SCSI_DEVICE_NAME=%s\n", device_name );   
        printf ( "SCSI_SERIAL_NUMBER=%s\n", serial );    
    }
    
    int CdskInfo::open_device ( ){    
        int fd, ret;    
        if ( ( fd = open( device_name, O_RDONLY | O_NDELAY ) ) <= 0 ){	
    	perror( "Open Error" );	
    	return ( -1 );	
        }
    /* CHANGE_MADE_HERE */
    /* ioctl Now does not open the device */
        if ( ( ret = ioctl( fd, CSIOC_SERIAL, &(*this) ) ) != 0 ){
    	perror( "SIOC_SERIAL ERROR" );
    	return ( -1 );
        }
        return ( ret );
    }
    Code:
    /*************************************************
     **
     ** Filename: cdskinfo_main.cc
     **
     ** Purpose:
     **
     *************************************************/
    
    #include <iostream.h>
    #include <cstdlib> // for exit()
    #include "cdskinfo2.h"
    
    int main ( int argc, char *argv[] ) {
    
        CdskInfo sserial( argv[1] );
        
        cout << "*****DEBUG*****"  << endl;
        sserial.print_device_name();
        sserial.dump();
      
      exit( 0 );
    }
    At this point, ioctl is expecting the address of the scsi_serial structure like in the first posting. This was originally defined as struct scsi_serial sn and given to ioctl as ioctl( fd, SIOC_SERIAL, &sn). In both cases the code compiles and runs but in this modified case, it does not open the file descriptor fd and thus errors quietly. So, at this point, I cannot figure out how to replicate the behavior in the original post to this modified post.

    Any help is greatly appreciated.

    Thanks,

    DeadPoet

  5. #5
    Registered User deadpoet's Avatar
    Join Date
    Jan 2004
    Posts
    50
    One more update:

    CSIOC_SERIAL should be

    Code:
    /* CHANGE_MADE_HERE */
    /* ioctl Now does not open the device */
        if ( ( ret = ioctl( fd, SIOC_SERIAL, &(*this) ) ) != 0 ){
    	perror( "SIOC_SERIAL ERROR" );
    	return ( -1 );
        }
    Sorry,

    DeadPoet

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Put device_name after all the original scsi_serial members in CdskInfo.

    The memory layout of CdskInfo and scsi_serial must be identical for the first sizeof(scsi_serial) bytes.

    gg

  7. #7
    Registered User deadpoet's Avatar
    Join Date
    Jan 2004
    Posts
    50

    Cool

    Cool , If I remove the device_name then It does compile and run, without the device_name. However, I need the device_name and I need to add additional structures into this class. Any ideas ?

    Thanks You are the MAN,

    DeadPoet


  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Here's an idea...
    Originally posted by Codeplug
    Put device_name after all the original scsi_serial members in CdskInfo.

    The memory layout of CdskInfo and scsi_serial must be identical for the first sizeof(scsi_serial) bytes.

    gg
    Do you understand the memory layout of a given structure?

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Structure vs. Class
    By bobbelPoP in forum C++ Programming
    Replies: 4
    Last Post: 07-09-2008, 09:44 AM
  3. Need help to build network class
    By weeb0 in forum C++ Programming
    Replies: 0
    Last Post: 02-01-2006, 11:33 AM
  4. Mmk, I give up, lets try your way. (Resource Management)
    By Shamino in forum Game Programming
    Replies: 31
    Last Post: 01-18-2006, 09:54 AM
  5. Serial Communications in C
    By ExDigit in forum Windows Programming
    Replies: 7
    Last Post: 01-09-2002, 10:52 AM