Page 1 of 1

Passing of variable to DLL not taking place

Posted: Wed Jun 01, 2016 10:14 am
by Blurryan
Below is the DLL file, compiled as "Astro2_0.dll: and the second file is the calling program. The third file is a normal function call inside a normal program.

The function computes the Julian Day. The function takes 3 variables, day as double, and month and year as integers. In calling the DLL, the day is not being passed, but in the normal function call the program is smooth.

Results of both are given below the code.

Can someone point out where I am going wrong? I would prefer not to use a Prototype.

Astro2_0.dll code

Code: Select all

Global JulD.d

ProcedureDLL.d JulianDay(d1.d, m.i, y.i)
    Protected a.i, b.i, dd.d, mm.i, yy.i
    dd = d1: mm = m: yy = y
    If yy > 1582: GJ = "G": EndIf
    If yy < 1582: GJ = "J": EndIf
    If yy = 1582
        If mm > 10: GJ = "G": EndIf
        If mm < 10: GJ = "J": EndIf
        If mm = 10
            If dd > 14: GJ = "G": EndIf
            If dd < 5 : GJ = "J": EndIf
        EndIf
    EndIf
    If mm > 2: mm = mm + 0: yy = yy + 0: ElseIf mm = 1 Or mm = 2: yy = yy - 1: mm = mm + 12: EndIf
    a = Int(yy / 100)
    If GJ = "J": b = 0: Else: b = 2 - a + Int(a / 4): EndIf
    JulD = Int(365.25 * (yy + 4716)) + Int(30.6001 * (mm + 1)) + dd + b - 1524.5
    ProcedureReturn @JulD
EndProcedure
DLL Calling program - with results of the call. Notice May 15th and 31st and June 15th and 30th are same figures, so effectively ignoring day value.

Code: Select all

If OpenLibrary(0, "Astro2_0.dll")
   Debug "01/01/0001 - " + StrD(PeekD(CallFunction(0, "JulianDay", 1.0, 1, 1)), 1)      ;1721423.5 - 1721422.5
   Debug "30/04/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", 30.0, 4, 2016)), 1)  ;2457508.5 - 2457478.5
   Debug "15/05/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", 15.0, 5, 2016)), 1)  ;2457523.5 - 2457508.5
   Debug "31/05/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", 31.0, 5, 2016)), 1)  ;2457539.5 - 2457508.5
   Debug "15/06/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", 15.0, 6, 2016)), 1)  ;2457554.5 - 2457539.5
   Debug "30/06/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", 30.0, 6, 2016)), 1)  ;2457569.5 - 2457539.5
Else
    MessageRequester("ERROR", "Can't open Library Astro2_0", #PB_MessageRequester_Ok)
EndIf
CloseLibrary(0)

; Results of the above Call are:
; 
; 01/01/0001 - 1721422.5
; 30/04/2016 - 2457478.5
; 15/05/2016 - 2457508.5
; 31/05/2016 - 2457508.5
; 15/06/2016 - 2457539.5
; 30/06/2016 - 2457539.5
Normal program with internal function - results are below the code.

Code: Select all

Procedure.d JulianDay(d.d, m.i, y.i)
    Protected a.i, b.i
    If y > 1582: GJ.s = "G": EndIf
    If y < 1582: GJ = "J": EndIf
    If y = 1582
        If m > 10: GJ = "G": EndIf
        If m < 10: GJ = "J": EndIf
        If m = 10
            If d > 14: GJ = "G": EndIf
            If d < 5 : GJ = "J": EndIf
        EndIf
    EndIf
    If m > 2: m = m + 0: y = y + 0: ElseIf m = 1 Or m = 2: y = y - 1: m = m + 12: EndIf
    a = Int(y / 100)
    If GJ = "J": b = 0: Else: b = 2 - a + Int(a / 4): EndIf
    dd = d+h/24+i/24/60+s/24/3600
    JulD.d = Int(365.25 * (y + 4716)) + Int(30.6001 * (m + 1)) + Int(d) + b - 1524.5
    ProcedureReturn JulD
EndProcedure

a1.d = JulianDay(1.0, 1, 1)
b1.d = JulianDay(30.0, 4, 2016)
c1.d = JulianDay(15.0, 5, 2016)
d1.d = JulianDay(31.0, 5, 2016)
e1.d = JulianDay(15.0, 6, 2016)
f1.d = JulianDay(30.0, 6, 2016)

Debug "01/01/0001 - " + StrD(a1, 1)
Debug "30/04/2016 - " + StrD(b1, 1) + " - " + StrD(b1-a1, 0)
Debug "15/05/2016 - " + StrD(c1, 1) + " - " + StrD(c1-b1, 0)
Debug "31/05/2016 - " + StrD(d1, 1) + " - " + StrD(d1-c1, 0)
Debug "15/06/2016 - " + StrD(e1, 1) + " - " + StrD(e1-d1, 0)
Debug "30/06/2016 - " + StrD(f1, 1) + " - " + StrD(f1-e1, 0)

; Results of the above Call are:
; 
; 01/01/0001 - 1721423.5
; 30/04/2016 - 2457508.5 - 736085
; 15/05/2016 - 2457523.5 - 15
; 31/05/2016 - 2457539.5 - 16
; 15/06/2016 - 2457554.5 - 15
; 30/06/2016 - 2457569.5 - 15

Re: Passing of variable to DLL not taking place (Solved) but

Posted: Wed Jun 01, 2016 10:37 am
by Blurryan
Ok. I think I understood. I need to pass a pointer to the DLL from the calling program.

Can someone vet if this is correct or is there something more to it?

Calling program for DLL as changed

Code: Select all

If OpenLibrary(0, "Astro2_0.dll")
    x.d = 1: y.d = 15: z.d = 30: zz.d = 31
   Debug "01/01/0001 - " + StrD(PeekD(CallFunction(0, "JulianDay", @x, 1, 1)), 1)      ;1721423.5 - 1721422.5
   Debug "30/04/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", @z, 4, 2016)), 1)  ;2457508.5 - 2457478.5
   Debug "15/05/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", @y, 5, 2016)), 1)  ;2457523.5 - 2457508.5
   Debug "31/05/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", @zz, 5, 2016)), 1)  ;2457539.5 - 2457508.5
   Debug "15/06/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", @y, 6, 2016)), 1)  ;2457554.5 - 2457539.5
   Debug "30/06/2016 - " + StrD(PeekD(CallFunction(0, "JulianDay", @z, 6, 2016)), 1)  ;2457569.5 - 2457539.5
Else
    MessageRequester("ERROR", "Can't open Library Astro2_0", #PB_MessageRequester_Ok)
EndIf
CloseLibrary(0)

; Results of the above Call are: (PREVIOUSLY)
; 
; 01/01/0001 - 1721422.5
; 30/04/2016 - 2457478.5
; 15/05/2016 - 2457508.5
; 31/05/2016 - 2457508.5
; 15/06/2016 - 2457539.5
; 30/06/2016 - 2457539.5

; Results of the above Call are: (AFTER CHANGE)
; 
; 01/01/0001 - 1721423.5
; 30/04/2016 - 2457508.5
; 15/05/2016 - 2457523.5
; 31/05/2016 - 2457539.5
; 15/06/2016 - 2457554.5
; 30/06/2016 - 2457569.5

Re: Passing of variable to DLL not taking place

Posted: Wed Jun 01, 2016 11:05 am
by DontTalkToMe
I have to say: what a mess.

1. The code you posted for the DLL does not work as you posted it, cannot even be compiled.
GJ = "G" ???

2. About the last "fixed" code, if you pass a value as a pointer that requires changes in the DLL function, you didn't post the updated version of it so your question "is it ok now ?" cannot be answered.

3. CallFunction cannot return float/double nor pass them, so yes one way (not the only one) to solve the problem is to return a pointer to a global double and to pass pointers to doubles if that's really what you want. So let's say that's OK.

4. The proper way to do this is through prototypes, resulting in a clean and understandable code perfectly equivalent to the code you used in the example without the DLL. Why you are against them ? Certainly not because they are complicated. Not compared to this. If you would like an example of using them let us know.

Re: Passing of variable to DLL not taking place

Posted: Wed Jun 01, 2016 11:16 am
by Blurryan
Thanks @DontTalkToMe.

I was checking out what is the alternative to not using Prototypes.

Being not a very good programmer possibly the mess.

With prototypes although things become "neater", the length of a statement becomes huge when there are many variables being passed and becomes difficult to track the variables.

Re: Passing of variable to DLL not taking place

Posted: Wed Jun 01, 2016 11:27 am
by DontTalkToMe
If you still want to avoid prototypes you could just pass to your proc a single pointer to a structure with all your data packed in that, both the input and output (or returned data).

At least you don't have all those peek/poke stuff and you can read and write doubles directly.

Personally I think it's still better and easy to manage than this.

Re: Passing of variable to DLL not taking place

Posted: Wed Jun 01, 2016 11:46 am
by Blurryan
Noted, thanks.

Re: Passing of variable to DLL not taking place

Posted: Wed Jun 01, 2016 12:06 pm
by DontTalkToMe
In any case, even if you are not gonna to use it, example on how using prototypes makes it more clear:

Code: Select all

; DLL.PB

EnableExplicit

ProcedureDLL.d JulianDay (d1.d, m.i, y.i)
    Protected a.i, b.i, dd.d, mm.i, yy.i, JulD.d
    Protected GJ$    
    dd = d1: mm = m: yy = y
    If yy > 1582: GJ$ = "G": EndIf
    If yy < 1582: GJ$ = "J": EndIf
    If yy = 1582
        If mm > 10: GJ$ = "G": EndIf
        If mm < 10: GJ$ = "J": EndIf
        If mm = 10
            If dd > 14: GJ$ = "G": EndIf
            If dd < 5 : GJ$ = "J": EndIf
        EndIf
    EndIf
    If mm > 2: mm = mm + 0: yy = yy + 0: ElseIf mm = 1 Or mm = 2: yy = yy - 1: mm = mm + 12: EndIf
    a = Int(yy / 100)
    If GJ$ = "J": b = 0: Else: b = 2 - a + Int(a / 4): EndIf
    JulD = Int(365.25 * (yy + 4716)) + Int(30.6001 * (mm + 1)) + dd + b - 1524.5
    ProcedureReturn JulD
EndProcedure

Code: Select all

; CLIENT.PB

EnableExplicit

Prototype.d JulianDay (d1.d, m.i, y.i) : Global JulianDay.JulianDay 

If OpenLibrary(0, "dll.dll")
    JulianDay = GetFunction(0, "JulianDay")
    
    Global x.d = 1, y.d = 15, z.d = 30, zz.d = 31
    
    Debug "01/01/0001 - " + JulianDay(x, 1, 1)     ;1721423.5 
    Debug "30/04/2016 - " + JulianDay(z, 4, 2016)  ;2457508.5 
    Debug "15/05/2016 - " + JulianDay(y, 5, 2016)  ;2457523.5 
    Debug "31/05/2016 - " + JulianDay(zz, 5, 2016) ;2457539.5 
    Debug "15/06/2016 - " + JulianDay(y, 6, 2016)  ;2457554.5 
    Debug "30/06/2016 - " + JulianDay(z, 6, 2016)  ;2457569.5 
Else
    MessageRequester("ERROR", "Can't open Library Astro2_0", #PB_MessageRequester_Ok)
EndIf
CloseLibrary(0)

Re: Passing of variable to DLL not taking place

Posted: Fri Jun 03, 2016 9:26 am
by Blurryan
Thanks DontTalkToMe for the Prototype example.

In some functions I am getting into about 12 to 15 variables and using Prototypes gets us all confused.

Let me work out a better example on my prototype "issue" and post it to the forum in the next week, so that you may have a look and suggest better procedure.

Am travelling and hence the delayed response