Hi everybody,

I have a legacy program at work that I have taken over and my boss wants me to add some functionality. I have already added a com object to the program and am producing a functional dll which I can write strings to and control my program. I however am having huge difficulties reading strings back from dll into my vb.net application. I have been googling for a week or so and have admittedly found a couple of examples but none of which solve my problem or even get me a bit closer.

The c++ side of life:

BSTR STDMETHODCALLTYPE Diag_Receive(BSTR* message);

 BSTR STDMETHODCALLTYPE TExtensionCordComImpl::Diag_Receive(BSTR* message)
{
  try
  {
  BSTR bstMessage=NULL;
  bstMessage=SysAllocStringByteLen(NULL,(sizeof(ExtCordMainForm->TxDiagMessageRxEdit->Text)*2)+1);
  HexFromBin((LPBYTE)(BSTR)ExtCordMainForm->TxDiagMessageRxEdit->Text.c_str(),sizeof(ExtCordMainForm->TxDiagMessageRxEdit->Text),(LPSTR)bstMessage);
  *message=(BSTR)(ExtCordMainForm->TxDiagMessageRxEdit->Text.c_str() );

   return bstMessage;
  }
  catch(Exception &e)
  {
    //return (BSTR)"NULL";
  }

};

The .net side of life:

Public Declare Ansi Function GetDiag Lib "D:\Documents and Settings\meberlein\My Documents\Computer Switch\Visual Studio 2008\Projects\ComUnitTest\ComUnitTest\obj\Debug\Interop.ExtensionCord.dll" (<MarshalAs(UnmanagedType.BStr)> ByVal message As String) As String


        Dim str As String = "Version Info OMAP"
        Dim message As String = ""
        Dim rtnmessage As String = ""
        ExtensionCord.Diag_Send(str)
        Threading.Thread.Sleep(1000)
        Try
            rtnmessage = GetDiag(message)
        Catch ex As Exception

        End Try
        Me.Text = message + " " + rtnmessage

Any help is greatly appreciated.

Sincerely,
Mike

>>sizeof(ExtCordMainForm->TxDiagMessageRxEdit->Text)*2)+

The sizeof operator doesn't work on std::string objects because sizeof will return the size of the c++ class, not the string which it manages. You should use Text.size() or Text.length() to get the length of the string

Next that line seems to be allocating enough space for wchar_t UNICODE string. If that is the case then it isn't allocating enough space for the null terminator. Should be (Text.size()+1) * sizeof(wchar_t)) because the sizeof(wchar_t) is machine or operating system dependent. MS-Windows it is normally 2 but *nix is normally 4. And it could be even larger. So you can't assume that sizeof(wchar_t) is always 2.

On line 9 of the c++ code you posted you might replace it with just some hard-coded string such as "Hello World" just to see if your dll works with the vb program. If that works then there is probably some problem with the functin call on line 9.

Edited 6 Years Ago by Ancient Dragon: n/a

That doesn't seem to be the ticket.

try
  {
  BSTR bstMessage=NULL;
  bstMessage=SysAllocStringByteLen(NULL,(ExtCordMainForm->TxDiagMessageRxEdit->Text.Length()*sizeof(wchar_t))+1);
  HexFromBin((LPBYTE)(BSTR)ExtCordMainForm->TxDiagMessageRxEdit->Text.c_str(),ExtCordMainForm->TxDiagMessageRxEdit->Text.Length()+1,(LPSTR)bstMessage);
  *message=(BSTR)(ExtCordMainForm->TxDiagMessageRxEdit->Text.c_str() );

   bstMessage=(BSTR)"HELLO";
   *message=(BSTR)"WORLD";
   return bstMessage;
  }
  catch(Exception &e)
  {
    //return (BSTR)"NULL";
  }

I think the .net Side should look more like this

Public ExtensionCord As New ExtensionCord.ExtensionCordCom
.
.  
.      
Dim str As String = "Version Info OMAP"
        Dim message As String = ""
        Dim rtnmessage As String = ""
        ExtensionCord.Diag_Send(str)
        Threading.Thread.Sleep(1000)

        rtnmessage = ExtensionCord.Diag_Receive(message)

        Me.Text = message + " " + rtnmessage

unfortunately when I try to run it like that I get the following exception

System.AccessViolationException was unhandled
  Message="Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
  Source="Interop.ExtensionCord"
  StackTrace:
       at ExtensionCord.ExtensionCordComClass.Diag_Receive(String& Message)    at ExtensionCord_Vehicle.Form1.Button7_Click(Object sender, EventArgs e) in D:\Documents and Settings\meberlein\My Documents\Computer Switch\Visual Studio 2008\Projects\ComUnitTest\ComUnitTest\Form1.vb:line 45    at System.Windows.Forms.Control.OnClick(EventArgs e)    at System.Windows.Forms.Button.OnClick(EventArgs e)    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)    at System.Windows.Forms.Control.WndProc(Message& m)    at System.Windows.Forms.ButtonBase.WndProc(Message& m)    at System.Windows.Forms.Button.WndProc(Message& m)    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)    at System.Windows.Forms.Application.Run(ApplicationContext context)    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()    at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)    at ExtensionCord_Vehicle.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81    at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)    at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)    at System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel)    at System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly()    at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData)    at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext)    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()    at System.Threading.ThreadHelper.ThreadStart_Context(Object state)    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)    at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

By the way this is windows XP with visual studio 2008 and the c++ ide is borland c++ builder 6.

Thank you,
Mike

It didn't work because you can't typecast char* to wchar_t* (lines 8 and 9 of c++ code). Try this in your c++ dll

#include <Windows.h>
#include <iostream>
using std::cout;
using std::wcout;
 
BSTR  Diag_Receive(BSTR* message)
{
  BSTR bstMessage;
  wchar_t msg[] = L"Hello World";
  bstMessage=SysAllocStringLen(msg,sizeof(msg));

 
  return bstMessage;
 
};

Edited 6 Years Ago by Ancient Dragon: n/a

That seems to make things a fair amount happier but I still get an empty string. There is no corrupt memory problem however.

Thank you very much for your help. Please keep the ideas coming.

This article has been dead for over six months. Start a new discussion instead.