2014-03-27 58 views
2

所以我有這個調用DLL代碼的VBA代碼。 DLL代碼工作正常,VBA代碼工作正常,直到我從VBA調用DLL函數。出於某種原因,它沒有正確傳遞第六個參數。我通過添加第7個參數並在第6個和第7個參數中傳遞相同的值進行測試 - 第7個傳遞正常,第6個傳遞相同的大(不正確)值。我不知道發生了什麼。VBA Excel DLL參數問題 - 第六個參數

VBA:

Option Explicit 

' Declare the LMM Function that's in the DLL 
Declare PtrSafe Function GenCudaLMMPaths Lib "C:\Path to DLL\LMMExcel.dll" Alias "GenerateCUDALMMPaths" (xTimes#, xRates#, xVols#, xRData#, ByRef ArrLen As Long, ByRef NPaths As Long) As Long 


' Generate LMM Paths on Click 
Sub LMM_Click() 

    Dim Times#(), Rates#(), Vols#() 

    Dim x As Long 
    Dim y As Long 
    Dim rTimes As Range 
    Dim rRates As Range 
    Dim rVols As Range 
    Dim cell As Range 

    Dim sz As Long 
    sz = 15 

    ' Resize 
    ReDim Times(sz), Rates(sz), Vols(sz) 

    ' Fill in Data 
    Set rTimes = Sheets("Market").Range("C2:Q2") 

    x = 1 
    For Each cell In rTimes 
     Times(x) = cell.Value 
     x = x + 1 
    Next 

    Set rRates = Sheets("Market").Range("C5:Q5") 

    x = 1 
    For Each cell In rRates 
     Rates(x) = cell.Value 
     x = x + 1 
    Next 

    Set rVols = Sheets("Market").Range("C4:Q4") 

    x = 1 
    For Each cell In rVols 
     Vols(x) = cell.Value/10000 
     x = x + 1 
    Next 

    'Call the Function 
    Dim np As Long 

    np = Sheets("LMM").Range("C2").Value 

    Dim useCuda As Boolean 

    If Sheets("LMM").Range("C3").Value = "GPU" Then 
     useCuda = True 
    Else 
     useCuda = False 
    End If 

    Dim rData#() 
    Dim rValue 

    ReDim rData(np * sz * (sz + 3)) 

    rValue = GenCudaLMMPaths(Times(1), Rates(1), Vols(1), rData(1), sz, np) 

    If rValue = -1 Then 
     'No CUDA Card 
     MsgBox ("Your system doesn't have a CUDA Enabled GPU") 
    ElseIf rValue = 1 Then 
     'Error Occurred 
     MsgBox ("An error occurred while trying to generate LMM paths") 
    ElseIf rValue = 0 Then 
     'Success 
     ' Need to reformat return data 
     Dim fmtData() 

     ReDim fmtData(np * sz, sz) 

     Dim i, j, k 

     For i = 0 To np - 1 
      For j = 0 To np - 1 
       For k = 0 To np - 1 
        fmtData(((i * sz) + j) + 1, k + 1) = rData(((i * sz * sz) + (j * sz) + k) + 1) 
       Next k 
      Next j 
     Next i 

     'Fill in data 
     Sheets("LMM").Range("A8:K" & (np * sz)) = fmtData 
    Else 
     'Too many requested paths for this CUDA card 
     MsgBox ("In order to prevent GPU Lock-up, you cannot request more than " & rValue & " paths.") 
     Sheets("LMM").Range("C2").Value = rValue 
    End If 

End Sub 

DLL函數聲明:

int __stdcall GenerateCUDALMMPaths(double* arrTimes, double* arrRates, double* arrVols, double* retData, int& ArrLength, int& NPaths); 

DEF文件:

LIBRARY "CUDAFinance" 
EXPORTS 
    CheckExcelArray = CheckExcelArray 
    GenerateLMMPaths = GenerateLMMPaths 
    GenerateCUDALMMPaths = GenerateCUDALMMPaths 

任何人有任何想法嗎?我完全失去了。

+0

你能舉出傳遞值的例子嗎? – 2014-03-27 15:52:28

+1

也許這會起作用,'np = CLng(Sheets(「LMM」)。Range(「C2」)。Value)' – hstay

+0

我相信你需要通過「ByVal」而不是「ByRef」我想你說過你在前面的問題中已經試過了......我正在查找更多。另外,你在哪裏看到大的不正確值出現?調試DLL,還是在VBA的某處? – MattB

回答

1

我只是遇到了同樣的問題,並得到它如下解決。

由於你已經在六個參數函數長可變,與Arrlen一起導入NPaths作爲數組而不添加第七論點:

1)在VBA:

聲明一個兩個元件陣列:

昏暗NArrLenNPaths(1),只要

然後,分配的值:

NArrLenNPaths(0)包含ArrLen和NArrLenNPaths(1)NPaths的價值。

保留VBA中的函數解析,但在調用它時,將NArrLenNPaths(0)作爲第6個參數。不要提出第七個理由。 C++將按以下方式檢索這兩個值。

2)在C++中使用而不是指針:

更改第六參數

INT * NArrLenNPaths

然後通過

retreive值

INT NArrLen = NArrLenNPaths [0];

int NPaths = NArrLenNPaths [1];