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

.NET string inside Fortran

Rudy__Delcroit
Beginner
339 Views
Dear Fortran Guru,

I'm trying to run a .NET assembly from fortran. However,it crashes with 'blabla has triggered a breakpoint.' when calling the assembly. I know that the assembly and COM wrapper is working because it works from VB6.

Here I suspect that my string definition is not correct. Probably a story about pointer ?

Here are the code ..


------- VB 6 Working Code ---------------
Set o = CreateObject("My.Library")
MsgBox (o.Version) <= o.version is a string
---------- End of Code --------------------


------------- Fortran Not Working Code ---------
integer(4) status,Obj
CHARACTER(300) CofVersion

call COMInitialize(status)
call COMCreateObject("My.Library", Obj, status) <= Obj is not null
status = $ILibrary_GetVersion(Obj, CofVersion)
------------- End of Code --------------------------

-----------Mod Wizard Generated Code ----------
INTEGER(4) FUNCTION $ILibrary_GetVersion($OBJECT, pRetVal)
IMPLICIT NONE
INTEGER(INT_PTR_KIND()), INTENT(IN) :: $OBJECT ! Object Pointer
!DEC$ ATTRIBUTES VALUE :: $OBJECT
CHARACTER(LEN=*), INTENT(OUT) :: pRetVal ! BSTR
INTEGER(4) $RETURN
INTEGER(INT_PTR_KIND()) $VTBL ! Interface Function Table
POINTER($VPTR, $VTBL)
INTEGER(INT_PTR_KIND()) $BSTR_pRetVal ! BSTR
INTEGER(4) $STATUS
$BSTR_pRetVal = NULL
$VPTR = $OBJECT ! Interface Function Table
$VPTR = $VTBL + 60 ! Add routine table offset
ILibrary_GetVersion_PTR = $VTBL
$RETURN = ILibrary_GetVersion($OBJECT, $BSTR_pRetVal) <= Crashes
$STATUS = ConvertBSTRToString($BSTR_pRetVal, pRetVal)
CALL SysFreeString($BSTR_pRetVal)
$ILibrary_GetVersion = $RETURN
END FUNCTION $ILibrary_GetVersion


INTERFACE
INTEGER(4) FUNCTION ILibrary_GetVersion($OBJECT, pRetVal)
INTEGER(INT_PTR_KIND()), INTENT(IN) :: $OBJECT ! Object Pointer
!DEC$ ATTRIBUTES VALUE :: $OBJECT
INTEGER(INT_PTR_KIND()), INTENT(OUT) :: pRetVal ! BSTR
!DEC$ ATTRIBUTES REFERENCE :: pRetVal
!DEC$ ATTRIBUTES STDCALL :: ILibrary_GetVersion
END FUNCTION ILibrary_GetVersion
END INTERFACE
POINTER(ILibrary_GetVersion_PTR, ILibrary_GetVersion) ! routine pointer

------------- End of Code -----------------------------

Any help would be greatly appraciated.

Regards,
Vincent

0 Kudos
5 Replies
anthonyrichards
New Contributor III
339 Views
Do you get an error message to the effect

"Invalid address specified RtlFreeHeap(00150000, 001644c8)" ?
If so, welcome to the club. I have posted a similar problem recently about accessing a couple of the COMDLG32.OCX methods using the same Module Wizrd approach. In my case it would seem somewhere a DLL is using a run-time library routine to release a heap created by another dll or thread and using the wrong pointer.
0 Kudos
JohnNichols
Valued Contributor III
339 Views
I have been reading on calling NET Assemblies from inside FORTRAN. So as an aside would it not be possible to add a C++ routine that does the net assembly calls. Seems to be a lot less hassle. I am going to try it today, as I have to be able to get my analysed data into a database easily.

I had a look at the Modules generated by the FORTRAN wizard and that is an interesting bowl of spaghetti.

Steve: Another issue with the FORTRAN help files. The tools menu has a sub menu called Intel etc, below this submenu is a single element the Fortran Wizard. The help files show it at the higher level making it easy to find, you had me stumped for about a minute, while I tried to find the wizard.

JMN


0 Kudos
JohnNichols
Valued Contributor III
339 Views
I copied the code to initialize into my CX1Reader4 program and it worked, using debug I got a status of zero, which I assume is ok as the help files are less than helpful on the return values, but the code shown in the helpful continues to run with a status of 0.

I am not able to continue testing unless we are looking at the same object. Can we get some sort of dummy object that we can all use to see what the problems are?

JMN
0 Kudos
Steven_L_Intel1
Employee
339 Views
John,

Your comment on the help has been passed on to the writers.
0 Kudos
jeremy_h
New Contributor I
339 Views
A slightly different problem, but it took me a couple days of fiddling to get vb.net to call Fortran or even Windows API. Until I got it working, calls would crash completely, untrappable, with no help, even in the debugger. The trick was to use the Marshal package.

It was a real eye-opener that strings declared in Microsoft vb.net were crashing during Microsoft Windows calls! But the .net managed memory is completely different and very strange.

For instance, the OpenPrinterW call from vb.net looks like this:
[vb]Public Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterW" (ByVal pPrinterName As System.IntPtr, ByRef phPrinter As System.IntPtr, ByVal pDefault As Integer) As Integer

Dim printerNamePtr As IntPtr = Marshal.StringToHGlobalUni(strRequestedPrinter)

result = OpenPrinter(printerNamePtr, hPrinter, 0)[/vb]
I'm guessing that returning from Windows API or Fortran to .net managed memory requires this to be undone. Can't say for sure but you can judge whether it is worth looking at. Don't forget that most .net strings are unicode, whereas Fortran strings are not unless you deliberately convert them.
0 Kudos
Reply