Reputation: 994
DISCLAIMER: I know how to allocate memory in VBA, fill an array within a C++ DLL and return its pointer, but sadly I might find a couple of cases in which I cannot know the size of an array, therefore I won't be able to Dim
or ReDim
it in VBA, before passing it to the DLL.
Suppose I have a C++ subroutine inside my DLL, that would "return" two things as output: one is an integer and the other is an array:
void _stdcall mySub(int inOption, int outXPR, double* outWeight_Coeff)
// Do Stuff
WindowThetaHalf = [insert random value here];
WindowPhiHalf = [insert random value here];
outXPR = value;
outWeight_Coeff = new double[(WindowThetaHalf + 1) * (WindowPhiHalf + 1)];
for (int i = -WindowThetaHalf; i <= WindowThetaHalf; i++)
{
for (int j = -WindowPhiHalf; j <= WindowPhiHalf; j++)
{
outWeight_Coeff[i + WindowThetaHalf + j * (WindowThetaHalf + 1) * 2 + WindowPhiHalf] = i + j;
}
}
Now, I know that I have to give to the DLL the first element of an array as a pointer to make this work:
Private Declare Sub mySub Lib "[dll path here]" (ByVal inOption As Long, ByVal XPR As Long, ByRef outWeight_Coeff As Double)
Sub main()
Dim XPR As Long
Dim a() As Double
ReDim a(0, 0)
LoadChannelType 1, XPR, a(0, 0)
Debug.Print XPR
For i = 0 To UBound(a, 1)
For j = 0 To UBound(a, 2)
Debug.Print a(i, j)
Next
Next
End Sub
This doesn't work though. I feel it might have something to do with the dimensions I'm specifying in VBA, but again, it is very possible that I will have to deal with a situation in which I'd basically have to "ReDim
" the outWeight_Coeff
array in C++ .
Is there any possibility to do that?
EDIT: Other ways I tried and failed:
Instead of using new
, I tried the following as well:
Using malloc
:
outWeight_Coeff = (double*)malloc(((WindowThetaHalf + 1) * (WindowPhiHalf + 1)) * sizeof(double));
Creating a new array and assigning the pointer to it:
double* newArr = new double [(WindowThetaHalf + 1) * (WindowPhiHalf + 1)];
outWeight_Coeff = newArr;
Upvotes: 0
Views: 1013
Reputation: 21936
C++ prototype:
void __stdcall mySub(int inOption, int outXPR, VARIANT *outWeight_Coeff)
VBA prototype:
Private Declare Sub mySub Lib "[dll path here]" (ByVal inOption As Long, ByVal XPR As Long, ByRef outWeight_Coeff As Variant)
This approach allows you to resize the array in C++ (SafeArrayRedim), and/or create a new array and replace whatever array was passed in the argument.
The simplest way to implement that is by using ATL classes CComVariant
and CComSafeArray<double>
. Don’t forget to use Attach/Detach for the CComVariant, otherwise you might leak memory.
Unfortunately, if you don’t have experience with COM automation in C++, you’ll spend some time implementing that even with ATL utility classes: Attach/Detach, VT_BYREF, different lower bounds, etc., it’s relatively cumbersome for a 2D array.
Upvotes: 1