I made really simple c++ dll with only one function:
int DLL_EXPORT __stdcall foo(double *source){return 0;}
and I'm trying to use it like that:
Option Explicit
Private Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
Private Declare PtrSafe Function FreeLibrary Lib "kernel32" (ByVal hLibModule As LongPtr) As Long
Private Declare PtrSafe Function foo Lib "MyLibrary.dll" (ByRef arr As Double) As Long
Sub test_foo(n As Long)
Dim i As Long
Dim library_address As LongPtr
Dim library_path As String
library_path = "global_path\MyLibrary.dll"
library_address = LoadLibrary(library_path)
Dim arr() As Double
ReDim arr(1 To n) As Double
For i = 1 To n
arr(i) = CDbl(Cells(i, 1).Value)
Next
foo arr(1)
Do Until FreeLibrary(library_address) = 0
Loop
End Sub
and it usually works, but sometimes it crashes (Excel dies).
Faulting application name: EXCEL.EXE, version: 16.0.8625.2139, time stamp: 0x5a162a41
Faulting module name: MyLibrary.dll_unloaded, version: 0.0.0.0, time stamp: 0x000000e2
Exception code: 0xc0000005
Fault offset: 0x00001230
Faulting process id: 0x1828
I've tested on Excel 2016 on Windows 10 and Excel 2013 on Windows 8 Please tell me what is wrong? Do you have any example of non-crashing usage of C++ DLL working on arrays?
WORKAROUND: Replace
Do Until FreeLibrary(library_address) = 0
Loop
with
FreeLibrary library_address
I've put that in the loop because sometimes FreeLibrary doesn't work, but i don't care anymore. Related question here
Integer in VBA is from -32768 to 32767. In C++
it is a way bigger, equivalent to the VBA Long
. Thus, try declaring like this:
Private Declare PtrSafe Function foo Lib "MyLibrary.dll" (ByRef arr As Double) As Long
Let me show what I did so far, which worked for me (if this was the way you wanted it). Anyhow, I have changed a few things, it will be better to use some text comparer to see a bit).
int __stdcall SimpleSlowMath(double *source)
{
return 0;
}
The *.def looks like this:
LIBRARY "SomeLibrary"
EXPORTS
SimpleSlowMath
The VBA:
Option Explicit
Public Const myPathDll = "C:\Users\your-own-path\Debug\vityata051217.dll"
Private Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" _
(ByVal lpLibFileName As String) As Long
Private Declare PtrSafe Function FreeLibrary Lib "kernel32" _
(ByVal hLibModule As LongPtr) As Long
Private Declare PtrSafe Function SimpleSlowMath Lib "vityata051217.dll" _
(ByRef arr() As Double) As Long
Sub Try(n As Long)
Dim i As Long
Dim library_address As Long
Dim library_path As String
library_path = myPathDll
library_address = LoadLibrary(library_path)
Dim arr() As Double
ReDim arr(1 To n) As Double
For i = 1 To n
arr(i) = CDbl(Cells(i, 1).Value)
Next
Debug.Print SimpleSlowMath(arr)
End Sub
Public Sub TestMe()
Dim n As Long
For n = 1 To 50
Try n
Debug.Print n
Next n
End Sub
As you see, the difference is that I declare the array with ()
here - ByRef arr() As Double
, but there are some other as well. Give it a try, for me it was working for 2000 samples.
User contributions licensed under CC BY-SA 3.0