Callback help

Mac OSX specific forum
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Callback help

Post by simberr »

I am in the process of writing a MAC OS dylib in PB and I have a need to operate a callback procedure within the dylib.

I have created my dylib and have found that passing parameters back to the calling program is problematic, but in a specific way.

I have procedures that will call various routines back in the main app. They will pass parameters to the callback routines that are Strings, Integers or Doubles.

In my testing I have found that I can easily and correctly send strings back to my calling program. However, when I send an Integer or a Double back to my calling program the program crashes.

Whilst I can currently get around the problem by always sending a string back and converting that string to an integer or a double in the calling program I would like to determine what it is I am doing wrong to not be able to send numeric values back to the calling program.

An example from my testing code:

Code: Select all

Prototype DoInteger(msg.s)    ; An Integer function (delegate)

Procedure CallInteger(ms.i)
  
  If *cbint
    callint.DoInteger = *cbint
    callint(ms)
  EndIf

EndProcedure
This just crashes upon the callback.

Help, please.
User avatar
NicTheQuick
Addict
Addict
Posts: 1224
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Callback help

Post by NicTheQuick »

Maybe you need PrototypeC or ProcedureC? Are the calling program and the dylib both programmed in Purebasic?
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Callback help

Post by simberr »

Ahhh, I will try that.

The dylib is in PB, the calling program is not PB.

Simon.
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Callback help

Post by simberr »

PrototypeC did not work.

Pity.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Callback help

Post by wilbert »

What calling convention does the main app use ?
You have to make sure the callback is called using the right calling convention.
Windows (x64)
Raspberry Pi OS (Arm64)
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Callback help

Post by simberr »

I don't really know. The main app is compiled with Xojo (another OO Basic implementation). I have found that producing dylibs I have the best results when I compile my PB dylib with the ProcedureCDLL rather than ProcedureDLL.

I have tries both Prototype and PrototypeC in defining my prototypes.

The calling convention is to have a setup, my example is thus:

Code: Select all

; DLL Callbacks
ProcedureCDLL SetCallbacks(*cStr, *cDbl, *cInt)

  *cbstr = *cStr
  *cbdbl = *cDbl
  *cbint = *cInt

  CallString("This is my å∂ƒ©˙∆˚¬…æ test string and I will add a number of lines to it.")
  CallInteger(1324567)
  CallDouble(1234.56789)

EndProcedure
The three pointers are set as global variables at the beginning of the PB source file. My prototypes are setup as thus:

Code: Select all

; Prototypes - Pre defined functions (copy of the xojo declaration)
Prototype XojoString(msg.s)     ; A Xojo function (delegate)
Prototype XojoDouble(msg.s)     ; A Xojo function (delegate)
Prototype XojoInteger(msg.s)    ; A Xojo function (delegate)
You will see that they are all set as strings because they fail otherwise. I originally had them thus:

Code: Select all

; Prototypes - Pre defined functions (copy of the xojo declaration)
Prototype XojoString(msg.s)     ; A Xojo function (delegate)
Prototype XojoDouble(msg.d)     ; A Xojo function (delegate)
Prototype XojoInteger(msg.i)    ; A Xojo function (delegate)
If it is not inappropriate here, my Xojo code is:

Code: Select all

Declare Sub SetCallbacks Lib "../Resources/callBackTest.dylib" (pSt As Ptr, pDbl As Ptr, pInt As Ptr)

' Set callbacks
Dim p1, p2, p3 As Ptr
p1 = AddressOf MyStringCall
p2 = AddressOf MyDoubleCall
p3 = AddressOf MyIntegerCall
SetCallbacks(p1, p2, p3)
which, according to Xojo, is the correct way of defining the call in to the routine. I know this to be true as I use PB a lot to create dylibs for my Xojo programs.

What is not making any sense to me is that my PB callback works fine if I send a string back. What is not working is a callback with a double or integer value. Then the Xojo app just crashes.

Hopefully, my answer will give some indication of the calling convention being used by Xojo. If not, please ask a more specific question so that I can give a better answer.

Thanks, again, for your help.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Callback help

Post by wilbert »

From what I read online, Xojo uses CDecl by default so that would mean you probably need to use both ProcedureCDLL and PrototypeC.
Are both the Xojo app and the dylib 64 bit or 32 bit ?
Windows (x64)
Raspberry Pi OS (Arm64)
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Callback help

Post by simberr »

Yes, they are both 64 bits.

I would stress that this is a callback, not a 'normal' call to a dylib. I have the normal calling procedure very good now, having found that I should use ProcedureCDLL and not ProcedureDLL. All of that works very well (you helped me on that topic, too!).

Mu issue is now the callback routines. I have set up three callbacks. One for a string, one for a double and one for an integer. The string based callback works fine but both numerics do not, they just crash the main app. At this moment I am just using the string one to return any/all values and converting the string back to an integer or double in the calling program. But, I can't believe that this is the way to do it and that is what I am investigating at the moment.

So, my dylib is calling a routine in my main app. The main app routine has a numeric parameter (double or integer). I am initiating the callback by sending the address of the main app routine to the PB dylib and then the dylib its able to call the main app routine. This is where it fails - but _only_ with a numeric parameter. No parameter or a string parameter executes fine.
jack
Addict
Addict
Posts: 1336
Joined: Fri Apr 25, 2003 11:10 pm

Re: Callback help

Post by jack »

try using a pointer to double and pointer to integer.
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Callback help

Post by simberr »

Jack

I have now tried by returning a pointer to the calling app. The main app I have changed to accept a pointer as the parameter and converting that pointer to a double or integer, depending upon which routine is being called.

I am now _not_ getting the crash and I get a result in my integer or double variable in the main app. However, these values are nothing like the actual value being returned. In fact, the integer value is immensely huge - more than a million times the actual value and the double value is always zero.

At least it is not crashing my app.

But I still do not have a resolution to my issue.
jack
Addict
Addict
Posts: 1336
Joined: Fri Apr 25, 2003 11:10 pm

Re: Callback help

Post by jack »

could it be that the double or integer are local and no longer valid when retrieving the value?
simberr
User
User
Posts: 46
Joined: Sun Jun 10, 2018 12:54 pm

Re: Callback help

Post by simberr »

So, I tried that by making an integer variable and a double variable that is global in the dylib. I returned those to the calling app - it crashed.

I am really getting annoyed at this. It _has_ to be something I am doing, but, for the life of me, I cannot see it.
Post Reply