Page 1 of 1

Calling external functions

Posted: Wed Mar 19, 2008 5:51 pm
by Capella
Hi!

I have DLL (compiled in C for Windows) with functions that I want to use.
Many of the functions have parameters as Double and also returns Double. Some functions also returns Arrays of Doubles.

As I understand it, I have to use "Prototype" to access these function, since the normal way of handling DLL's cannot handle Float or Double.

My question now, is PureBasic able to handle this?

If so, any sample code is apprecited based on the following Visual Basic declaration of one such function:

Declare Function calculate Lib "calc32.dll" _
Alias "_calc@24" ( _
ByVal tjd As Double, _
ByVal ipl As Long, _
ByVal iflag As Long, _
ByRef x As Double, _
ByVal serr As String _
) As Long

Note: The variable x above of the parameters is returning an array of 6 different numbers as doubles, similar to x(6) as Double in VB.

Re: Calling external functions

Posted: Thu Mar 20, 2008 1:44 pm
by tinman
Capella wrote:My question now, is PureBasic able to handle this?
Yes. Or at least, it should be. You might also be able to import the functions directly rather than having to use prototypes, I'm not sure if imported functions have the same limitations as CallFunctionFast() etc.

I'm not sure about the string parameter.

Code: Select all

Import "calc32.lib"
    calculate.l(tjd.d, ipl.d, iflag.l, *x.d, serr.s) As calc
EndImport

Dim real_x.d(6)
calculate(1, 2, 3, @real_x(0), "foo")

Posted: Mon Mar 24, 2008 8:19 pm
by Trond
PB can't handle returning array of double. I didn't even know you could do that in C.

Posted: Tue Mar 25, 2008 11:09 am
by walker
isn't

Code: Select all

 ByRef x As Double, _ 
simply a pointer to that array?

Functions returning array of double

Posted: Tue Mar 25, 2008 11:32 am
by Capella
It can be done in C and it can be done Visual Basic, so I don't understand why PureBasic cannot handle this - returning an array of doubles from an external function call.

I had the impression that PB would be a more sophisticated language than VB, but apparently not. Or?

Is this a problem with external functions only, or is this a problem with "normal" functions calls as well? I have the C so source code, so I could re-compile the function to use additional parameters instead of an array. But I prefer not, as I then also have to make other changes as well.

Posted: Tue Mar 25, 2008 11:36 am
by Trond
Actually, that VB code does not return an array of doubles. It returns a long. PB can handle that VB function just fine.

Returning arrays of long

Posted: Tue Mar 25, 2008 12:03 pm
by Capella
Yes, the return value is a long, which in this case is a value to control if the calculations within the functions was done correctly or not.

However, I must also be able to read some of the parameters (here delcared as Global), which have been calculated within the function, and especially the array (the 4th parameter containing the array of calculated data, and the 5th parameter which contains any error message).

In PB I have written it like this (a short sample)...

Note: I've manage to create a static "lib" out from the "dll", so I first import that, then use prototypes in order to be able to use doubles, and pointers to the functions to simplify the coding thereafter...

;-------------------------------------------------------------
Import "calc32.lib"
calc32 (a.d, b.l, c.l, d.d, e.s) As "_calc@32"
EndImport
Prototype.l FunctionC (a.d, b.l, c.l, d.d, e.s, f.l=1)
*PointerC.FunctionC=@calc32()

jd.d = 2436858.58333
no.l = 0
flg.l = 512
Global Dim pos.d(6)
Global erro.s = ""

ret.l = *PointerC (jd.d, no.l, flg.l, @pos.d, erro.s);

OpenConsole()
PrintN (StrD (pos.d(1))
CloseConsole()
;----------------------------------------------------

Posted: Tue Mar 25, 2008 1:26 pm
by Trond
There are some errors in your code.

- If you use import you don't need the prototypes.
- "ByRef x As Double" is a POINTER to a double, you declared it as a double.
- You used "As "_calc@32"", but the original definition uses @24. PB can even figure out this by itself, so you don't need it.
- You send @pos.d, which is the address of the double variable "pos". That is a completely different variable than the array pos().
- Pos(6) has 7 elements, from 0 to 6. You only need 6.
- You print Pos(1) as the first element, but the first element is Pos(0)