将对 DLL 的引用从 VBA 翻译成 VB.NET

Translating the passage of a reference to a DLL from VBA to VB.NET

我正在尝试重写一段代码,其中包括从 VBA 到 VB.NET 的 C++ dll 调用。
特别是我在 dll 中调用了一个 C++ 函数,它对 float 的几个二维数组执行一些操作是:

int __stdcall FindPolarization(int PointsTheta, int PointsPhi, float* Real1, float* Imag1 = nullptr)
{
    double Max[4] = { -999, -999, -999, -999 };         // Max values
    long MaxPos[4][2] = { -999, -999,                   // Max Theta and Max Phi
        -999, -999,
        -999, -999,
        -999, -999 };
    float* Pointers[4][2];
    double DeltaTheta = static_cast<double>(180.0 / PointsTheta);
    double DeltaPhi = static_cast<double>(360.0 / PointsPhi);
    vector<vector<vector<double>>> Ampl;

    // Setup
    Pointers[0][0] = Real1;
    Pointers[0][1] = Imag1;
    Pointers[1][0] = Real2;
    Pointers[1][1] = Imag2;
    Pointers[2][0] = Real3;
    Pointers[2][1] = Imag3;
    Pointers[3][0] = Real4;
    Pointers[3][1] = Imag4;
    if (Real3 != nullptr && Real4 != nullptr && Imag3 != nullptr && Imag4 != nullptr)
    {
        Ampl.resize(4, vector<vector<double>>(PointsTheta + 1, vector<double>(PointsPhi, 0)));
        Real3 = nullptr; Imag3 = nullptr; Real4 = nullptr; Imag4 = nullptr;
    }
    else
    {
        Ampl.resize(2, vector<vector<double>>(PointsTheta + 1, vector<double>(PointsPhi, 0)));
    }
    Real1 = nullptr; Imag1 = nullptr; Real2 = nullptr; Imag2 = nullptr;

    // Coordinates transformation + Maximum storage
    Concurrency::parallel_for(0, PointsPhi, [&](int j)
    {

        double PhiRad = j * DeltaPhi * Deg2Rad;
        double CosPhi = cos(PhiRad);
        double SinPhi = sin(PhiRad);
        int ind;
        pair<double, double> AmplCoCr;

        for (int i = 0; i <= PointsTheta; i++)
        {

            ind = j * (PointsTheta + 1) + i;

            for (int k = 0; k < static_cast<int>(Ampl.size()); k = k + 2)
            {
                AmplCoCr = AmplCalc(ind, Pointers[k][0], Pointers[k][1], Pointers[k + 1][0], Pointers[k + 1][1], CosPhi, SinPhi);
                Ampl[k][i][j] = AmplCoCr.first;
                Ampl[k + 1][i][j] = AmplCoCr.second;

                if (Ampl[k][i][j] > Max[k])
                {
                    Max[k] = Ampl[k][i][j];
                    MaxPos[k][0] = i;
                    MaxPos[k][1] = j;
                }
                if (Ampl[k + 1][i][j] > Max[k + 1])
                {
                    Max[k + 1] = Ampl[k + 1][i][j];
                    MaxPos[k + 1][0] = i;
                    MaxPos[k + 1][1] = j;
                }
            }
        }

    });

    double A = max(max(Max[0], Max[1]), max(Max[2], Max[3]));
    if (A > Max[1] && A > Max[2] && A > Max[3]) return 45;
    else if (A > Max[0] && A > Max[2] && A > Max[3]) return 135;
    else if (A > Max[0] && A > Max[1] && A > Max[3]) return 90;
    return 0; // else if (A > Max[0] && A > Max[1] && A > Max[2]) 

}


pair<double, double> AmplCalc(int index, float* RealCo, float* ImagCo, float* RealCr, float* ImagCr, double CosPhi, double SinPhi)
{
    double A, B;

    const double RealCoij = static_cast<double>(RealCo[index]);
    const double RealCrij = static_cast<double>(RealCr[index]);
    const double ImagCoij = static_cast<double>(ImagCo[index]);
    const double ImagCrij = static_cast<double>(ImagCr[index]);

    A = RealCoij * CosPhi + RealCrij * SinPhi;
    B = ImagCoij * CosPhi + ImagCrij * SinPhi;
    double Co = 10 * log10(A * A + B * B);

    A = (RealCoij * SinPhi * (-1) + RealCrij * CosPhi);
    B = (ImagCoij * SinPhi * (-1) + ImagCrij * CosPhi);
    double Cr = 10 * log10(A * A + B * B);

    return make_pair(Co, Cr);
}

在 VBA 环境中导入的是:

Private Declare Function FindPolarization Lib "EvalFunc.dll" (ByVal PointsTheta As Long, ByVal PointsPhi As Long, ByRef RealLev1 As Single, ByRef ImagLev1 As Single = 0) As Long

并通过以下方式在代码中调用:

Dim RealLev1() As Single, ImagLev1() As Single
Dim PolMax As Long, FFThetaPoints As Long, FFPhiPoints As Long

' Arrays are filled here through a function that determines their dimensions and values
FFThetaPoints = UBound(RealLev1, 1)
FFPhiPoints = UBound(RealLev1, 2)
PolMax = FindPolarization(FFThetaPoints, FFPhiPoints, RealLev1(0, 0), ImagLev1(0, 0))

这适用于 VBA,但我一直试图将其翻译成 VB.NET 但惨遭失败。

前提是我无法更改dll里面的C++代码,我已经停在了下面的代码
函数的导入如下所示:

 <DllImport("myDll.dll", SetLastError:=True, CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.StdCall)> _

Public Shared Function FindPolarization(ByVal PointsTheta As Integer, ByVal PointsPhi As Integer, ByRef RealLev1 As Single, _
Optional ByRef ImagLev1 As Single = Nothing) As Integer
End Function

调用它的代码是:

Dim FFThetaPoints As Integer, FFPhiPoints As Integer, PolMax As Integer
Dim RealLev1(,) As Single = Array.CreateInstance(GetType(Single), 1, 1)
Dim ImagLev1(,) As Single = Array.CreateInstance(GetType(Single), 1, 1)

FFThetaPoints = UBound(RealLev1, 1)
FFPhiPoints = UBound(RealLev1, 2)
PolMax = ImportDll.FindPolarization(FFThetaPoints, FFPhiPoints, RealLev1(0, 0), ImagLev1(0, 0))

现在,这些数组是 System.Array 类型,因为特定的函数要求它们如此。

虽然在 VBA 中我得到了一些结果,但在 VB.NET 中我得到了其他结果。我认为这与我声明 Single 数组的方式有关,但我不确定。

我做错了什么?

我必须在这里把所有的功劳都归功于@Craig。 VBA 和 VB.NET 确实有不同的矩阵寻址逻辑(主要列与行主要),所以我不得不转置所有二维数组,而不交换 FFThetaPointsFFPhiPoints

值得一提的是,我尝试使用Excel.Application Worksheetfunction.Transpose 方法,但没有达到预期效果。所以我不得不自己写一段代码来转置矩阵。