Results 1 to 4 of 4

Thread: Logging a DLL call that returns a string causes ThinBASIC to crash

  1. #1
    Join Date
    Jan 2017
    changsha China
    Rep Power

    Logging a DLL call that returns a string causes ThinBASIC to crash

    I often implement DLLs to extend the functionality of thinBasic. These DLLs were originally written using FreeBasic, and I later started using TCC to implement my DLLs.

    I find that when exchanging data between thinBasic and DLLs implemented in other programming languages, strings are always difficult to use as return values, unless my return value type is BSTR.

    So I often needed wrappers such as

    Declare Function Process_ListChild_Ori Lib "xLib.dll" Alias "Process_ListChild" (ByVal pHdr As Long) As ASCIIZ Ptr
    Function Process_ListChild(ByVal pHandle As Long) As String
    	Dim sPtr As Long = Process_ListChild_Ori(pHandle)
    	Dim sRet As String = Peek$(ASCIIZ, sPtr)
    	Return sRet
    End Function
    Then I got used to using BSTR, but found that my scripts often crashed and were very random. After a few days of troubleshooting, I came across this passage in a search engine

    BSTR is always free by the caller, the called party does not need to free the BSTR.

    It seems that ThinBASIC is the same way, so I removed the code for GC to reclaim BSTR memory, and now they work fine and run for a long time without crashing, sharing it to avoid people who have the same problem as me to suffer difficulties.

    Translated with (free version)
    Last edited by xLeaves; 25-05-2022 at 07:59.

  2. #2
    Super Moderator Petr Schreiber's Avatar
    Join Date
    Aug 2005
    Brno - Czech Republic
    Blog Entries
    Rep Power
    Hi xLeaves,

    thanks a lot for sharing the solution for the problem!

    I would say exchanging text between languages is an challenge in general. For example - std::string in C++ is even more interesting, as the place of the data depends on the string length (if interested, see second reply here).

    ThinBASIC has an ideal symbiosis with PowerBASIC for STRING data type, as it is the same internally.

    You correctly picked ASCIIZ to change the data between FreeBASIC and thinBASIC. The same would apply for example for pure C and thinBasic.

    If I may note one thing - your approach is perfectly safe, yet may pose a performance issue.

    You basically perform extra allocation:
    - your DLL allocates the memory for result - text allocated at memory location 1
    - thinBasic duplicates the memory of result - text allocated at memory location 2
    - you return the duplicated value and possibly assign it to some variable - text allocated at memory location 3

    In many cases it is okay, in other cases you could run into speed issues:
    - if the amount of data is large
    - especially if you would perform such operation in a loop

    If you can use ASCIIZ directly, without conversion, and if you see ahead the maximum possible size for the string the returned pointer points to, you can shorten your code to:
    Dim azMyResult As asciiz * 512 at Process_ListChild_Ori(pHandle) ' Note I expect the string from freebasic to not be larger than 512 bytes, feel free to change that number
    ' Now azMyResult can be used to further print the value, but assigning the data from FreeBasci to azMyResult did not create a new allocation, azMyResult maps over the original memory
    Alternatively, if you are okay with the copy, your code can also use the PeekZ$:
    Function Process_ListChild(ByVal pHandle As Long) As String
      Return PeekZ$(Process_ListChild_Ori(pHandle))  ' Note PEEKZ$, so you don't have to specify ASCIIZ
    End Function

    Last edited by Petr Schreiber; 27-05-2022 at 19:56.
    Learn 3D graphics with ThinBASIC, learn TBGL!
    Windows 10 64bit - Intel Core i5-3350P @ 3.1GHz - 16 GB RAM - NVIDIA GeForce GTX 1050 Ti 4GB

  3. #3
    Join Date
    Jan 2017
    changsha China
    Rep Power


    Thank you Petr Schreiber, these methods you shared were very useful for me.

  4. #4
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Milan - Italy
    Blog Entries
    Rep Power
    Depending on what is the programming language you use for your DLL, you can pass a thinBasic string BYREF to your DLL function, manage the string as a BSTR and the rest will be done by thinBasic.
    Your external function will just return a status code while the string will be changed by your function
    When you return from external function the string will be visible by thinBasic script with the chages you performed inside external function
    Allocation and deallocation will be performed by thinBasic automatically

    In this way you do not have to convert anything, that is a big CPU consuming.

    Just a another idea to test.


    Declare Function Process_ListChild_Ori Lib "xLib.dll" Alias "Process_ListChild" (byref thinBasicString as string) As Long
    Function MythinBasicFunction(...) As String
      dim MyString    as string
      dim lReturnCode as long
      '---MyString is allocated by thinBasic
      '---Pass it to external function
      '---Change MyString in external function
      lReturnCode = Process_ListChild_Ori(MyString)
      '---Here thinBasic will de-allocate MyString
    End Function | |
    Win10Pro 64bit - 8GB Ram - Intel i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB

Similar Threads

  1. ThinBasic used for data logging
    By Petr Schreiber in forum thinBasic where ...
    Replies: 0
    Last Post: 06-06-2010, 16:07
  2. Comm_Recv causes thinBasic to crash
    By Bevan in forum COMM (Serial communication)
    Replies: 23
    Last Post: 08-08-2007, 10:59
  3. CALL keyword with function name as string expression
    By ErosOlmi in forum Sources, Templates, Code Snippets, Tips and Tricks, Do you know ...
    Replies: 0
    Last Post: 07-09-2006, 16:16

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts