For Programmers: Free Programming Magazines  


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

Sponsored Links







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

Copyright 2008 codecomments.com