- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am rewriting a large application moving from VB6 using FORTRAN executables, to VB.NET using FORTRAN DLL's.
I am able to move single values and arrays both to and from the DLL, but now have gotten stuck trying to push strings.
Here is the relevant VB.NET code:
In the declarations section:
<UnmanagedFunctionPointer(CallingConvention.StdCall)> Private Delegate Sub pushString(ByRef varIndex As Short, ByVal MsgString As StringBuilder) Dim EntryPointer As IntPtr = NativeMethods.LoadLibrary(EXE_DLL_filename) FunctionPointer = NativeMethods.GetProcAddress(EntryPointer, "pushString") Dim pushString As pushString = CType(Marshal.GetDelegateForFunctionPointer(FunctionPointer, GetType(pushString)), pushString)
Executable code:
Dim index As Short = 501 Dim filePath As String = "C:\Users\mark.ARROWTECH\AppData\Local\Temp\tmpD33F.tmp" Dim strMessage As StringBuilder = New StringBuilder(filePath, 120) pushString(index, strMessage)
The DLL that I link to is only known at runtime.
Relevant FORTRAN code:
!dec$ attributes dllexport, CVF, alias : 'pushString' :: pushString SUBROUTINE pushString(varIndex, InputString ) use, intrinsic :: ISO_C_BINDING USE Traj20006D_Global_Export integer(2), intent(in) :: varIndex CHARACTER(KIND=C_CHAR,LEN=1), INTENT(in) :: InputString(*) INTEGER :: StringLen INTEGER :: I !.. Determine input string length; check for null-termination StringLen = 0 Loop_SizeVec: DO ! IF (InputString(StringLen+1) == C_NULL_CHAR) THEN EXIT Loop_SizeVec End If StringLen = StringLen + 1 IF (StringLen == 2048) THEN !.. Replace: arbitrary large length EXIT Loop_SizeVec END IF END DO Loop_SizeVec IF (StringLen == 0) RETURN select case(varIndex) Case (501) FORALL (I = 1:StringLen) !.. Copy string TEXTFILE1(I:I) = InputString(I)(1:1) END FORALL Case (502) FORALL (I = 1:StringLen) !.. Copy string TEXTFILE2(I:I) = InputString(I)(1:1) END FORALL End Select Return END SUBROUTINE pushString
So what happens is the string is transferred fine, but on leaving the routine I get this error:
"Additional information: A call to PInvoke function 'PRODASV4!PRODASV4.prodasTask+pushString::Invoke' has unbalanced the stack. "
I am just not sure what to try next.
Thanks,
Mark
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My hunch, based on a very quick glance at your code, is your problem is !DEC$ ATTRIBUTES specification of CVF. You may want to:
- Simply specify DEC$ ATTRIBUTES DLLEXPORT::pushString
- have the procedure declaration as
SUBROUTINE
pushString(varIndex, InputString ) BIND (C, Name="pushString")
See this thread:
https://software.intel.com/en-us/forums/topic/509148.
My suggestion would be that if you are going to do mixed-language solution development, make full use of C interoperability features in Fortran via ISO_C_BINDING. Look into all the data types e.g., Short in Visual Basic vis-a-vis C_SHORT in ISO_C_BINDING; review all the procedure interop aspects relative to BIND keyword, etc. And avoid "mixed mode" that you have currently, where you make part use of ISO_C_BINDING and mix it with Intel Fortran extensions of !DEC$ attributes. Mixed types (e.g., INTEGER(2)) may also cause problems.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My hunch, based on a very quick glance at your code, is your problem is !DEC$ ATTRIBUTES specification of CVF. You may want to:
- Simply specify DEC$ ATTRIBUTES DLLEXPORT::pushString
- have the procedure declaration as
SUBROUTINE
pushString(varIndex, InputString ) BIND (C, Name="pushString")
See this thread:
https://software.intel.com/en-us/forums/topic/509148.
My suggestion would be that if you are going to do mixed-language solution development, make full use of C interoperability features in Fortran via ISO_C_BINDING. Look into all the data types e.g., Short in Visual Basic vis-a-vis C_SHORT in ISO_C_BINDING; review all the procedure interop aspects relative to BIND keyword, etc. And avoid "mixed mode" that you have currently, where you make part use of ISO_C_BINDING and mix it with Intel Fortran extensions of !DEC$ attributes. Mixed types (e.g., INTEGER(2)) may also cause problems.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the quick response.
I modified my FORTRAN per your suggestions, and also cleaned up the data types. In addition, I changed the calling convention from STDCALL to CDECL in the VB.NET code.
Works like a champ,
Thanks again

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page