Home > Archive > Fortran > December 2005 > Re: Mystery with passing a function reference through the argument
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 |
Re: Mystery with passing a function reference through the argument
|
|
| R. MacDonald 2005-12-15, 3:58 am |
| My sincere apologies to all who might have tried to read my "synopsis"
of sample code. It was obviously much too late last night and I was in
"panic mode" when I placed my note. The "synopsis" was my attempt to
extract and simplify the essence of the problem from my test code that
had become overburdened with unnecessary and obsolete lines of code.
Please find below this morning's complete trimmed-down version, which
will actually compile and run to produce the log file shown at the end.
========================================
==================
=====vvvv==== Start of Tester.f90 Source file ====vvvv====
Integer Function Tester( DataCallBack, Message)
!DEC$ ATTRIBUTES DLLEXPORT:: Tester
Use DFCOM ! Declare SafeArray and BSTR interfaces
Implicit None
Integer DataCallBack ! Pointer to call-back function.
Integer Message ! Pointer to message BStr.
Integer CBInit ! Initialization function.
Integer iStatus
Open (Unit=1, File='J:\Tester\Tester.log', IOSTAT=iStatus)
If (iStatus .NE. 0) Then
Tester = iStatus
Message = ConvertStringToBSTR ('Failed to open log file! ')
Return
End If
Write (1,*) 'In Tester: DataCallBack = ', DataCallBack
iStatus = CBInit(DataCallBack)
Write (1,*) 'In Tester: CBInit completed, iStatus = ', iStatus
Tester = iStatus
If (iStatus .NE. 0) Then
Message = ConvertStringToBSTR ('Tester init failed! ')
End If
End Function
Integer Function CBInit(DataCallBack)
Use VBInterface ! Declare GlobalDataCB
Integer DataCallBack ! "Pointer" to call-back function
Integer ReadData ! Sample data access function.
Integer iptSafeArray ! Pointer to SafeArray.
GlobalDataCB = DataCallBack
CBInit = ReadData(DataCallBack, 'Read test', iptSafeArray)
End Function
Integer Function ReadData(ptrCallBack, Request, Result)
Use VBInterface
Interface
Integer Function ptrCallBack(Request, iptData)
Character*32 Request
Integer iptData
End Function ptrCallBack
End Interface
Character*(*), Intent(In) :: Request
Integer, Intent(InOut) :: Result ! Pointer to SafeArray.
Integer iStatus
Integer VBCallBack ! Fortran Routine to invoke VB call-back.
! This call to VBCallBack will succeed.
Call WriteLog('In readData: ptrCallBack = ', ptrCallBack)
iStatus = VBCallBack(ptrCallBack, Request, Result)
Call WriteLog('In readData: 1st call, iStatus = ', iStatus)
! This call to VBCallBack will fail.
Call WriteLog('In readData: GlobalDataCB = ', GlobalDataCB)
iStatus = VBCallBack(GlobalDataCB, Request, Result)
Call WriteLog('In readData: 2nd call, iStatus = ', iStatus)
ReadData = iStatus
End Function
Integer Function VBCallBack(ptrCallBack, Request, Result)
Interface
Integer Function ptrCallBack(Request, iptData)
Character*32 Request
Integer iptData
End Function ptrCallBack
End Interface
Character*(*), Intent(In) :: Request
Integer, Intent(InOut) :: Result ! Pointer to SafeArray.
! Get the requested data from the VB.Net application.
! (If VBCallBack is invoked with ptrCallBack=GlobalDataCB
! this call fails . VB reports a NullReferenceException.)
VBCallBack = ptrCallBack(Request, Result)
End Function
Subroutine WriteLog(Message, Value)
Character*(*) Message
Integer Value
Write (1,*) Message, Value
End Subroutine
=====^^^^===== End of Tester.f90 Source file =====^^^^====
========================================
==================
The Module definition is provided in the file VBInterface.f90 shown below:
========================================
==================
===vvvv=== Start of VBInterface.f90 Source file ===vvvv===
Module VBInterface
Implicit None
Integer, Save, Public :: GlobalDataCB ! Call-back ptr.
End Module VBInterface
===^^^^==== End of VBInterface.f90 Source file ====^^^^===
========================================
==================
Then finally, the log file output:
========================================
==================
======vvvv====== Start of Tester.log file ======vvvv======
In Tester: DataCallBack = -1778919240
In readData: ptrCallBack = -1778919240
In readData: 1st call, iStatus = 4
In readData: GlobalDataCB = -1778919240
======^^^^======= End of Tester.log file =======^^^^======
========================================
==================
So, what's the secret of the difference between these two calls?
Cheers,
Randy
| |
| R. MacDonald 2005-12-15, 7:57 am |
| Hello, Group,
Thanks to any who were giving my problem their consideration. I have
finally found the solution.
It appears that it is a problem with how the call-back reference is
passed. I had thought what I was receiving a pointer from VB.Net whose
value was the address that I wanted. I guess that it is actually the
address itself that is being passed.
So the solution is to store the address of the argument in my global
variable, not its value. I can then pass this by value into VBCallBack,
and the VB.Net world is happy again.
Cheers,
Randy
|
|
|
|
|