Who, OlimilO?
Why do you think so?
Printable View
Olaf usually didn't try to impose coding "rules" to others (as far as I remember), and he must be more concerned in doing his VB6-Replacement-Compiler than talking about these trivialities... (and VB7 syntax? :afrog:) but who knows, maybe he is bored and is playing a character. I guess everything is possible...
no, its not Olaf. Olaf would not say something like this.
LongPtr is useless most of the time. not even sure when its a good time to use it.
as I wrote before, when Im in 64bit, I will code accordingly, no purpose to use it if u stay in 32bit. its even stupid to use it.
and I think Olaf would not argue about such BS.
but who knows. from time to time Olaf can argue about nonsense, so it could be one such time.
This is a very valuable thread.
It can be said that this kind of black-tech "Public Enum LongPtr: [_]: End Enum" literally saved my life. Without this adorable monster, my work could hardly continue.
It would be amazing if we could have the following grammar:
Code:Public Enum LongPtr64
[_] As Currency
End Enum
LongPtr64 as Currency is possible via typelib.
I made a typelib specifically for LongPtr. Just updated it to also have LongPtr64 and LongLong aliased to Currency. Just add a reference to the TLB and voilĂ , VB6 now supports LongPtr, LongPtr64, and LongLong; only needed on the development machine, you don't need to include the typelib with compiled exes.Code:typedef [public] CURRENCY LongPtr64;
If I ever update oleexp.tlb again I'll add them there too. (oleexp is deprecated/maintenance mode; would only update to fix bugs).
Though remember as The trick explained, there's serious limits to what you can do with the technique, and extraordinarily difficult. These days it also makes very little sense when even if you want to stay in VB6, it would be far easier and without limits to just use a 64bit twinBASIC process to handle 64bit operations, and use interprocess communication to pass data back and forth to your main VB6 app. One way is a memory mapped file (you don't need an actual file on disk); CreateFileMapping memory blocks can be shared between 32 and 64bit processes.
PS- tB will support 32bit ActiveX Controls in 64bit apps for v1.0; it's in development/testing right now with lots of controls already working... should land in a public beta any time now.
Thanks great work! I updated Asm_Unsigned's vb-test-project to utilize LongLong as well, with 3 testfunctions: TestCurrencyAsLongLong, TestLongLong1, TestLongLong2
In UnsignedOps.dll a Currency is used to "simulate" resp to hold the bits of an Int64 (unsigned).
We have to be careful with LongLong-multiplications in VB6. Of course you know multiplication of 2 Currency is not the same as multiplication of 2 Int64 e.g. 0.01 * 0.1 = 0.001
And of course you know the multiplication of 2 Int64 can overflow Int64 resp result in Int128. In VB6 only a Decimal in a Variant is capable of holding at least 96bits
Maybe have a look at the code in Form1:
Form_Load
I checked with windows calculator, the dll delivers the correct result of the multiplication: 1234567890123 * 9876543210987 = 12193263113696860222381401
I tried the same in a win32 and win64 project in twinBASIC, I guess the error is already known, or am I doing something wrong?
Code:Private Sub Form_Load()
MsgBox(TestCurrencyAsLongLong) '0
MsgBox(TestLongLong1) '0
MsgBox(TestLongLong2) '0
MsgBox(TestLongLong3) ' empty
End Sub
Private Function TestCurrencyAsLongLong() As Currency
On Error Resume Next
Dim llng1 As Currency = 123456789
Dim llng2 As Currency = 987654321
Dim result As Currency = llng1 * llng2
Return result
End Function
Private Function TestLongLong1() As LongLong
On Error Resume Next
Dim llng1 As LongLong = 1234567890123
Dim llng2 As LongLong = 9876543210987
Dim result As LongLong = llng1 * llng2
Return result 'the correct answer should be: 12.193.263.113.696.860.222.381.401
End Function
Private Function TestLongLong2() As Decimal
On Error Resume Next
Dim llng1 As LongLong = 1234567890123
Dim llng2 As LongLong = 9876543210987
Dim result As Decimal = llng1 * llng2
Return result 'the correct answer should be: 12.193.263.113.696.860.222.381.401
End Function
Private Function TestLongLong3() As Variant
On Error Resume Next
Dim llng1 As LongLong = 1234567890123
Dim llng2 As LongLong = 9876543210987
Dim result As Variant = llng1 * llng2
Return result 'the correct answer should be: 12.193.263.113.696.860.222.381.401
End Function
You might be interested in this: https://github.com/fafalone/LongLongHelper. Same idea, but way, way easier.
It's a DLL for VB6 that performs operations on a LongLong held in a Currency using twinBASIC's native support for LongLong. You have the declares as Currency in VB6 but the tB DLL is set to see it as LongLong;
VB6:
Public Declare Function LongLongDiv Lib "LngLngHelp.dll" (ByVal c1 As Currency, ByVal c2 As Currency) As Currency
tB:
So you can do the math on them without any worry of the issues you get from Currency ops in vb6 where the decimal places will cause overflows and need adjustments multiplying or dividing by 10000. It's also super easy to modify to add additional functions; tB supports Standard DLLs natively so there's no registration issues and all you need to do is put that [DllExport] attribute above the function and VB6 is able to call it. Much more accessible than trying to do it in assembly.Code:[DllExport]
Public Function LongLongDiv(ByVal c1 As LongLong, ByVal c2 As LongLong) As LongLong
On Error GoTo fail
LongLongDiv = (c1 / c2)
hErr = S_OK
Exit Function
fail:
hErr = Err.Number
End Function
The tB DLL also handles it as a signed type like Currency and Long instead of unsigned like the asm dll, and errors give the same results as VB6 instead of the wrapping asm will do.
Yeah great ... have a look who starred your GitHub repo long ago. Whould you consider starring my repo as well?
When you remove the On Error Resume Next you'll see that you're overflowing.
The asm dll you're using is using unsigned data types, so there's a higher maximum value.
TestCurrencyAsLongLong:
Currency max: 922,337,203,685,477.5807
Multiplication result: 121,932,631,112,635,269
Overflow
TestLongLong1...
Max value for LongLong: 9,223,372,036,854,775,807
Multiplication result: 12,193,263,113,696,860,222,381,401
Overflow
TestLongLong2:
A Decimal can hold the result, but the intermediate math is multiplying 2 LongLongs so the temporary result is a LongLong, which overflows. If you use CDec(llng1) * CDec(llng2), or use Decimal for all 3, it works. This is the proper VB6-compatible behavior... try this in VB6:
Now despite the fact that Integer can obviously hold 500, the code will give an overflow because the intermediate Byte cannot. Same principle, and same issue with TestLongLong3.Code:Private Sub Form_Load()
Dim b1 As Byte
Dim b2 As Byte
b1 = 250
b2 = 250
Dim r As Integer
r = b1 + b2
MsgBox r
End Sub
A further difference is the asm operators wrap an overflow, where in VB6/tB, the operation fails and the variables never change from their values before the error.
PS- Starred your repo.
Thanks 100% correct.
ntdll's _allmul and _alldiv are only exported from the 32bit ntdll, so keep in mind if you're provisioning for x64.
Dolmio/Delmonte is definitely not Olaf. Olaf was largely correct in all technical things and unbearably precise.
I miss LaVolpe, I still NEED Olaf - whilst Dil. added the colour to the forum.