Static linking of .obj/.lib from other languages now available
Thought some people around here would find this new feature noteworthy, so wanted to give it special mention.
In new twinBASIC releases you can now statically link (compile directly into your project) .OBJ and .LIB files, allowing you to have code written in any language that can be compiled into that format (e.g. C, C++, Assembly).
There's a new Sample Project with SQLITE... if you compile it with using x86 tools then again with x64 tools;
cl /c /Gw /Gy /GS- /DSQLITE_OMIT_SEH sqlite3.c
you can then add the .obj file to the Miscellaneous folder in the Project Explorer, then:
Code:
#If Win64 Then
Import Library "/Miscellaneous/sqlite3_64.obj" As SQLITE3 Link "stdlib", "kernel32"
#Else
Import Library "/Miscellaneous/sqlite3_32.obj" As SQLITE3 Link "stdlib", "kernel32"
#End If
Module MainModule
Declare PtrSafe Function sqlite3_open CDecl Lib SQLITE3 (ByVal filename As String, ByRef ppDb As LongPtr) As Long
Declare PtrSafe Function sqlite3_exec CDecl Lib SQLITE3 (ByVal pDb As LongPtr, ByVal sql As String, ByVal exec_callback As LongPtr, ByVal udp As LongPtr, ByRef errmsg As LongPtr) As Long
Declare PtrSafe Function sqlite3_prepare_v2 CDecl Lib SQLITE3 (ByVal pDb As LongPtr, ByVal zSql As String, ByVal nByte As Long, ByRef ppStmt As LongPtr, ByVal pzTail As LongPtr) As Long
Declare PtrSafe Function sqlite3_step CDecl Lib SQLITE3 (ByVal ppStmt As LongPtr) As Long
CDecl is the better calling convention here because with __stdcall the compiler will mangle the names by adding @size_of_args, i.e. sqlite3_open would be sqlite3_open@8 on 32bit, sqlite3_open@16 on 64bit. Since that can only be fixed at the linker stage we're not using, it's seemingly unavoidable.
--
The first thing I've used this for is to exported the C/C++ compiler intrinsics for the Interlocked____ APIs, which are only exported by 32bit system dlls. Previously I had written a c++ dll, but half the use was kernel mode, where you couldn't use it. The new static library version can be used in both kernel mode and user mode (where it's useful for multithreading).
Interlocked64.c
Code:
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
long __cdecl x64InterlockedIncrement(long* Addend)
{
return InterlockedIncrement(Addend);
};
...
Then compiled with cl.exe /c /Gw /Gy /GS- Interlocked64.c /Fo"Interlocked64.obj", added to a tB project in a new StaticLibraries folder I made, and:
Code:
#If Win64 Then
Import Library "/StaticLibraries/Interlocked64.obj" As Interlocked
#End If
Module MyModule
Private DeclareWide PtrSafe Function InterlockedIncrement CDecl Lib Interlocked Alias "x64InterlockedIncrement" (Addend As Long) As Long
...
No Link ,,, here because as purely exporting intrinsics, it has no dependencies.
Re: Static linking of .obj/.lib from other languages now available
Btw, this will allow wrapping cdecl only C/C++ libraries in Ax-DLLs for VB6 users to enjoy e.g. libarchive and zstd come to mind, probably some modern image/video formats too, pdf readers, cairo, skia, even openssl can be embedded in an Ax-DLL.
For RC6 this would mean it can reduce its several redistributable binaries to a single DLL, provided that TB compiler can process such behemoth of a VB6 project.
This is also making any thunking efforts obsolete too as these can be directly embedded in the final binary as ASM executable code.
Overall this would be a monumental shift in VB6 and COM land in general. All we need now is a couple of hundred of betas so the compiler stabilizes once more :-))
Re: Static linking of .obj/.lib from other languages now available
@wqweto -- If you were going to compile from source, couldn't you build the DLLs as __stdcall for use in VB6 (assuming for some reason you didn't want to use The trick's CDeclFix or a typelib)? IIRC correctly that's been done (I think by you, possibly)
But yes while not *completely* eliminating the need for inline asm support later, it does help with a lot of places were thunks would be used.
#If Win64 Then
Import Library "/Miscellaneous/tinf.lib" As tinf
#Else
Import Library "/Miscellaneous/tinf32.lib" As tinf
#End If
'To compile, I just used Wayne's instructions from Discord;
'cl.exe /c /Gw /Gy /GS- crc32.c /Fo"crc32.obj"
'cl.exe /c /Gw /Gy /GS- tinfgzip.c /Fo"tinfgzip.obj"
'cl.exe /c /Gw /Gy /GS- tinflate.c /Fo"tinflate.obj"
'cl.exe /c /Gw /Gy /GS- tinfzlib.c /Fo"tinfzlib.obj"
'lib /out:tinf.lib adler32.obj crc32.obj tinfgzip.obj tinflate.obj tinfzlib.obj
Module TinfLib
Public Const TINF_VER_MAJOR = 1 /**< Major version number */
Public Const TINF_VER_MINOR = 2 /**< Minor version number */
Public Const TINF_VER_PATCH = 1 /**< Patch version number */
Public Const TINF_VER_STRING = "1.2.1" /**< Version number as a string */
Public Enum tinf_error_code
TINF_OK = 0 /**< Success */
TINF_DATA_ERROR = -3 /**< Input error */
TINF_BUF_ERROR = -5 /**< Not enough room for output */
End Enum
'int TINFCC tinf_uncompress(void *dest, unsigned int *destLen,
' const void *source, unsigned int sourceLen);
Public Declare PtrSafe Function tinf_uncompress CDecl Lib tinf (dest As Any, destLen As Long, source As Any, ByVal sourceLen As Long) As Long
'int TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen,
' const void *source, unsigned int sourceLen);
Public Declare PtrSafe Function tinf_gzip_uncompress CDecl Lib tinf (dest As Any, destLen As Long, source As Any, ByVal sourceLen As Long) As Long
' int TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen,
' const void *source, unsigned int sourceLen);
Public Declare PtrSafe Function tinf_zlib_uncompress CDecl Lib tinf (dest As Any, destLen As Long, source As Any, ByVal sourceLen As Long) As Long
'unsigned int TINFCC tinf_adler32(const void *data, unsigned int length);
Public Declare PtrSafe Function tinf_adler32 CDecl Lib tinf (data As Any, ByVal length As Long) As Long
'unsigned int TINFCC tinf_crc32(const void *data, unsigned int length);
Public Declare PtrSafe Function tinf_crc32 CDecl Lib tinf (data As Any, ByVal length As Long) As Long
Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
'Note: This computes the checksum as Unicode, it doesn't reduce it to 1-byte per char ANSI
Public Function CRC32(ByVal pStr As String) As Long
Dim ar() As Integer
ReDim ar(Len(pStr))
CopyMemory ar(0), ByVal StrPtr(pStr), Len(pStr) * 2
Return tinf_crc32(ar(0), UBound(ar) + 1)
End Function
End Module
Re: Static linking of .obj/.lib from other languages now available
Originally Posted by fafalone
The first thing I've used this for is to exported the C/C++ compiler intrinsics for the Interlocked____ APIs, which are only exported by 32bit system dlls.
It might be even better than that. SIMD instructions are also offered as intrinsics by modern C/C++ compilers. If this works the way I think it does, this would open up a new world of optimization options for VB6 programmers that were not so easily available before.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Re: Static linking of .obj/.lib from other languages now available
Greetings, I was trying to compile https://github.com/utelle/SQLite3MultipleCiphers to test the static compilation and I have not obtained any results. How should I compile to avoid getting the error: unrecognized symbol....?
Re: Static linking of .obj/.lib from other languages now available
No worries with the images; not your fault, it's a forum bug that hasn't been fixed for years now.
Did you compile it from the developer prompt with the same options as the sample? cl /c /Gw /Gy /GS- /DSQLITE_OMIT_SEH sqlite3.c /Fo"sqlite3_64.obj" (or 32, with the appropriate settings... note with VS2022 you'd just open the appropriate command prompt rather than run vcvars commands yourself). That there's security_cookie functions named definitely makes me think /GS- wasn't defined.
Last edited by fafalone; Mar 4th, 2024 at 01:09 AM.
Re: Static linking of .obj/.lib from other languages now available
Compile that way, now I get these errors. What am I doing wrong? Are any dependencies missing when compiling or including any dependencies in TwinBasic?
Re: Static linking of .obj/.lib from other languages now available
It's compiled into your project so I believe you can just use AddressOf; I tried it and it returned a valid-looking value but I didn't try actually using it yet.
Re: Static linking of .obj/.lib from other languages now available
Can you clarify whether you're talking about declared functions within the static lib, or if you were trying to use it on undeclared static lib functions? The latter wouldn't be expected to work.
Re: Static linking of .obj/.lib from other languages now available
Call undeclared static library functions. It's not something that relevant, it's just part of my curiosity. I have an Activex library that allows using SQLite3 in VB6, but it requires "Sqlite3.dll", in a class it exposed a function that allowed calling the dll functions without them being previously declared. something like this:
Code:
Public Function CallFunc(FunctionName As String, ParamArray Params() As Variant) As Variant
Dim pFunc As Long
Dim hMod As Long
hMod = GetModuleHandleW(StrPtr("sqlite3.dll"))
If hMod = 0 Then hMod = LoadLibraryW(StrPtr("sqlite3.dll"))
pFunc = GetProcAddress(hMod, FunctionName)
Call DispCallFunc(0, pFunc, 1&, vbLong, ...., ...., ....., CallFunc)
End Function
Re: Static linking of .obj/.lib from other languages now available
Is there anything that should be configured when compiling .libs?Project:https://github.com/PCRE2Project/pcre2. i used cmake&visual studio to compile the libs. When I just import libs,an error "Syntax error. No handler for this symbol" is raised.