Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

C string from Fortran string

Nick2
New Contributor I
848 Views

My subroutine declares,

character*15000 SQLStmtStr
character*15000 SQLStmtStrA

where SQLStmtStr is an incoming argument. My goal is to make a C string to call

iRet = SQLExecDirect(StmtHndl,SQLStmtStrA,len)

And I'm not sure how to accomplish this...if I try

SQLStmtStrA=ADJUSTL(TRIM(SQLStmtStr))//char(0)

Then SQLStmtStrA ends up with garbage characters.

If I try

len=

len_trim(SQLStmtStr)
SQLStmtStrA=SQLStmtStr(1:len)//char(0)

Then the code stops execution when I step over that last line.

Errr...what am I doing wrong?

0 Kudos
9 Replies
Nick2
New Contributor I
848 Views
SQL was kind enough to let me send in the Fortran string (and the length) - so this issue is resolved. But it would still be nice to know where this weird behavior came from.
0 Kudos
Steven_L_Intel1
Employee
848 Views
My guess is that it's because you declared the arguments as CHARACTER*15000 rather than CHARACTER(*) and that the TRIM was seeing garbage at the end of the string.

When you say that the code "stops execution", what do you mean? Was there an error message?
0 Kudos
Nick2
New Contributor I
848 Views

I saw an error that looks like this:

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

A very peculiar thing is thatmy SQLStmtStrA has an initial value that starts with a funny character (a square).

I also just tried re-defining

character(*) SQLStmtStr

but that didn't help

0 Kudos
Nick2
New Contributor I
848 Views

This gets even more fun!

I also have

character*255 ColStr

and when I call

iRet = SQLBindCol(StmtHndl,int(1,2),1,ColStr,255,0)

that's when my SQLStmtStrA seems to get corrupt.

0 Kudos
Steven_L_Intel1
Employee
848 Views
Do the SQL routines expect the lengths to be passed by value? (And if so, do you have interfaces for them saying so?)
0 Kudos
Nick2
New Contributor I
848 Views

Yes and yes. (Though I tried the last argument by reference, since it wasn't really clear). Does anything stand out from how I wrote my interface? (Microsoft definition of SQLBindCol follows)

C
C see http://msdn2.microsoft.com/en-us/library/ms711010.aspx
C see also ODBC32.lib in notepad
integer(2) function SQLBindCol
& (StatementHandle,ColumnNumber,TargetType,
& TargetValuePtr,BufferLength,StrLen_or_Ind)
CVBASIC UNCOMMENT START
!DEC$ATTRIBUTES C, ALIAS: "_SQLBindCol@24":: SQLBindCol
!DEC$ATTRIBUTES VALUE:: StatementHandle
!DEC$ATTRIBUTES VALUE:: ColumnNumber
!DEC$ATTRIBUTES VALUE:: TargetType
!DEC$ATTRIBUTES REFERENCE:: TargetValuePtr
!DEC$ATTRIBUTES VALUE:: BufferLength
!DEC$ATTRIBUTES VALUE:: StrLen_or_Ind
CVBASIC UNCOMMENT END
integer(4) StatementHandle
integer(2) ColumnNumber
integer(2) TargetType
character(*) TargetValuePtr
integer(4) BufferLength
integer(4) StrLen_or_Ind
end function

SQLRETURN SQLBindCol(
SQLHSTMTStatementHandle,
SQLUSMALLINTColumnNumber,
SQLSMALLINTTargetType,
SQLPOINTERTargetValuePtr,
SQLINTEGERBufferLength,
SQLLEN *StrLen_or_Ind);
0 Kudos
Steven_L_Intel1
Employee
848 Views
Oh my goodness yes. Here's your problem:

!DEC$ATTRIBUTES C, ALIAS: "_SQLBindCol@24":: SQLBindCol

Make this instead:

!DEC$ ATTRIBUTES STDCALL, DECORATE, ALIAS:"SQLBindCol" :: SQLBindCol

You've told ifort to use the C calling convention for a STDCALL routine, which will corrupt the stack on every call. That @24 on the end of the alias is the giveaway that the routine is STDCALL (as all Win32 API routines are.)
0 Kudos
Nick2
New Contributor I
848 Views

Steve, you're Da Man!!!

0 Kudos
Steven_L_Intel1
Employee
848 Views
Make sure you make a similar edit on your other interfaces.
0 Kudos
Reply