Using Nim to Creating a vb6 dll that Returns String

Viewed 92

Nim Compiler Version 1.6.6 [Windows: i386]
Compiled at 2022-05-05
Copyright (c) 2006-2021 by Andreas Rumpf
active boot switches: -d:release

Cmd Compile nim c --cpu:i386 -d:release --app:lib --nomain mydll.nim

Hi there, I was able to return a Long value, now I'm trying to get string values.

I googled to find some exemples and find out here: https://my.oschina.net/yuekcc/blog/775990

I'm getting this error:

enter image description here

VB6:

Private Declare Function MyStr Lib "mydll.dll" (ByVal s As String) As String
Private Declare Function return_multiply Lib "mydll.dll" Alias "return_multiply@8" (ByVal a As Long, ByVal b As Long) As Long

Private Sub Form_Click()
  MsgBox MyStr("?")  'error
  MsgBox return_multiply(5, 4) 'ok
End Sub

Another question, why the Alias has @8 at the end? return_multiply@8

Nim:

import encodings

const
    vbCodePage = "GB2312"
    vbTrue* = 1
    vbFalse* = 0

type
    VBString* = cstring
    VBBoolean* = int32

proc MyStr*(): cstring {.stdcall, exportc, dynlib.} =
  result = $"teste"

proc fromVBString*(a: VBString): string =
    return encodings.convert($a, "UTF-8", vbCodePage)

proc toVBString*(a: string): VBString =
    return VBString(encodings.convert(a, vbCodePage, "UTF-8"))

proc return_multiply*(a, b: int): int {.stdcall, exportc, dynlib.} =
    a * b
2 Answers

Since you want to export toVBString in the dynamic library, you have to add the exportc, dynlib pragmas to it as to others:

proc toVBString*(a: string): VBString {.exportc, dynlib, stdcall.} =
    return VBString(encodings.convert(a, vbCodePage, "UTF-8"))

But the definition is wrong anyway - I don't know what type VB's String is, but it certainly is different from the Nim string, and I'm not sure why you are importing it in your VB program.

Also, I don't think it's correct to just convert the Nim string to cstring to pass it to VB - Nim's cstring doesn't actually "own" the string data, so when the Nim runtime frees the Nim string, the cstring of it will point to invalid data. I don't know if VB has specific APIs for that or not though.

I know nothing about Nim, but the way to create a VB string is to make an OLE BSTR. SysAllocStringLen() would probably be your best bet. Others in that family might be better depending on what your string data looks like and where it comes from. Check out the MS docs.

Related