Home All Groups Group Topic Archive Search About

How to correctly invoke next DLL from Visual Basic?

Author
19 May 2009 10:41 PM
Eduardo
I have next C/C++ source DLL library (heading, definition and C++ files):

c_dll_4_vb.h
========
class stNivAut {
public:
   long nivel;
   long uniOrg;
   char txtUniOrg[41];
   long pernr;
   char nomCompleto[81];
};
stNivAut nivAut[5];
long __declspec(dllexport) __stdcall getNivAut(stNivAut *);


c_dll_4_vb.def
==========
LIBRARY dll01
EXPORTS
  getNivAut @1


c_dll_4_vb.cpp
==========
#include <string.h>
#include "c_dll_4_vb.h"

long getNivAut(stNivAut * nivAut)
{
  nivAut[0].nivel = 3;
  nivAut[0].uniOrg = 3004000;
  strncpy_s(nivAut[0].txtUniOrg, "IT Corporate", 12);
  nivAut[0].pernr = 3005000;
  strncpy_s(nivAut[0].nomCompleto, "Andrew Lindon", 13);

  nivAut[1].nivel = 2;
  nivAut[1].uniOrg = 3004001;
  strncpy_s(nivAut[1].txtUniOrg, "IT CEO", 6);
  nivAut[1].pernr = 3005002;
  strncpy_s(nivAut[1].nomCompleto, "Philip Gonzáles", 15);

  nivAut[2].nivel = 1;
  nivAut[2].uniOrg = 3004002;
  strncpy_s(nivAut[2].txtUniOrg, "President", 9);
  nivAut[2].pernr = 3005003;
  strncpy_s(nivAut[2].nomCompleto, "Franz Gardiner", 14);

  return 0;
}


I wrote next main C++ program to invoke the .DLL library:
#include <stdio.h>
#include "c_dll_4_vb.h"

int main()
{
   int val = getNivAut(nivAut);
   printf("%d %s %s\n",
       nivAut[1].pernr, nivAut[1].nomCompleto, nivAut[1].txtUniOrg);
   return 0;
}

Getting next result:
3005002 Philip Gonzßles IT CEO


I need to do same main program but in Visual Basic so I coded next one but I
have problems: program compiles well but aborts without explanation when
executed, the VB code is:

Private Declare Function getNivAut _
      Lib "C:\msApps\myTests\dll01\Debug\dll01.dll" _
                     (ByRef nivAut() As stNivAut) As Long
  Type stNivAut
     nivel As Long
     uniOrg As Long
     txtUniOrg As String * 41
     pernr As Long
     nomCompleto As String * 81
  End Type

Private Sub Form_Load()
  Dim nivAut(5) As stNivAut
  lRetVal = getNivAut(nivAut)
  MsgBox (Str(nivAut(1).pernr) & " " & nivAut(1).nomCompleto & _
    " " & nivAut(1).txtUniOrg)
End Sub

What is wrong with this VB code?
Thanks for your attention ... and help.
Eduardo.

Author
20 May 2009 1:21 AM
Jim Mack
Eduardo wrote:
Show quoteHide quote
> I have next C/C++ source DLL library (heading, definition and C++
> files):
>
> c_dll_4_vb.h
> ========
> class stNivAut {
> public:
>    long nivel;
>    long uniOrg;
>    char txtUniOrg[41];
>    long pernr;
>    char nomCompleto[81];
> };
> stNivAut nivAut[5];
> long __declspec(dllexport) __stdcall getNivAut(stNivAut *);
>
>
> c_dll_4_vb.def
> ==========
> LIBRARY dll01
> EXPORTS
>   getNivAut @1
>
>
> c_dll_4_vb.cpp
> ==========
> #include <string.h>
> #include "c_dll_4_vb.h"
>
> long getNivAut(stNivAut * nivAut)
> {
>   nivAut[0].nivel = 3;
>   nivAut[0].uniOrg = 3004000;
>   strncpy_s(nivAut[0].txtUniOrg, "IT Corporate", 12);
>   nivAut[0].pernr = 3005000;
>   strncpy_s(nivAut[0].nomCompleto, "Andrew Lindon", 13);
>
>   nivAut[1].nivel = 2;
>   nivAut[1].uniOrg = 3004001;
>   strncpy_s(nivAut[1].txtUniOrg, "IT CEO", 6);
>   nivAut[1].pernr = 3005002;
>   strncpy_s(nivAut[1].nomCompleto, "Philip Gonzáles", 15);
>
>   nivAut[2].nivel = 1;
>   nivAut[2].uniOrg = 3004002;
>   strncpy_s(nivAut[2].txtUniOrg, "President", 9);
>   nivAut[2].pernr = 3005003;
>   strncpy_s(nivAut[2].nomCompleto, "Franz Gardiner", 14);
>
>   return 0;
> }
>
>
> I wrote next main C++ program to invoke the .DLL library:
> #include <stdio.h>
> #include "c_dll_4_vb.h"
>
> int main()
> {
>    int val = getNivAut(nivAut);
>    printf("%d %s %s\n",
>        nivAut[1].pernr, nivAut[1].nomCompleto, nivAut[1].txtUniOrg);
>    return 0;
> }
>
> Getting next result:
> 3005002 Philip Gonzßles IT CEO
>
>
> I need to do same main program but in Visual Basic so I coded next
> one but I have problems: program compiles well but aborts without
> explanation when executed, the VB code is:
>
> Private Declare Function getNivAut _
>       Lib "C:\msApps\myTests\dll01\Debug\dll01.dll" _
>                      (ByRef nivAut() As stNivAut) As Long
>   Type stNivAut
>      nivel As Long
>      uniOrg As Long
>      txtUniOrg As String * 41
>      pernr As Long
>      nomCompleto As String * 81
>   End Type
>
> Private Sub Form_Load()
>   Dim nivAut(5) As stNivAut
>   lRetVal = getNivAut(nivAut)
>   MsgBox (Str(nivAut(1).pernr) & " " & nivAut(1).nomCompleto & _
>     " " & nivAut(1).txtUniOrg)
> End Sub
>
> What is wrong with this VB code?
> Thanks for your attention ... and help.
> Eduardo.

You're declaring the function in VB as expecting an array of nivAut,
but the DLL is not returning a VB array, that is, a SafeArray. It's
returning a vector, which VB doesn't consider an array.

Your best bet is to create and populate a SafeArray in the DLL. Look
at SafeArrayCreate and related OLE functions.

Also, you may need to place the definition of stNivAut as a Public
Type in a standard module in order for VB to handle it as a parameter
to an external function.

Once you get that straightened out, you will have Unicode issues
because when VB passes an array of a UDT containing strings, it uses
Unicode strings, and if I read your DLL code correctly, you're not
using wchar[] in your class.

If that's true, then you could change the VB side to use:

      txtUniOrg(1 to 41) As Byte
      nomCompleto(1 to 81) As Byte

...or change the DLL code to use wchar.

--
   Jim Mack
   Twisted tees at http://www.cafepress.com/2050inc
   "We sew confusion"