Results 1 to 7 of 7

Thread: How to statically link a LIB or OBJ file in VB6!

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    How to statically link a LIB or OBJ file in VB6!

    There is a kinda hacky way to do this actually! I realized that there's no way to statically link the code so that it can be called like a normal function, as VB6 IDE won't even try to compile something if the function is not specifically defined in the code (unlike C or C++ where it the compilation goes fine, and then the linker needs to figure out if that function exists in any external OBJ, LIB, or DLL files referenced in the linker's command line). In VB6 the IDE will immediately give an error in this situation when you click the "Make Project1.exe" menu item in the File menu. But there is a way to call DLL functions using Declare statements. I know that when using a declare statement, compilation will work fine, and then you will get a runtime error if the DLL isn't found when you try to run the program.

    So I figured that since this delays the point at which the function needs to be available, maybe I could actually export the function from the EXE, as if it were a DLL (as both are PE files, so theoretically EXEs support an export table, just like DLLs), and then import it back in the same EXE for executing it (though technically it's not importing it the standard way via an import table, as it actually is creating pieces of code that call LoadLibrary and GetProcAddress internally followed by jumping to the address it gets from GetProcAddress, so even the linker doesn't need to process this, as it won't be creating an import table).

    It turns out, that worked! For testing it, I used the same ASM function I used in https://www.vbforums.com/showthread....-a-VB6-program but this time tweaked the ASM code slightly so the resulting object file would contain the info needed to get the linker to first link the OBJ into the EXE, and then export the function from the EXE. Normally the linker needs an /EXPORT command line argument to export a function, but an object file can also contain an export directive so that the linker will automatically export the desired function. This latter technique is the one I used. That way, I only needed to add one thing to the VB6 linker command line, not 2 things, to get it to work. No need for the /EXPORT command line argument, just the path to the OBJ file that was generated from the NASM assembler.

    Note that for this trick to work, you need to rename the VB6 linker to something else, and then create your own program called link.exe that lets you edit the command line before calling the actual linker (under its new name). This way when you click "Make Project1.exe" it actually calls your proxy first, which gives you control of the linker command line, before passing that now-edited command line to the actual linker.

    Here's the code for my VB6 program.
    Code:
    'Import the function from the EXE file itself. This only works if the EXE exports it, which requires
    'a proxy linker to replace the normal linker (with the normal linker renamed and called from the
    'proxy), to give you access to the command line arguments. In this example you will need to make
    'sure that it links shr.obj into the EXE file.
    'Also the object file must have been made from some external source that supports the technique you
    'wish to use. In this case, I used NASM to make a function called SHR which uses the x86 instruction
    'shr. NASM assembled the assembly code into an object file, which (with a proxy linker to edit VB6's
    'linker command line) will be linked into the EXE file, and since the assembly code stated that the
    'function is exported, the resulting EXE file will export the function, and the below Declare will
    'import it back into the same EXE. Not an ideal way to do static linking, but this trick is the only
    'way to do it in VB6 using actual object files (should also work with LIBs that have multiple object
    'files in them).
    
    Private Declare Function SHR Lib "Project1.exe" (ByVal Value As Long, ByVal ShiftAmount As Byte) As Long
    
    
    Private Sub Form_Load()
        Dim n As Long
    
        'Perform a test where it performs 32 different shifts (no shift, up to 31 bits shifted) on the hex value &hFFFFFFFF.
        'Note that with the static linking technique, this will ONLY work in the compiled EXE file, not in
        'the VB6 IDE, as static linking only occurs when generating the EXE file, not when running in the
        'VB6 IDE.
        For n = 0 To 31
            Print Hex$(SHR(&HFFFFFFFF, n))
        Next n
    End Sub
    Here's the ASM code I used.
    Code:
    BITS 32
    
    GLOBAL SHR
    EXPORT SHR
    
    SECTION .text
    
    SHR:
    mov eax,[esp+4]
    mov cl,[esp+8]
    shr eax,cl
    ret 8
    The BITS 32 statement sets it to 32bit mode (NASM outputs 16bit code by default).
    The GLOBAL SHR statement tells NASM to set a bit associated with the function SHR in the OBJ file, that tells any linker reading the OBJ file that the function can be used by other functions outside of that specific OBJ file (it's kinda like the Public keyword in VB6). The EXPORT SHR statement adds the function SHR to an export table in the OBJ file. Both the GLOBAL and EXPORT statements are needed to generate an OBJ file that when read by the VB6 linker the function will actually be added to the EXE file's export table. Same trick should work with a static LIB file, which is just a file that contains one or more OBJ files.

    When all of this is done correctly, the function's machine code actually is added to the EXE file's code section directly (not contained in a hexadecimal string), that can then be executed in the same way that VB6 executes DLL functions, but since the code is in the EXE file itself, it doesn't require the presence of an external file like with an actual DLL file. This eliminates the need for using CallWindowProc or other function-calling functions, and also eliminates the need to have a dedicated function to convert hexadecimal string to raw bytes, and also eliminates the need to have a bunch of extra strings or byte array to hold the converted bytes. The code for the function instead is linked directly into the EXE file, along side all the code of the main program.

    Please note that because this technique requires external software (the NASM assembler, and a proxy linker for VB6 that intercepts the command line for the VB6 linker), the code I have here is NOT usable as-is (unlike most of the code in the codebank). You can't just copy it all straight into your VB6 IDE and run it for immediate results. You'll need to first get a copy of NASM and assemble the ASM code in this post into an OBJ file, as well as write your own proxy linker program.

    Note that when using NASM.exe, its default output is raw machine code (aka a "flat binary" file), not any kind of object file. You'll need to use the command line args "-f win32" to make it generate a 32bit Windows COFF object file as its output. That's what the VB6 linker expects for its input.

    Yes, I tested everything in I wrote in this post, and it does work.
    Last edited by Ben321; Sep 22nd, 2021 at 05:37 AM. Reason: fixed typo

  2. #2

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: How to statically link a LIB or OBJ file in VB6!

    Here's a screenshot of the output of the program running.

  3. #3
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,235

    Re: How to statically link a LIB or OBJ file in VB6!

    Very interesting indeed.

    If I can offer some help on your posts, for the image attachments to work on your posts, host them externally at imgur or similar and when embedding don't use the option to reference locally. The forum currently has problems linking images and it fails to display quite often. The way I suggest above works every time for me.
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  4. #4
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,235

    Re: How to statically link a LIB or OBJ file in VB6!

    Can we see your proxy linker program code too?
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  5. #5
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,121

    Re: How to statically link a LIB or OBJ file in VB6!

    Quote Originally Posted by Ben321 View Post
    Note that for this trick to work, you need to rename the VB6 linker to something else, and then create your own program called link.exe that lets you edit the command line before calling the actual linker (under its new name). This way when you click "Make Project1.exe" it actually calls your proxy first, which gives you control of the linker command line, before passing that now-edited command line to the actual linker.
    This is exactly what this proxy linker is meant to do. It allows you to selectively swap OBJ files with different precompiled ones (ASM or C/C++ based ones).

    The idea is to place same named external (precompiled) object files with extension COBJ into the target folder where EXE/DLL is built to. So if you want to swap out mdSqlite.bas just place a mdSqlite.cobj into target folder.

    Unfortunately it's buggy and I don't have time to fix it so the repo is archived :-))

    cheers,
    </wqw>

  6. #6
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,057

    Re: How to statically link a LIB or OBJ file in VB6!

    Jim White had a nice linker replacement too, have not used it to much but was stable

    https://github.com/dzzie/addins/tree/master/LinkTool

    end of the day I just prefer writing a standard C dll and including it.
    just easier to work on and maintain in the long run.
    Last edited by dz32; Sep 22nd, 2021 at 07:33 AM.

  7. #7

Posting Permissions

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



Click Here to Expand Forum to Full Width