How to Return a String from Windows DLL

Just starting out? Need help? Post your questions and find answers here.
swhite
Enthusiast
Enthusiast
Posts: 727
Joined: Thu May 21, 2009 6:56 pm

How to Return a String from Windows DLL

Post by swhite »

Hi

When I call the Encrypt function from this PB dll from another Windows application all I receive is the "C" but I should be receiving the entire encrypted string. Can someone tell me what I have done wrong?

Code: Select all

;
; AES Encryption key and Initialization Vector
;
DataSection
   Key:
   Data.b $25, $64, $24, $47, $7D, $BC, $80, $BF, $2B, $7A, $72, $2A, $29, $41, $6E, $2B, $4B, $23, $5E, $75, $65, $34, $3D, $70, $43, $3F, $3B, $49, $6A, $36, $51, $30
   
   IV:
   Data.b $3d, $af, $ba, $42, $9d, $9e, $b4, $30, $b4, $22, $da, $80, $2c, $9f, $ac, $41
EndDataSection
Global gcEnc.s

ProcedureDLL.s Encrypt(tcTxt.s)
   Define lcTxt2.s
   If Len(tcTxt) < 16
      tcTxt = LSet(tcTxt,16," ")
   EndIf
   lcTxt2 = Space(1024)
   AESEncoder(@tcTxt,@lcTxt2,StringByteLength(tcTxt),?Key,256,?IV,#PB_Cipher_CBC) 
   lcTxt2 = RTrim(lcTxt2)
   gcEnc = Base64Encoder(@lcTxt2,StringByteLength(lcTxt2))
   ProcedureReturn gcEnc
EndProcedure

Simon White
dCipher Computing
tored
User
User
Posts: 61
Joined: Wed Feb 16, 2022 12:47 pm
Location: Sweden

Re: How to Return a String from Windows DLL

Post by tored »

Strings returned from DLLs are returned as pointers. And strings returned from DLLs also need to be allocated.

https://www.purebasic.com/documentation ... e/dll.html

There are multiple strategies to handle this, in this thread you can find some of them , search the forum for more.

viewtopic.php?t=66612
User avatar
mk-soft
Always Here
Always Here
Posts: 5385
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to Return a String from Windows DLL

Post by mk-soft »

Or as BStr ...

Code: Select all


ProcedureDLL MyFuncBStr()
  Protected r1, text.s
  text = "Hello World!"
  r1 = SysAllocString_(text)
  ProcedureReturn r1
EndProcedure


; Main

*bstr = MyFuncBStr()
Debug PeekS(*bstr)
SysFreeString_(*bstr)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 5385
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to Return a String from Windows DLL

Post by mk-soft »

I just found it in the forum. But I don't remember testing this with Excel.
I think I'm getting old.

https://www.purebasic.fr/english/viewtopic.php?t=70848
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
tored
User
User
Posts: 61
Joined: Wed Feb 16, 2022 12:47 pm
Location: Sweden

Re: How to Return a String from Windows DLL

Post by tored »

Here are some other options (if I'm thinking correctly late at night)

Memory handling in the DLL

dll.pb

Code: Select all

EnableExplicit

ProcedureDLL.i Get()
  Protected text.s, *buffer, *pointer
  
  text.s = "Hello World"
  *buffer = AllocateMemory(StringByteLength(text), #PB_Memory_NoClear)
  If Not *buffer
    ProcedureReturn #False
  EndIf   
  *pointer = *buffer
  CopyMemoryString(text, @*pointer)
  ProcedureReturn *buffer
EndProcedure  

ProcedureDLL Free(*buffer)
  FreeMemory(*buffer)
EndProcedure  
app.pb

Code: Select all

EnableExplicit

If Not OpenLibrary(0, "dll.dll")
  Debug "Failed opening dll"
  End 1
EndIf

Prototype.i ProtoGet()
Prototype ProtoFree(*buffer)

Define Get.ProtoGet = GetFunction(0, "Get")
Define Free.ProtoFree = GetFunction(0, "Free")

Define *buffer
*buffer = Get()
If Not *buffer
  Debug "Failed getting string"
  End 1
EndIf  
Debug PeekS(*buffer)
Free(*buffer)

Memory handling in the app

dll2.pb

Code: Select all

EnableExplicit

Prototype.i ProtoAllocator(*mem, len.q)

ProcedureDLL.i Get(Allocator.ProtoAllocator)
  Protected text.s
  
  text.s = "Hello World"
  ProcedureReturn Allocator(@text, StringByteLength(text))
EndProcedure 
app2.pb

Code: Select all

EnableExplicit

If Not OpenLibrary(0, "dll2.dll")
  Debug "Failed opening dll"
  End 1
EndIf

Prototype.i ProtoAllocator(*mem, len.q)
Prototype ProtoGet(Allocator.ProtoAllocator)

Define Get.ProtoGet = GetFunction(0, "Get")

Procedure.i MyAllocator(*mem, len.q)
  Protected *buffer, *pointer
  
  *buffer = AllocateMemory(len, #PB_Memory_NoClear)
  If Not *buffer
    ProcedureReturn #False
  EndIf   
  *pointer = *buffer
  CopyMemory(*mem, *pointer, len)
  ProcedureReturn *buffer
EndProcedure

Define *string = Get(@MyAllocator())
If Not *string
  Debug "Failed getting string"
  End 1
EndIf  
Debug PeekS(*string)
FreeMemory(*string)
swhite
Enthusiast
Enthusiast
Posts: 727
Joined: Thu May 21, 2009 6:56 pm

Re: How to Return a String from Windows DLL

Post by swhite »

I did not realize the return value was a pointer to the string. Now I have it working correctly so thank-you to everyone.

Simon
Simon White
dCipher Computing
Post Reply