Calling into C code

Discussion in 'Mac Programming' started by Maury, Jun 15, 2012.

  1. Maury, Jun 15, 2012
    Last edited by a moderator: Jun 15, 2012

    macrumors 6502

    Joined:
    Mar 25, 2008
    #1
    This is noob, I know, but I haven't touched basic C in years...

    I'm trying to call into the ODBC call "SQLGetConnectAttr", as documented here:

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms710297(v=vs.85).aspx

    My code is...
    Code:
        SQLCHAR szName[SQL_MAXIMUM_CATALOG_NAME_LENGTH];
        SQLINTEGER iLen;
        SQLINTEGER nResult;
        
        nResult = SQLGetConnectAttr(&hdbc, SQL_ATTR_CURRENT_CATALOG, &szName, SQL_MAXIMUM_CATALOG_NAME_LENGTH, &iLen);
        if (nResult != SQL_SUCCESS)
        {
            // do something!
        }
        
        return [NSString stringWithCString:(char *)&szName encoding:NSASCIIStringEncoding];
    
    The code runs without errors, but I'm getting gooblygook output. I suspect I'm declaring or passing the buffer incorrectly? That I should or should not have a * and/or & somewhere?
     
  2. macrumors 65816

    Joined:
    Nov 26, 2007
    Location:
    Austin, TX
    #2
    I think your third parameter should be szName rather than &szName. The API is asking for a pointer to a buffer. You are supplying it a pointer to a pointer to a buffer.
     
  3. macrumors 603

    Joined:
    Aug 9, 2009
    #3
    1. Please show the type of the variable hdbc. If its type is SQLHDBC, then your first function arg is wrong. The declared type is
    Code:
    SQLHDBC ConnectionHandle
    
    not
    Code:
    SQLHDBC * ConnectionHandle
    
    There should have been a compiler warning about mismatched types. If not, you should turn on strict arg-type checking for functions, and pay attention to all warnings.


    2. If nResult isn't successful, does the block return or otherwise break sequential flow? Because if it doesn't, it will fall thru to NSString stringWithCString:, which I'm pretty sure won't work.


    3. Is the string data really in the ASCII encoding? ASCII is a 7-bit code. If there are any bytes in the range 0x80-0xFF, it ain't ASCII.
     
  4. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4
    stringWithCString:encoding: is declared as:

    Code:
    + (id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc
    So why are you passing

    Code:
    &szName
    Which you are casting to be a char*? What does the & operator do? Does this result in a pointer? Or did you already have a pointer before you used the & operator (hint are arrays really pointers)?
     
  5. thread starter macrumors 6502

    Joined:
    Mar 25, 2008
    #5
    Thank you so much, your suggestion to remove the & on hdbc nailed it! Ugg, so nice to see working data.

    I know I have to re-learn all these pointer passing rules, it can be very frustrating to track these down.

    Ok I'd like to do this now, do you have a pointer to the doc for this? My google-fu has failed me.
     
  6. macrumors 603

    Joined:
    Aug 9, 2009
    #6
    @ ScoobyMcDoo & robbieduncan

    Code:
    #include <stdio.h>
    
    #define SQL_MAXIMUM_CATALOG_NAME_LENGTH  20
    
    typedef  unsigned char  SQLCHAR;
    
    int main( int argc, const char * argv[] )
    {
    	SQLCHAR szName[ SQL_MAXIMUM_CATALOG_NAME_LENGTH ];
    	int nums[ 10 ];
    
    	printf( " szName: %p\n", szName );
    	printf( " &szName: %p\n", &szName );
    	printf( " &szName[0]: %p\n", &szName[0] );
    
    	printf( " nums: %p\n", nums );
    	printf( " &nums: %p\n", &nums );
    	printf( " &nums[0]: %p\n", &nums[0] );
    }
    
    Output (64-bit):
    Code:
     szName: 0x7fff5fbff890
     &szName: 0x7fff5fbff890
     &szName[0]: 0x7fff5fbff890
     nums: 0x7fff5fbff860
     &nums: 0x7fff5fbff860
     &nums[0]: 0x7fff5fbff860
    

    In C, the unadorned name of an array is a constant pointer to the first element of that array. Since it's a constant, it can't have its address taken (prefix & operator). The compiler simply gives the address of the first array element, effectively ignoring the &. There was a time when C compilers complained about & prefixing array names, but that was long, long ago.

    If szName were declared as pointer type, then it can have its address taken. The code illustrating this is left as an exercise for the reader.

    ----------

    Glad it worked out.


    Your OS version? Xcode version? Development tools (Xcode, make, something else)?

    -Wall should turn on most warnings. Otherwise consult the man page for gcc and look for the word prototype.
     
  7. macrumors 65816

    Joined:
    Nov 26, 2007
    Location:
    Austin, TX
    #7
    Wow, I forgot all about that. Made me curious, so I looked it up in my trusty 1st edition K&R and sure enough is says that taking the address of an array is illegal.
     

Share This Page