0

From Visual Basic I need to call a function in a dynamic link library (DLL) which is implemented in C. The C function has the signature

uint32_t F(char **str);

where str is an output parameter. The array *str is expected to be at least n characters long. On the Visual Basic side the function is declared as

<DllImport("lib.dll", CallingConvention:=CallingConvention.Cdecl)> _
Public Shared Function F(ByRef str As String) As UInteger
End Function

How do I declare a string of length n in Visual Basic which is compatible with the formal parameter of the C function F?

Edit: The function call works as expected if I declare the actual parameter as for instance

Dim str As String = "          "

assuming n is 10. However, n is a variable.

djv
  • 15,168
  • 7
  • 48
  • 72
August Karlstrom
  • 10,773
  • 7
  • 38
  • 60

3 Answers3

2

The String in VB is actually a BSTR on the C side, which is a struct in the Windows API.

On the C side, you use Windows functions like SysAllocString to manufacture a BSTR, and free the memory with a SysReleaseString.

You will not be able to interop (easily) with uint32_t F(char **str); between C and VB.

Further reading: https://learn.microsoft.com/en-gb/previous-versions/windows/desktop/automat/string-manipulation-functions

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • The function call works as expected if I declare str as `Dim str As String = " ... "` (with *n* spaces), but I want to set the length dynamically (without constructing a string of *n* spaces). – August Karlstrom Oct 18 '19 at 14:24
  • This doesn't really address the question of how to interop with an existing function. There is support for interop with native C strings. It's also not correct - the native .NET string type is not a BSTR, that is only true of the VBA lineage. – Craig Oct 21 '19 at 13:29
1

You can pad a string with n spaces.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim s As String = ""
    Dim n As Integer = 10
    Dim paddedStr = s.PadRight(n)
    Debug.Print(paddedStr.Length.ToString) 'Prints 10
End Sub
Mary
  • 14,926
  • 3
  • 18
  • 27
  • 2
    A more direct route would be to use the [String(Char, Int32) constructor](https://learn.microsoft.com/en-us/dotnet/api/system.string.-ctor?view=netframework-4.8#System_String__ctor_System_Char_System_Int32_). Something like: `Dim s as New String(ChrW(0), 10)`. – TnTinMn Oct 19 '19 at 21:20
  • @TnTinMn Yes, this works like a charm. If you turn your comment into an answer I can accept it. – August Karlstrom Oct 21 '19 at 12:35
  • @AugustKarlstrom, please just accept Mary's answer if this is the route you want to pursue. She is more than welcome to roll my comment into the answer. IMHO, while a declared length string works, the overall usage seems wrong when viewed from a .Net perspective and using a StringBuilder would be more typical. – TnTinMn Oct 21 '19 at 13:45
1

As mentioned by TnTinMn in one of the comments, declare the actual argument like this:

Dim str As New String(ChrW(0), n)
August Karlstrom
  • 10,773
  • 7
  • 38
  • 60