views:

445

answers:

2

I have written my own function, which in C would be declared like this, using standard Win32 calling conventions:

int Thing( char * command, char * buffer, int * BufSize);

I have the following amount of VB figured out, which should import the dll and call this function, wrapping it up to make it easy to call Thing("CommandHere",GetDataBackHere).

UPDATE:This code is now a working solution, as shown here:

 Imports Microsoft.VisualBasic
Imports System.Runtime.InteropServices
Imports System
Imports System.Text

Namespace dllInvocationSpace

    Public Class dllInvoker
        ' tried attributes but could not make it build:
        ' <DllImport("thing1.dll", False, CallingConvention.Cdecl, CharSet.Ansi, "Thing", True, True, False, True)>
        Declare Ansi Function Thing Lib "thing1.dll" (ByVal Command As String, ByRef Buffer As StringBuilder, ByRef BufferLength As Integer) As Integer

        ' this part contributed by helpful user:
  Shared Function dllCall(ByVal Command As String, ByRef Results As String) As Integer
      Dim Buffer As StringBuilder = New StringBuilder(65536)
      Dim Length As Integer = Buffer.Capacity
      Dim retCode As Integer = Thing(Command, Buffer, Length)
      Results = Buffer.ToString()
      'Debug.Assert(Results.Length = Length)  ' this assertion is not true for me
      Return retCode
  End Function


    End Class
End Namespace

Updates: I got the code to build by following the help received here, and then I had forgot the As Return Type (which got me a MarshalDirectiveException PInvokeRestriction). Then I had an assertion failure inside my DLL, which lead to an SEHException. Once fixed, this works BEAUTIFULLY. Thank you folks. There are newsgroups where people are saying this can not be done, that VB only loads managed dll assemblies (which I guess is the normal thing most VB users are used to).

A: 

You cannot convert a StringBuilder instance to a string instance, instead, use the 'ToString' method to convert it back to the string type...here's the portion of the code in the dllCall function...

retCode = Thing(Command, Buffer, bufsz)
Results = Buffer.ToString();
tommieb75
That was a stupid brain fart by me. Now I'm stuck at the marshall exception (pinvoke restriction) exception. Thanks tho.
Warren P
+1  A: 

It depends on how you use the buffer argument in your C code. If you only pass a string from your VB.NET code to your C code then declaring it ByVal String is good enough. If however you let the C code return a string in the buffer then you have to declare it ByVal StringBuilder and initialize it properly before the call. For example:

Public Class dllInvoker
    Declare Ansi Function Thing Lib "Thing1.dll" (ByVal Command As String, ByVal Buffer As StringBuilder, ByRef BufferLength As Integer) As Integer

    Shared Function dllCall(ByVal Command As String, ByRef Results As String) As Integer
        Dim Buffer As StringBuilder = New StringBuilder(65536)
        Dim Length As Integer = Buffer.Capacity
        Dim retCode As Integer = Thing(Command, Buffer, Length)
        Results = Buffer.ToString()
        Debug.Assert(Results.Length = Length)
        Return retCode
    End Function
End Class

Note the ambiguity in the returned Length value.

Hans Passant
INteresting. I still get a MarshalDirectiveException although I'm sure the code you sent is more correct than mine was.Thing1.dll is not the actual DLL name, but one thing that concerns me is that if I put in "foo3290809.dll" (which does not exist) I get the same MarshaleDirectiveException - "PInvoke restriction: cannot return variants"
Warren P
@Warren: Check my declaration, it returns an Integer. You'll have to use the scrollbar to see it.
Hans Passant
Okay I am now caught up. with Declare Ansi Function Thing Lib "Thing1.dll" (ByVal Command As String, ByVal Buffer As StringBuilder, ByRef BufferLength As Integer) As Integer, I still get SEHException
Warren P
@Warren: now you need to debug your C code.
Hans Passant
It is possible that my dll is being loaded and that the crash is now inside my DLL (which is puzzling). I will debug and update my question tomorrow AM.
Warren P
That was it. An assertion failure inside my code that I least expected to go off, did.
Warren P