• Welcome to Jose's Read Only Forum 2023.
 

FreeBASIC CWstr

Started by Juergen Kuehlwein, April 09, 2018, 11:39:00 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

José Roca

#90
> As long as "p" in "someprop" is an IN parameter, this will work in general (because of the intermediately created CBstr) - is this correct?

Of course. What I mean is that if you intend to call, for example, the GetParentFolderName of the IFileSystem object

GetParentFolderName (BYVAL Path AS BSTR, BYVAL pbstrResult AS BSTR PTR) AS HRESULT

you have to pass a BSTR with the path and the address of another BSTR to receive the result, and if they aren't true BSTRings it won't work. You can't declare the parameters as CBSTR instead of BSTR because the called method has no idea of what a CBSTR is, and you can't declare these parameters as WSTRINGs because it will fail. What you can do is to pass cbsPath.bptr and cbsRes.vptr.


Juergen Kuehlwein

José,


i don´t intend to call GetparentFolderName directly, i would use the wrapper function your framework supplies, which conveniently accepts CBstrs:


Quote
PRIVATE FUNCTION CFileSys.GetParentFolderName (BYREF cbsFolder AS CBSTR) AS CBSTR


and i would call it like this


Quote
p = <CFileSys>.GetParentFolderName(f)


where p MUST be a CBstr, and f can be a CBstr, CWstr, WSTRING, String and ZSTRING (and if i define USTRING as CWstr, a USTRING as well).


I didn´t find one single instance, where a BSTR is needed as parameter of a procedure i could call directly. As it seems, it is used internally alone. So when using your framework i can get away with a CWstr most of the time and sometimes (only in COM) i MUST use a CBStr for IN/OUT parameters (CBstr.vptr) and for returned strings (CBstr).

In summary this means: when using your framework i can almost have what i want, a universal string data type (USTRING defined as CWstr). And only in some special cases (as said above) i must implement a CBstr, which mimics a BSTR, which is the required string data type for COM. If someone doesn´t want to use your framework in my IDE, i will supply a wide string data type (a clone of your CWstr) and some functions for string manipulation. In this case COM (and all other functionality of your frame work) is not available, and a decision between CBstr and CWstr is immaterial and pointless, because there is no use for CBstr, in fact there is no CBstr at all - so USTRING (= CWstr) can be used universally.


Do you agree?


JK

José Roca

It is mandatory for parameters. For strings returned as the result of a function, you can assign it to a CBSTR, CWSTR, CVAR, STRING, WSTRING or even ignore it. The returned CBSTR is temporary and destroys itself.

If somebody does not want to use my framework, it will be his loss, not mine. I'm providing with it the functionality available in PowerBasic that is missing in FreeBasic and much more, although, of course, with a different syntax and programming style.

A SDK programmer should not have many problems to use my framework, but unfortunately the PBer's have been spoiled by DDT. Very few, if any, will use CWindow directly. Instead they will use a tool like the Visual Designer in which Paul Squires is working. The generated code will use CWindow and other wrappers internally, but for the custom code they will use the OOP classes in which Paul is also working. Millions of programmers have been spoiled by Visual Basic.


Juergen Kuehlwein

Quote
For strings returned as the result of a function, you can assign it to a CBSTR, CWSTR, CVAR, STRING, WSTRING or even ignore it. The returned CBSTR is temporary and destroys itself.


...even better! So the only place, where CBstr.vptr is mandatory in your framework, is an IN/OUT parameter in a COM method or property.



Quote
If somebody does not want to use my framework, it will be his loss, not mine.


i absolutely agree!



The Visual Designer in my IDE produces pure SDK code without any wrappers (it already does in PowerBASIC and it will do in FreeBASIC). In fact i´ve never understood, what´s the benefit of learning wrappers compared to learning the fundamentals, which can be re-used in almost every programming language for Windows. DDT and Visual Basic were attempts to make things easier (a marketing instrument) for beginners and professionals, but i agree, while maybe easier in the beginning both don´t make it easier in the long run, and both kept/keep people away from learning the fundamentals of the Windows API. I think we share the same point of view here.


Did you find any more problems in the code i posted (fb_str.inc, when USTRING is defined as CWstr)


JK

José Roca

#94
> ...even better! So the only place, where CBstr.vptr is mandatory in your framework, is an IN/OUT parameter in a COM method or property.

Only for OUT parameters. For IN/OUT parameters not (I mentioned it previously by mistake, sorry).

The reason is to avoid memory leaks. The COM rules are strict. When we pass a BSTR pointer to a COM method with an IN/OUT parameter, the COM method reads the content of the passed BSTR, does what it needs to do, frees the passed BSTR and returns a new allocated BSTR. When we pass it to an OUT parameter, it simply returns a pointer to a new allocated BSTR. Therefore, if we pass a BSTR that has contents, it won't we freed and we will have a memory leak. What the .vptr method does is to free the BSTR before pasing the pointer. The alternative is to clear the CBSTR before passing it.

> Did you find any more problems in the code i posted (fb_str.inc, when USTRING is defined as CWstr)

The fundamental flaw was to define it as CBSTR and then use it with a function designed to work with a CWSTR. CBSTR uses attaching instead of copying whenever possible for speed and for ease of use. If it is attached, the BSTR will we freed when the CBSTR is destroyed. If it is copied, you are responsible of freeing the original BSTR.

> I think we share the same point of view here.

If nobody did learn how to use the API, there won't be tools and frameworks available. Even the Windows API is a framework. My framework simply helps to do some things more easily. Instead of using CWSTR, you can work allocating and freeing your own buffers and manipulate them using pointers, but this is very hard.

When a SDK programmer tries to use a new compiler, as we are doing with FreeBasic, all he needs is to learn the intrinsics of the language, but DDTers will ask "What is the equivalent of CONTROL SET TEXT?," "What is the equivalent of CONTROL ADD LISTBOX?," etc. Excepting Paul, that has used it to write his editor, nobody has helped me to debug the framework. Everybody is lurking and waiting for the upcoming visual designer.

Anyway, I believe that almost all the DDTer's will continue to use PB for ever. Therefore, my efforts are directed to extend FreeBasic, not to attract DDTers.

Juergen Kuehlwein

Hello, José,


having finished my IDE´s todo list for FreeBASIC, i will have time now for returning to CWstr.

The type itself seems to work flawlessly, at least i did not encounter problems anymore using it in the last month. I my view there are two problems remaining:

1.) CWstr is not multiplatform, currently it depends on windows
2.) it doesn´t integrate seamlessly into the compiler (you need to prepend "**")

Well, #1 should be solvable, you must get rid of the Windows API functions. For the copy part i already have specialized assembler functions (32 and 64 bit), which leaves the conversion functions. I didn´t try but maybe "MultiByteToWideChar" could be replaced by FB intrinsic functions (maybe in "utf_conv.bi"). There must be such (multiplatform) functions, because of the automatic conversions between STRING/ZSTRING and WSTRING taking place when assigning one type to the other.

#2 is a compiler problem not always processing CWstr as it should. Fortunately the compiler´s code is available. I don´t know anything (so far) about compiler building, nevertheless it took me only two and a half hours to code a (working) fix for the "SELECT CASE" problem, you don´t need "**" for CWstr anymore after "SELECT CASE". So fixing the compiler´s behavior is doable!


Would you like to help making your excellent work as perfectas possible ? I would appreciate that very much!


JK

José Roca

With Linux, FreeBasic uses UTF-32 (4 bytes for each character). Therefore, you may need not only to get rid of the Windows functions, but a separate class that treats each character as a DWORD.

I never have used Linux and I don't think that I will ever do.

Juergen Kuehlwein

José,


are you sure ? This would mean that "WSTRING" must be handled differently for Windows and Linux by the compiler. Even if this is the case, just processing a character of dword size instead of word size for Linux shouldn´t be much of a problem. There are intrinsic defines (__FB_LINUX__, etc.) you could use for platform depended conditional compiling in your CWstr class.

I don´t use Linux either, nor do i plan to use it, but there should be enough people in the FB forum, who actually do. Maybe someone is willing to help. Would you mind me asking for help there ? I don´t want to take over your work, but i intend to optimize it, if you don´t mind and if you don´t want to take the lead.


JK

José Roca

Open

The encoding to be used when reading or writing text, can be one of:

Encoding "ascii" (ASCII encoding is used, default)
Encoding "utf8" (8-bit Unicode encoding is used)
Encoding "utf16" (16-bit Unicode encoding is used)
Encoding "utf32" (32-bit Unicode encoding is used)

However, I think that Linuxers use mainly utf-8 because utf-32 is wasteful and not widely supported by third party libraries.

Regarding FreeBasic users, I don't see anybody using unicode, neither in Windows nor in Linux. I'm an exception. Even the FreeBasic "Open" statement can't open a file using an unicode file name. Go figure!

Anyway, if you want to play with it, you can use the DWSTRING class that I posted in the FreeBasic forum. It is a variation of CWSTR that uses a WSTRING pointer instead of an UBYTE pointer. You can do with it whatver you wish.

Juergen Kuehlwein

José,


thanks - i will try my best


JK



Marc Pons

Hi
happy to see someone interrested on unicode for freebasic

it was a long story for me, José probably remember , specially for concatenation...

please have a look here  https://www.freebasic.net/forum/viewtopic.php?f=17&t=24070&hilit=marpon&start=45

finally i stopped developping that point, i see you want to follow the same route ... good

if you are interrested  my githib with my last code https://github.com/marpon/DWSTR
and my first attempt https://github.com/marpon/uStringW
marc

Juergen Kuehlwein

Hi Marc,


thanks, i didn´t know your version, which tries to address Linux and surrogate pairs too. Are there there fundamental differences between your version and José´s version (apart form your´s being multiplatform and the surrogate pair stuff) ?
If yes - what and where are they ?

You say you stopped developping that point - what exactly do you mean by "that point" - the whole thing ? Where there still unsolved problems other than having to prepend "*" ?



JK



Marc Pons

hi Juergen

i've stopped investing time on  "unicode" globally.
In fact for my own usage i do not need it,  cp1252 is enougth for me.
It was just for me an exercise and a long time attempt to push the FreeBasic team integrating it as a native feature
and making it visible for them to show it is doable quit easily if ...

My last version not have fundamental differences vs José's, that inspired me a lot, execpt:
   - surrogates minimal support
   - linux /windows
   -  *   compared to **   (wich i did not like)
   - strptr overload
   - codepage management for win / linux
and some extra stuff

in my first version uStringW (1 year before DWSTR), you could see more conversion and file support that i did not add to DWSTR

Marc


Juergen Kuehlwein

Ok - i have been successful adapting the compiler´s code so that it now accepts and properly processes "SELECT CASE <USTRING>" and "MID" (function and statement) with USTRINGs.

I need all kinds of sample code snippets, where "**" (José) or "*" (Marc) must be prepended because either
- the compiler throws an error
or (even worse)
- the compiler accepts it but the result is wrong (e.g "MID" as a statement compiles, but the result is wrong for an USTRING).

Please help me with your code, so I don´t miss something...


So far it isn´t as hard as i expected, it´s all about telling the compiler to handle an USTRING just like a WSTRING in different places. I´m quite confident to get this done without major changes to the compilers inner working and therefore i hope to be able to convince the current developers to integrate it.


JK

Juergen Kuehlwein

#104
José, Marc


here is a test version of the compiler (32 and 64 bit). According to my tests prepending "*" isn´t necessary anymore. You should be able to use exactly the same syntax as with other intrinsic FreeBASIC string data types. Please help testing.


JK


PS: I forgot to mention both compilers are compiled for the standalone (not for the installer) version.