Calling C++ 64 bit dlls from vb.net


  • I've had to move to 64 bit  under Vista to get access to more memory space.  I'm running a mixed vb.net and c++ program


    I've managed to create 64 bit versions of both the VB and the C++ using Visual Studio 2005 and I've managed to get the VB code to call the c++ code and can pass variables by value.  However, I can't seem to pass arrays by reference.


    I've written a little test to demonstrate.  The code is shown below:


    Visual basic calling code


    Private Declare Function return8 Lib "C:\test\test8.dll" (ByRef a As single) As double


    sub call()

    dim a(10) as single

    dim x as double


    x = return8( a(0) )

    msgbox x


    And the C++ code


    double _stdcall return8(float *w )


    return w[3];



    When I pass by reference I either get a rubbish answer or it bombs out.  If I try the identical code but pass a single variable by value it works fine.  However, I need to pass by reference.


    Can anyone help?  I can't seem to find the answer anywhere.





    Thursday, June 28, 2007 9:57 AM


All replies

  • Arrays are layed out differently in managed code vs unmanaged code, so it was a total fluke that it worked simply be passing the first element ByRef anyway.


    This page has a sample of the "correct" way to do it, which will work with both 64-bit and 32-bit: http://blogs.msdn.com/robgruen/archive/2004/04/30/124076.aspx


    Also be aware that you should probably be passing the length of the array along with the array itself, otherwise how does your unmanaged code know where the end of the array is?

    Monday, July 02, 2007 7:21 AM
  • Dean


    Thank you for that -I'm very grateful.


    It works - but even knowing the answer I can't find any documentation on it!


    I also found another way of getting this to work.  You can pass Intptr (pointers)  to the C++ routine instead of trying to pass the arrays by reference.

    You can create the pointers using code such as:


    dim a(10) as single

    Dim h As GCHandle = GCHandle.Alloc(a)

    Dim ptr As IntPtr = Marshal.UnsafeAddrOfPinnedArrayElement(a, 0)

    Return ptr


    and then pass the ptr by value to the c++ routine.


    This seems to work -  I was wondering whether you knew whether this was doing the same thing.



    Tuesday, July 03, 2007 7:23 AM
  • Here is a blog entry I have written about this problem.




    -Josh [MS]


    Monday, July 09, 2007 4:30 PM