For Programmers: Free Programming Magazines  


Home > Archive > Fortran > July 2004 > Mixed Language Character String









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Mixed Language Character String
rih5342

2004-07-08, 8:58 pm


Hi,

I'm using CVF V6.6 and Windows 2000.

I'm having trouble reading a character string returned by a character
function in a CPP DLL.

The CPP header file contains the following line

typedef char *( __stdcall *pDLLVersion )( void );

for which I have written the following interface.

interface
function rtn_DLLVersion()
!DEC$ ATTRIBUTES DLLIMPORT :: rtn_DLLVersion
!DEC$ ATTRIBUTES STDCALL, ALIAS:'_rtn_DLLVersion' :: rtn_DLLVersion
character (len=128) :: rtn_DLLVersion
!DEC$ ATTRIBUTES REFERENCE :: rtn_DLLVersion
end function rtn_DLLVersion
end interface

The same meaningless character string is returned when I call the function
a second time.

Is the length of the character string returned in the string I am
getting?

Is this a binary versus ASCII issue?

Thanks.




Jugoslav Dujic

2004-07-09, 4:00 pm

rih5342 wrote:
| Hi,
|
| I'm using CVF V6.6 and Windows 2000.
|
| I'm having trouble reading a character string returned by a character
| function in a CPP DLL.
|
| The CPP header file contains the following line
|
| typedef char *( __stdcall *pDLLVersion )( void );
|
| for which I have written the following interface.
|
| interface
| function rtn_DLLVersion()
| !DEC$ ATTRIBUTES DLLIMPORT :: rtn_DLLVersion
| !DEC$ ATTRIBUTES STDCALL, ALIAS:'_rtn_DLLVersion' :: rtn_DLLVersion
| character (len=128) :: rtn_DLLVersion
| !DEC$ ATTRIBUTES REFERENCE :: rtn_DLLVersion
| end function rtn_DLLVersion
| end interface
|
| The same meaningless character string is returned when I call the function
| a second time.
|
| Is the length of the character string returned in the string I am
| getting?

I doubt you can bind a C(++) function which returns a char* like that.
Fortran convention for FUNCTIONs which return other than plain vanilla
numeric types is not standardized and varies from compiler to compiler.
I think that CVF will implement the FUNCTION whose interface you
wrote like

void rtn_DLLVersion(char*)

rather than "obvious" char* rtn_DLLVersion(void)

You can verify that if you compile the file containing only the dummy
function rtn_DLLVersion like above, written in Fortran (remove ALIAS
clause), then examine contents of the .obj file via

dumpbin /symmbols rtn_DLLVersion.obj

I bet you will get _rtn_dllversion@4 instead of _rtn_dllversion@0.

So, if you may change C++ source, I suggest rewriting
it to void _rtn_DLLVersion(char*) or (char**) (the former will
have CHARACTER(X), POINTER:: as Fortran equivalent).

If you may not change the source, I think you will have
to use non-standard Cray pointer instead:

interface
function rtn_DLLVersion()
!DEC$ ATTRIBUTES DLLIMPORT :: rtn_DLLVersion
!DEC$ ATTRIBUTES STDCALL, ALIAS:'_rtn_DLLVersion' :: rtn_DLLVersion
integer (INT_PTR_KIND()) :: rtn_DLLVersion
end function rtn_DLLVersion
end interface
character(128):: sVersion; pointer(p_sVersion, sVersion)
...
p_sVersion = rtn_DLLVersion()
write(*,*) sVersion(1 : index(sVersion,char(0))-1)


--
Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

rih5342

2004-07-09, 4:00 pm

This looks promising.

I implemented your suggestion (exactly) and got an access violation during
run time when the code executed the write statement.

I'm no wizard at pointers, so what next?

Thanks.

Jugoslav Dujic

2004-07-10, 4:14 pm

rih5342 wrote:
| This looks promising.
|
| I implemented your suggestion (exactly) and got an access violation during
| run time when the code executed the write statement.

Well, which part of it? I made 3 distinct ones:
1) Change C code to void (char*)
2) Change C code to void (char**)
3) Change Fortran code to use Cray pointer

| I'm no wizard at pointers, so what next?

If it was 3), what's the value of p_sVersion? It shouldn't be
zero, but an address. If it's non-zero, you can open "Memory"
debug window and type "sVersion" there -- does the output look
like the right string with proper termination char(0)?

--
Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

rih5342

2004-07-19, 4:00 pm

Hi Jugoslav,

I was away last w.

I don't have access to the source so I am
limited (as you suspected) to option 3.

p_sVersion = -2147418113

Are there any project settings that influence this?

What next?

Thanks,

Rob

Jugoslav Dujic

2004-07-20, 3:57 am

rih5342 wrote:
| Hi Jugoslav,
|
| I was away last w.
|
| I don't have access to the source so I am
| limited (as you suspected) to option 3.
|
| p_sVersion = -2147418113

Well, let's check out whether this really points to the real thing:

1) Place a breakpoint (F9) at line p_sVersion = rtn_...
2) Debug/Go (F5). Do what is necessary to invoke the call. The
debugger will stop at that line. Step over the line (F10).
3) Open Watch window (Alt+3), and type
p_sVersion,x
in one of its lines. You should get a hex number (-2147418113
evaluates to 0x8000FFFF -- I can't tell whether it's OK or not in
advance; the value may change from call to call).
4) In the Watch window, also type
sVersion
in the next line. Does the string look like function's result?
5) Open "Memory" window (Alt+6) and type "sVersion" there. You
should end up on address 0x8000FFFF. What are contents of first
dozen bytes? Where's the first zero (00) relative to the starting
address?


--
Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

rih5342

2004-07-20, 3:59 pm


Hi Jugoslav,

In the watch windoow, the following values remain the same with repeated
calls. "Undefined address" is the only the character string that appears
for sVersion.

p_sVersion -2147418113
p_sVersion,x #8000FFFF
sVersion Undefined address

In the memory window, sVersion yields

8000FFFF ?? ?? ?? ?? ?? .....
8001001A ?? ?? ?? ?? .....

Am I looking in the right places to fix this?

Thanks,

Rob


Jugoslav Dujic

2004-07-20, 3:59 pm

rih5342 wrote:
| Hi Jugoslav,
|
| In the watch windoow, the following values remain the same with repeated
| calls. "Undefined address" is the only the character string that appears
| for sVersion.
|
| p_sVersion -2147418113
| p_sVersion,x #8000FFFF
| sVersion Undefined address
|
| In the memory window, sVersion yields
|
| 8000FFFF ?? ?? ?? ?? ?? .....
| 8001001A ?? ?? ?? ?? .....
|
| Am I looking in the right places to fix this?

Well -- yes, it's the right place, but I can't see the whole from this
side of usenet :-).

I overlooked that 8000FFFF is NOT a valid address -- valid user's address
space is from 0x00000000 to 0x7FFFFFFF. You can't see in the debugger anything
above it, nor you can refer to anything above that address -- if you try,
you'll get an access violation (on WRITE) (and question marks in the memory
window).

Thus, that means that there's something wrong with C<->Fortran interface...
Still, one thing bugs me: in C++,

typedef char *( __stdcall *pDLLVersion )( void );

declares a pointer to a function with no arguments and return type of char*,
while you seem to call the function "rtn_DllVersion". Could you post some
more code? Any C code snippet regarding usage of rtn_DllVersion? Maybe
we were hunting the wrong issue all the time?

--
Jugoslav
___________
www.geocities.com/jdujic

Please reply to the newsgroup.
You can find my real e-mail on my home page above.

rih5342

2004-07-20, 3:59 pm


Hi Jugoslav,

It's not pretty, but here it is.

Thanks,

Rob

! ========================================
===========
program test_OneWay

use kernel32

! Jugoslav Duric method #3, non-standard Cray pointer
interface
function rtn_DLLVersion()
!DEC$ ATTRIBUTES DLLIMPORT :: rtn_DLLVersion
!DEC$ ATTRIBUTES STDCALL, ALIAS:'_rtn_DLLVersion' :: rtn_DLLVersion
integer (kind=INT_PTR_KIND()) :: rtn_DLLVersion
end function rtn_DLLVersion
end interface

pointer (p1way, i1way)
pointer (q11, rtn_DLLVersion)
pointer(p_sVersion, sVersion)
character(128):: sVersion

logical status

! Locate the dll and load it into memory
p1way = loadlibrary("OneWay(mod1).dll"C)
if (p1way == 0) then
type *, "Error occurred opening OneWay(mod1).dll"
goto 1000
endif

! Set up a pointer to the routine of interest
q11 = getprocaddress(p1way, "DLLVersion"C)
if (q11 == 0) then
type *, "Error finding DLLVersion in OneWay(mod1).dll"
goto 1000
endif

p_sVersion = rtn_DLLVersion()
p_sVersion = rtn_DLLVersion()
p_sVersion = rtn_DLLVersion()

! run time error here
write(*,*) sVersion(1 : index(sVersion,char(0))-1)

status = .false.
status = freelibrary(p1way)
if( .not. status) then
write(*,*) "freelibrary OneWay(mod1).dll status was: ", status
endif

1000 continue

end program test_OneWay
! ========================================
================


Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com