Search code examples
c++.netvb.netpinvoke

C++ DLL Returns only first Character to VB Application


One of our technicians asked my to write a small library file in which he would pass a filename and an integer. The library would load the text file and find the integer in the text file referenced by the file name and return a string back to his program. He is working in a third party application that uses VB as its scripting language.

So, not wanting to worry about the .net install on some of the older machines that he has his equipment installed on I decided to take a crack at C++ (VS 2010). I am doing applications development in C# and the last time I compiled any C++ code was in VS 6, but I though how hard can it be? Well I am typing here so things have taken a decidedly wrong turn. I started out with the C++ Side.

#include <WTypes.h>
#include <comutil.h>
#include <string.h>

BSTR _stdcall regExConv(BSTR fileName, int modNumber);

BSTR _stdcall regExConv(BSTR fileName, int modNumber) {
    string inText;
    // open the file and read in the text from the file
    ifstream testFile;
    testFile.open("C:\\Test\\testFile.txt", ifstream::in);
    if(testFile.fail())
        MessageBox(NULL,L"Failed to Open", NULL, NULL);
    while (testFile.good())
        getline(testFile, inText);
    testFile.close();
    _bstr_t passString(inText.c_str());
    BSTR finalPass = passString.copy();
    return finalPass;
}

That works fine. The finalPass gives me the test string that I have in the text file.

Locals Window:

inText  "eeeeeeeee" std::basic_string<char,std::char_traits<char>,std::allocator<char> >

passString  {"eeeeeeeee" (1)}   _bstr_t

finalPass   0x00722214 "eeeeeeeee"  wchar_t *

On the VB side I have this.

Public Class Form1
    Private Declare Function testFunc Lib "c:\Development\gTP3200\Debug\gTP3200.dll" (ByVal testVar As Integer) As Integer
    Private Declare Function stringTest Lib "c:\Development\gTP3200\Debug\gTP3200.dll" (ByVal Str As String) As String
    Private Declare Function regExConv Lib "c:\Development\gTP3200\Debug\gTP3200.dll" (ByVal fileString As String, ByVal faultedMod As Integer) As String
    Private Declare Function stringBack Lib "c:\Development\gTP3200\Debug\gTP3200.dll" () As String

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim retVal As String
        retVal = regExConv("file name pass", 3)
    End Sub
End Class

The two are talking just fine, issue is the string returned to the VB side is just the first character from inText.

Locals Window:

retVal  "e" String

For two days now I have tried to read everything that I can about it but I am starting to feel like im in a bad Monty Python skit. Nothign seems to work. I have tried to convert the string to various other types then back to the BSTR. Tried SysAlloc, didnt work.

If I pass a String to a BSTR as a parameter then pass it back again (like the file name) then the VB side reads in the entire string.


Solution

  • Have your tried MarshalAs?

    Private Declare Function stringBack Lib "c:\Development\gTP3200\Debug\gTP3200.dll" () As <MarshalAs(UnmanagedType.BStr)> String