3

After many hours of trying to figure out this problem I'm wondering if there even is a way of doing it.

I need to be able to export functions that are called from VB6 (yes you read that correctly, not VB.NET) and I'm at a loss. I got as far as generating a DLL that should have worked; it worked when being called from C at least, but nothing further.

Maybe some Nim vet can steer me in the right direction. I would be immensely greatful.

SLWW
  • 89
  • 7
  • 2
    If you want something that's callable from VB6 (you do know that that went out of support in, I think, 2005), you are going to want to make your "DLL" export things as an `IDispatch' compatible COM object. That's reasonably easy to do with C# (find a copy of Adam Nathan's ".NET and COM" book) – Flydog57 Jul 15 '21 at 20:58
  • 3
    @Flydog57 - I know nothing about Nim, but a DLL *callable* from VB6 doesn't need a COM interface. You can use the Declare method, which just requires `StdCall` -- like most of the Win32 API. – Jim Mack Jul 15 '21 at 21:41
  • 2
    @jimmack, but, if you are working in C#, COM is likely the way to go. I have no idea about Nim either – Flydog57 Jul 15 '21 at 21:54
  • @JimMack so if i were to try exporting a function it would have to be a stdcall (a static call i presume) and see where that gets me? – SLWW Jul 15 '21 at 23:21
  • @Flydog57 yes but unfortunately legacy support is still a thing :( – SLWW Jul 15 '21 at 23:22
  • @Flydog57 - Definitely so, though there are ways of calling non-COM functions from C#. But I only meant to address the notion that to be used in VB6, it *had* to be COM. – Jim Mack Jul 16 '21 at 01:05
  • 2
    @SLWW - Yes. If you can create a COM dual-interface then by all means do that. But just to invoke a function from VB6, all you need is a DLL entry point -- a named, declared function. – Jim Mack Jul 16 '21 at 01:07
  • @jimmack, how would you create an `StdCall` export from a C#-coded assembly, and how would you call it with anything but the simplest of _blittable_ typed parameters. COM provides an infrastructure to do this. Making a C# type COM-exported is pretty easy – Flydog57 Jul 16 '21 at 02:35
  • @slww. Yes, legacy support is a thing (I've done _a lot_ of that over the past decades). Supporting 25 year old technologies that have been abandoned by their publishers for 15 years is inviting security vulnerabilities – Flydog57 Jul 16 '21 at 02:39
  • 1
    @Flydog57 - I think the OP wanted the opposite: a DLL created in some other language that can be called by VB6 and C#, not something created in C#. Calling `StdCall` functions from C# ('unmanaged') is possible, but not ideal. We have no idea what parameters he needs, but if he's calling this from VB6 they're very likely OLE compatible types, and in-process, so unmarshalled. – Jim Mack Jul 16 '21 at 03:15
  • @jimmack. I read a question, tagged as `C#`, that says _"I need to be able to export functions that are called from VB6"_. That's what I answered. Sure, C# can call C-coded functions via P/Invoke. But with VB6 calling into C#, COM is the way to go. – Flydog57 Jul 16 '21 at 04:05
  • 1
    There are of course many good reasons to migrate from VB6. But the [VB6 runtime is still fully supported](https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-basic-6/visual-basic-6-support-policy) & updated as part of Windows, so there's no extra risk of security vulnerabilities and VB6 hasn't been abandoned by its publishers. – MarkJ Jul 16 '21 at 13:27
  • A DLL callable from C is also most likely usable from VB6. If you load your DLL in a tool like Dependencies (https://github.com/lucasg/Dependencies) what do you see in the list of exported functions (lower pane)? If you can, I would add a screenshot of that to the question (just edit the Q and paste the image). – StayOnTarget Jul 17 '21 at 12:05
  • As @JimMack pointed out, StdCall calling convention is important for a native 32-bit DLL to be (easily) callable by VB6. Not sure in which language you're proficient in, but if you "speak" BASIC, are willing to invest USD 50, you can use [PowerBASIC's Windows compiler](https://www.powerbasic.com/powerbasic-compiler-for-windows) (v8 does the job) to create native 32-bit DLLs for consumption by VB6. It's [help file](https://help.powerbasic.com/PBWIN8/PBWIN.htm) even has a dedicated _Working with VB6_ section. I've used it more than a decade to enhance VB6. – Hel O'Ween Jul 19 '21 at 14:27
  • @Flydog57 Absolutely right, this is a component-by-component rewrite we are doing so as to still support current users while changing out the old cruft in a systematic way – SLWW Jul 19 '21 at 19:28
  • this post from 2016 has an example which might still work: https://www.euantorano.co.uk/posts/nim-with-c-sharp-net/ – pietroppeter Jul 26 '21 at 17:50

1 Answers1

4

I'm definitely not a Nim vet, but here is something that works.
Calling Nim proc from VB6 application.

Nim DLL (compile with nim c --cpu:i386 --app:lib --nomain):

{.passc:"-m32"}
{.passl:"-m32"}
import winim,os

proc TestFunc(a: cint):cint {.exportc, stdcall, dynlib.} =
    echo "function called!"
    a + 5

when defined(vcc):
    {.emit: "N_LIB_EXPORT N_CDECL(void, NimMain)(void);".}
else:
    proc NimMain() {.cdecl, importc.}

proc DllMain(hModule: HINSTANCE, reasonForCall: DWORD, lpReserved: LPVOID): WINBOOL {.exportc, dynlib, stdcall.} =
    case reasonForCall:
    of DLL_PROCESS_ATTACH:
        when defined(vcc):
            {.emit: "NimMain();".}
        else:
            NimMain()
        AllocConsole()
        discard stdout.reopen("CONOUT$", fmWrite)
        discard execShellCmd("chcp 65001")
        echo "Hello from Nim Code!"

    else:
        discard
    return TRUE

VB6:

Private Declare Function TestFunc Lib "nim.dll" Alias "TestFunc@4" (ByVal a As Long) As Long

Private Sub Form_Load()
    Caption = CStr(TestFunc(5))
End Sub
  • That worked! Much thanks, although i will say that when compiling on my machine (with vcc) the Alias should be "_TestFunc@4" but other then that this works surprisingly well – SLWW Jul 26 '21 at 19:52
  • @Юра-Векша Could you please try to answer the same question but returning string? https://stackoverflow.com/questions/72952227/using-nim-to-creating-a-vb6-dll-that-returns-string – huvdev4 Jul 12 '22 at 21:46