PDA

View Full Version : Calling into C code




Maury
Jun 15, 2012, 09:36 AM
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...

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?



ScoobyMcDoo
Jun 15, 2012, 10:42 AM
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.

chown33
Jun 15, 2012, 10:43 AM
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
SQLHDBC ConnectionHandle
not
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.

robbieduncan
Jun 15, 2012, 10:44 AM
stringWithCString:encoding: is declared as:

+ (id)stringWithCString:(const char *)cString encoding:(NSStringEncoding)enc

So why are you passing

&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)?

Maury
Jun 15, 2012, 12:07 PM
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.


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.

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

chown33
Jun 15, 2012, 12:13 PM
@ ScoobyMcDoo & robbieduncan

#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):
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.

----------

Thank you so much, your suggestion to remove the & on hdbc nailed it! Ugg, so nice to see working data.

Glad it worked out.


Ok I'd like to do this now, do you have a pointer to the doc for this? My google-fu has failed me.
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.

ScoobyMcDoo
Jun 15, 2012, 01:44 PM
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.