Bridging PowerBasic and a PureBasic DLL: A Detailed Guide on Interoperability

Started by Theo Gottwald, July 13, 2023, 11:47:13 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Theo Gottwald

In this post, I aim to shed light on a critical aspect of programming that often goes unnoticed - the handling of strings and binary data in different programming languages. Specifically, I will be focusing on two languages: PureBasic and PowerBasic.

Understanding String Engines: PureBasic vs PowerBasic
The first point of divergence between PureBasic and PowerBasic lies in their string engines. PowerBasic employs BSTRINGS, while PureBasic uses "zero terminated strings". This distinction becomes crucial when dealing with binary data.

In PowerBasic, you can directly insert binary data into a string. However, in PureBasic, you need to allocate memory for binary data and handle it in a manner akin to the C programming language.

It's worth noting that strings often contain "text" and do not include any zeroes. In such cases, you can use a PureBasic DLL with the strings from PowerBasic without any issues.

The Case for PureBasic DLLs in PowerBasic
There are compelling reasons to consider calling a PureBasic DLL from PowerBasic. Over time, PureBasic has surpassed PowerBasic in terms of library support, offering a wide range of functionalities with just a handful of commands.

Moreover, PureBasic supports x64, is user-friendly, and is a "Single-Pass" compiler, which results in impressive compiler speed.

The Power of Combining PowerBasic and PureBasic
Why not leverage the best of both worlds? By combining your existing PowerBasic code with the new PureBasic, transitioning becomes much smoother. Let's delve into this further.

Creating a DLL with PureBasic and Calling it from PowerBasic
The goal here is to create a DLL using PureBasic and call it from a PowerBasic main program. While working with numbers poses no problem, string handling can be a bit more complex.

A Simple Example: Sending a String from PowerBasic to a PureBasic DLL
Let's start with a simple example where we send a string from PowerBasic into a PureBasic DLL. We'll be working with both 32-bit versions, as PowerBasic does not support x64.

In the following sections, I will provide a step-by-step guide on how to accomplish this, complete with code snippets and explanations. Stay tuned!

I hope this post has been informative and sparked your interest in exploring the interoperability between PureBasic and PowerBasic. As always, I welcome any questions or comments you may have.

';This is the Code in the Purebasic DLL

Global.s Mode

ProcedureDLL Set_Mode(U01.s) 
 Protected S02.s
 If Len(U01)>0 
   Mode=Trim(U01)
 Else
   Mode=#defmode
 EndIf
EndProcedure

' In Powerbasic you would write
DECLARE SUB Set_Mode LIB "Pure.dll" ALIAS "Set_Mode" (BYVAL U01 AS WSTRING)   

You can then proceed to call the PureBasic DLL and set the variable. However, it's crucial to ensure that your string doesn't contain any "zeroes" before sending it to the DLL, as this could potentially lead to unexpected outcomes.

Retrieving a string from a PureBasic DLL into PowerBasic presents a more challenging scenario. The interoperability between the two isn't as seamless as one might hope. However, it's not an insurmountable task. Let's explore this through an example:

; This is the code in the Purebasic DLL to send the String
; Last_A to Powerbasic
; Its split into 2 Subprogrammes

Global.s Last_A
ProcedureDLL.l GetLast_A()   
ProcedureReturn @Last_A
EndProcedure

ProcedureDLL.l GetALen(U01.l)
  Static T01.l
   T01=Len(Last_A)
  ProcedureReturn T01
EndProcedure   
 

On the Powerbasic side we need to put this all together.

DECLARE FUNCTION GetALenLIB "Pure.dll" ALIAS "GetALen" () AS LONG
DECLARE FUNCTION GetLast_ALIB "Pure.dll" ALIAS "GetLast_A" () AS LONG 

' This will do the trick
FUNCTION Get_Last_A() AS STRING
REGISTER R01 AS LONG,R02 AS LONG
LOCAL S01 AS STRING
R01=GetLast_A()
R02=GetALen()
S01=PEEK$$(R01,R02)
FUNCTION=S01
END FUNCTION   

In Powerbasic you will call:   "A$=Get_Last_A()" to get the String from Purebasic.

While the steps outlined so far have their complexities, they are not the most challenging aspect of this process. The real test of your skills comes when you want to send a string array from PowerBasic to PureBasic.

; This is in the Purebasic DLL
; This Array will be filled with the COntent from thwe Powerbasic String-Array
Global.s GArray()

ProcedureDLL TransferStringArray(arrayPointer.i, arraySize.l,U03.l)
  Protected i = 0, start = arrayPointer, current = arrayPointer, tempString.s
  ReDim_GArray(U03)
  GDim=U03
  While current < start + arraySize-1
    If PeekB(current) = 0 ; Null terminator found
      GArray(i) = tempString
      tempString = ""
      i + 1
    Else
      tempString + Chr(PeekB(current))
    EndIf
    current + 1
  Wend
; Zum Anzeigen ob das Array angekommen ist 
CompilerIf 0
  For i = 0 To GDim ;ArraySize(GArray()) - 1
    Debug(GArray(i))
  Next
CompilerEndIf
EndProcedure

; This is the Code on the Powerbasic Side
' U01 - STRPTR()
' U02 - Len()
' U03 - UBOUND()
'
DECLARE SUB TransferStringArray LIB "Pure.dll" ALIAS "TransferStringArray" (BYVAL arrayPointer AS LONG, BYVAL arraySize AS LONG,BYVAL U03 AS LONG)
' U01() - Array 0 ... U02-1
'
SUB Send_Array(BYREF U01() AS STRING)
    'DIM MyArray(0 TO 4) AS STRING
    REGISTER i AS LONG
    REGISTER j AS LONG
    LOCAL T01,T02,T03 AS LONG
    LOCAL S01 AS STRING
    ' Upper Array-Bound bestimmen
    T01=LBOUND(U01(1)):T02=UBOUND(U01(1))
    ' Concatenate all strings into a single string, with a null character as separator
    FOR i = T01 TO T02
        S01 += U01(i)+CHR$(0)
    NEXT
    ' Am Ende noch eine Extra-0
    S01 += CHR$(0)

    ' Call the DLL function
    j=LEN(S01)
    T03=T02-T01
    TransferStringArray(STRPTR(S01),j,T03)
END SUB             

In this manner, you can transmit a string array to PureBasic. As always, it's crucial to ensure that the string data does not contain any "zeroes". If it does, you might need to employ a different approach due to the "zero terminated strings" characteristic of PureBasic.