The way I normally do it is to do something like this (which doesn't break any dll boundary rules e.g. no memory allocation takes place inside of the dll to be deallocated outside etc) :
Code:
void MyDllMethod( BYTE *pbByteArray, int *pnSize )
{
const BYTE abData[] = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70 };
const int nSizeOfData = sizeof(abData);
if (pbByteArray == NULL)
{
// if NULL is passed in just return the length
*pnSize = nSizeOfData;
}
else
{
*pnSize = min( nSizeOfData, *pnSize );
::memcpy(pbByteArray, abData, *pnSize);
}
}
Basically you pass NULL in and recieve the size of the buffer. Then you allocate a buffer of this size and pass it back into the method where it's populated.
You should have a .def file in your dll and specify your methods in there. This will prevent them from being 'decorated' i.e. having a load of gunk put around them.
In C# you'd do this like this (sorry I don't know VB.NET enough to be able to do it in this language straight off : but it should give you an idea)
Code:
using System.Runtime.InteropServices;
public class MyDllInterface
{
[DllImport("MyDll.dll")]
static extern void MyDllMethod(IntPtr byteArray, ref int size);
static public byte[] MyDllMethod()
{
int size = 0;
MyDllMethod(IntPtr.Zero, ref size);
byte [] data = new byte[size];
GCHandle pData = GCHandle.Alloc(data, GCHandleType.Pinned);
MyDllMethod(pData.AddrOfPinnedObject(), ref size);
pData.Free();
return data;
}
}
OK ?
Darwen.
www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.
void MyDllMethod( BYTE *pbByteArray, int *pnSize )
{
const BYTE abData[] = { 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70 };
const int nSizeOfData = sizeof(abData);
if (*pbByteArray == NULL)
{
// if NULL is passed in just return the length
*pnSize = nSizeOfData;
}
else
{
*pnSize = min( nSizeOfData, *pnSize );
::memcpy(pbByteArray, abData, *pnSize);
}
}
This is how the VB.NET code looks like after I translated from C#:
Code:
Imports System.Runtime.InteropServices
Public Class MyDllInterface
Public Declare Function MyDllMethod Lib "MyDLL.dll" (ByRef byteArray As IntPtr, ByRef size As Integer) As Integer
Public Sub ByteArray(ByRef data() As Byte)
Dim Size As Integer = 0
MyDllMethod(Nothing, Size)
ReDim data(Size)
Dim pData As GCHandle = GCHandle.Alloc(data, GCHandleType.Pinned)
MyDllMethod(pData.AddrOfPinnedObject(), Size)
pData.Free()
End Sub
End Class
The size is returned as 7 and that is correct, but the byte array is returned with only zeros?
all is not fixed,i still get 17179869171 25769803781 .........
when 1 2 .... expected.(but some values have been changed,however)
i imagine some changes in the vba files may be innapropriate.
here 's the code:
MyDllInterface.vb
Code:
Imports System
Imports System.Runtime.InteropServices
Public Class MyDllInterface
Public Declare Function MyDllMethod Lib "C:\Users\Frederic\Desktop\Documents\dll\maillage\meshdll\Debug\mesh.dll" _
(ByVal byteArray As IntPtr, ByRef size As Integer) As Integer
Public Function GetByteArray() As Long()
Dim Size As Integer = 0
MyDllMethod(Nothing, Size)
Dim ResultByteArray As Long()
ResultByteArray = Array.CreateInstance(GetType(Long), Size)
Dim pData As GCHandle = GCHandle.Alloc(ResultByteArray, GCHandleType.Pinned)
MyDllMethod(pData.AddrOfPinnedObject(), Size)
pData.Free()
Return ResultByteArray
End Function
End Class
and main code in vba:
Code:
Dim myDllInterface As MyDllInterface = New MyDllInterface
Dim tabByte As Long()
tabByte = myDllInterface.GetByteArray()
hi again,
another problem,with the same kind of context:
in vb,we have 2 arrays of integer:beginArray[100] and endArray[1500]
the way to return endArray with the c++ dll is ok,the previous posts explain that.
the problem comes from beginArray, how to initialize it,
and avoid the clash when c++ dll receives it: (line int attempt = ....)
vb.code:
Code:
sub usesCppDll()
Dim inputArray(100) As Integer
'i tried also
'Dim inputArray As Integer()
'Dim Size As Integer = 0
'initSmallArray(Nothing, Size)
'inputArray = Array.CreateInstance(GetType(Integer), Size)
'Dim pData As GCHandle = GCHandle.Alloc(outputArray, GCHandleType.Pinned)
'initSmallArray(pData.AddrOfPinnedObject(), Size)
For i = 0 To 99
tabdep(i) = i
Next
Dim outputArray As Integer()
Dim Size As Integer = 0
initBigArray(Nothing, Size)
outputArray = Array.CreateInstance(GetType(Integer), Size)
Dim pData As GCHandle = GCHandle.Alloc(outputArray, GCHandleType.Pinned)
returnArray(outputArray(0), pData.AddrOfPinnedObject(), Size)
pData.Free()
End sub
c++ code
Code:
void __clrcall initSmallArray( int *anArray, int *pnSize )
{
int abData[100];
const int nSizeOfData = sizeof(abData) / sizeof(int);
if (*anArray == NULL)
*pnSize = nSizeOfData;
else
{
*pnSize = min( nSizeOfData, *pnSize );
::memcpy(anArray, abData, (*pnSize) * sizeof(int));
}
};
void __clrcall initBigArray( int *noArrayYet, int *pnSize )
{
int abData[1500];
*pnSize = nSizeOfData;
};
void __clrcall returnArray( int *initialArray, int *finalArray, int *pnSize )
{
int abData[1500];
int attempt = initialArray[1];//problem here to get the values from initialArray
abData[i] = ...;//result of the dll treatment(no more problem at this stage,and after)
const int nSizeOfData = sizeof(abData) / sizeof(int);
*pnSize = min( nSizeOfData, *pnSize );
::memcpy(finalArray, abData, (*pnSize) * sizeof(int));
};
Please post only relevant code and explain exactly what doesn't work. I don't understand what is "problem here to get the values from initialArray": exception, junk values, something else?
i have found the solution.
(it was contained in the previous posts,in fact)
here's the modification in vb,if it can help someone.
vb code:
Code:
sub usesCppDll()
Dim inputArray As Integer()
dim Size As Integer = 0
initSmallArray(Nothing, Size)
inputArray = Array.CreateInstance(GetType(Integer), Size)
Dim pData As GCHandle = GCHandle.Alloc(outputArray, GCHandleType.Pinned)
initSmallArray(pData.AddrOfPinnedObject(), Size)
For i = 0 To 99
tabdep(i) = i
Next
Dim outputArray As Integer()
initBigArray(Nothing, Size)
outputArray = Array.CreateInstance(GetType(Integer), Size)
Dim pData As GCHandle = GCHandle.Alloc(outputArray, GCHandleType.Pinned)
Dim pData2 As GCHandle = GCHandle.Alloc(inputArray, GCHandleType.Pinned)
returnArray(pData2.AddrOfPinnedObject(), pData.AddrOfPinnedObject(), Size)
pData.Free()
End sub
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.