Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Calling Visual Basic DLL from Fortran

Status
Not open for further replies.

Guest_imported

New member
Jan 1, 1970
0
Hello,

I create a simple VB DLL (name: SimpleDLLTest with 2 functions) which looks like:
- ReadInput
- WriteInput(s as String)

I heard somewhere that Fortran now support COM. And since VB DLL are COM object, I am assuming that I can call the SimpleDLLTest in Fortran. When I imported this DLL into Fortran, I see some codes. Please see code below if interested.

My question is with this function:
FUNCTION $$cTest_WriteInput($OBJECT, strInput, $ARG2)

This function seems to be needing the pointer to the object. Question: What is this object and how can I resolved this.

I thank you for your time and response in advance. Hopefully someone can clarify this for me.

My function in VB looks like this for WriteInput (very simple)

Public Function WriteInput(ByVal strValue as String)
WriteInput = strValue
end Function

Cheers.

! simpletest.f90

! This module contains the COM interfaces of the objects defined in
! C:\Projects\fort2vba\SimpleTestDLL.dll
! Generated by the Fortran Module Wizard on 06/25/02

MODULE simpletest
USE DFWINTY
USE DFCOM
IMPLICIT NONE


! CLSIDs
TYPE (GUID), PARAMETER :: CLSID_cTest = &
GUID(#B2E96734, #855C, #11D6, &
CHAR('8C'X)//CHAR('8B'X)//CHAR('00'X)//CHAR('01'X)// &
CHAR('03'X)//CHAR('1C'X)//CHAR('B5'X)//CHAR('32'X))

! IIDs
TYPE (GUID), PARAMETER :: IID__cTest = &
GUID(#B2E967D7, #855C, #11D6, &
CHAR('8C'X)//CHAR('8B'X)//CHAR('00'X)//CHAR('01'X)// &
CHAR('03'X)//CHAR('1C'X)//CHAR('B5'X)//CHAR('32'X))

! Interfaces
INTERFACE
INTEGER*4 FUNCTION $cTest_ReadInput($OBJECT, $ARG1)
INTEGER(INT_PTR_KIND()), INTENT(IN) :: $OBJECT ! Object Pointer
!DEC$ ATTRIBUTES VALUE :: $OBJECT
INTEGER(INT_PTR_KIND()), INTENT(OUT) :: $ARG1 ! BSTR
!DEC$ ATTRIBUTES REFERENCE :: $ARG1
!DEC$ ATTRIBUTES STDCALL :: $cTest_ReadInput
END FUNCTION $cTest_ReadInput
END INTERFACE
POINTER($cTest_ReadInput_PTR, $cTest_ReadInput) ! routine pointer
INTERFACE
INTEGER*4 FUNCTION $cTest_WriteInput($OBJECT, strInput, $ARG2)
USE DFWINTY
INTEGER(INT_PTR_KIND()), INTENT(IN) :: $OBJECT ! Object Pointer
!DEC$ ATTRIBUTES VALUE :: $OBJECT
INTEGER(INT_PTR_KIND()), INTENT(IN) :: strInput ! BSTR
!DEC$ ATTRIBUTES VALUE :: strInput
TYPE (VARIANT), INTENT(OUT) :: $ARG2
!DEC$ ATTRIBUTES REFERENCE :: $ARG2
!DEC$ ATTRIBUTES STDCALL :: $cTest_WriteInput
END FUNCTION $cTest_WriteInput
END INTERFACE
POINTER($cTest_WriteInput_PTR, $cTest_WriteInput) ! routine pointer


! Module Procedures
CONTAINS
INTEGER*4 FUNCTION $$cTest_ReadInput($OBJECT, $ARG1)
!DEC$ ATTRIBUTES DLLEXPORT :: $$cTest_ReadInput
IMPLICIT NONE

INTEGER(INT_PTR_KIND()), INTENT(IN) :: $OBJECT ! Object Pointer
!DEC$ ATTRIBUTES VALUE :: $OBJECT
CHARACTER*(*), INTENT(OUT) :: $ARG1 ! BSTR
!DEC$ ATTRIBUTES REFERENCE :: $ARG1
INTEGER*4 $RETURN
INTEGER(INT_PTR_KIND()) $VTBL ! Interface Function Table
POINTER($VPTR, $VTBL)
INTEGER(INT_PTR_KIND()) $BSTR_$ARG1 ! BSTR
INTEGER*4 $STATUS
$VPTR = $OBJECT ! Interface Function Table
$VPTR = $VTBL + 32 ! Add routine table offset
$cTest_ReadInput_PTR = $VTBL
$RETURN = $cTest_ReadInput($OBJECT, $BSTR_$ARG1)
$STATUS = ConvertBSTRToString($BSTR_$ARG1, $ARG1)
CALL SysFreeString($BSTR_$ARG1)
$$cTest_ReadInput = $RETURN
END FUNCTION $$cTest_ReadInput
INTEGER*4 FUNCTION $$cTest_WriteInput($OBJECT, strInput, $ARG2)
!DEC$ ATTRIBUTES DLLEXPORT :: $$cTest_WriteInput
IMPLICIT NONE

INTEGER(INT_PTR_KIND()), INTENT(IN) :: $OBJECT ! Object Pointer
!DEC$ ATTRIBUTES VALUE :: $OBJECT
CHARACTER*(*), INTENT(IN) :: strInput ! BSTR
!DEC$ ATTRIBUTES REFERENCE :: strInput
TYPE (VARIANT), INTENT(OUT) :: $ARG2
!DEC$ ATTRIBUTES REFERENCE :: $ARG2
INTEGER*4 $RETURN
INTEGER(INT_PTR_KIND()) $VTBL ! Interface Function Table
POINTER($VPTR, $VTBL)
INTEGER(INT_PTR_KIND()) $BSTR_strInput ! BSTR
$BSTR_strInput = ConvertStringToBSTR(strInput)
$VPTR = $OBJECT ! Interface Function Table
$VPTR = $VTBL + 28 ! Add routine table offset
$cTest_WriteInput_PTR = $VTBL
$RETURN = $cTest_WriteInput($OBJECT, $BSTR_strInput, $ARG2)
CALL SysFreeString($BSTR_strInput)
$$cTest_WriteInput = $RETURN
END FUNCTION $$cTest_WriteInput
END MODULE

 
First, I think that if you have used the Fortran module Wizard to generate the interface module, you do not have chosen the right option (you need to use "Type library containing Automation information" rather than "Type library containing COM interface information"). This will generate a module source slightly different (keep trace of the CLSID_cTest and IID_cTest type definitions as they could be missing in the newer module). In order to use this COM DLL you need first to initialize COM communication by calling COMInitialize() function and then you need to create an object implementing your interface (call COMCreateObjectFromGUID()) and then you can call your routines.

let's see:

[tt] integer(4) status, iTest

call COMInitialize(status)
call COMCreateObjectByGUID(CLSID_cTest, CLSCTX_ALL, &
IID_cTest, iTest, status)
i1 = Test_ReadInput(iTest, status)
i2 = Test_WriteInput(iTest, 'Test string', status)

status = COMReleaseObject(iTest)
call COMUninitialize()
[/tt]

If this don't work, I think that the solution is not so far (I have personaly experienced this with success for calling Delphi COM Dlls). Don't forget to register your DLL before trying your executable (DLLRegsiterServer,.....)

have fun ;-)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top