I need to create a C++ dll that have one function that returns a string to be used in an Excel (2010) VBA code.
I've read the following posts: Using C++ DLL in Excel VBA - and Microsoft's tutorials about C++ dll creation and VBA usage (Walkthrough: Create and use your own Dynamic Link Library (C++), Access DLLs in Excel) and followed the procedure.
Here is the code:
C++ dll (taken from Microsoft web page):
// MathLibrary.h - Contains declarations of math functions
#pragma once
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
// The Fibonacci recurrence relation describes a sequence F
// where F(n) is { n = 0, a
// { n = 1, b
// { n > 1, F(n-2) + F(n-1)
// for some initial integral values a and b.
// If the sequence is initialized F(0) = 1, F(1) = 1,
// then this relation produces the well-known Fibonacci
// sequence: 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
// Initialize a Fibonacci relation sequence
// such that F(0) = a, F(1) = b.
// This function must be called before any other function.
extern "C" MATHLIBRARY_API void fibonacci_init(
const unsigned int a, const unsigned int b);
// Produce the next value in the sequence.
// Returns true on success and updates current value and index;
// false on overflow, leaves current value and index unchanged.
extern "C" MATHLIBRARY_API bool fibonacci_next();
// Get the current value in the sequence.
extern "C" MATHLIBRARY_API unsigned int fibonacci_current();
// Get the position of the current value in the sequence.
extern "C" MATHLIBRARY_API unsigned fibonacci_index();
the VBA code (Mine, following Microsoft documentation):
Public Declare Sub fibonacci_init Lib "C:\development\MathLibrary\Release\MathLibrary.dll" (ByVal a As Integer, ByVal a As Integer)
Public Declare Function fibonacci_next Lib "C:\development\MathLibrary\Release\MathLibrary.dll" () As Boolean
Public Declare Function fibonacci_current Lib "C:\development\MathLibrary\Release\MathLibrary.dll" () As Integer
Public Function run_dll()
Dim b As Integer
Call fibonacci_init(1, 1)
b = fibonacci_current()
End Function
When I run the run_dll
function in VBA i get an exception: "Bad DLL calling convention" on the Call fibonacci_init(1,1)
line.
What is wrong here? I've declared the C++ function as extern "C"
so I assumed calling convention are fixed...
UPDATE
More things i've tried...
- I've created a new dll from scratch following the tips from the comments/answers:
Trial.cpp:
const char* str = "abcdefg";
extern "C" __declspec(dllexport) int size()
{
return strlen(str);
}
extern "C" __declspec(dllexport) bool test(char* pReturn)
{
int nSize = strlen(str);
lstrcpynA(pReturn, str, nSize);
return true;
}
with the following VBA:
Public Declare Function size Lib "C:\development\MathLibrary\Release\Trial.dll" () As Long
Public Declare Function test Lib "C:\development\MathLibrary\Release\Trial.dll" (ByVal p As Long) As Boolean
(1) Public Function run_dll()
(2) Dim bb As Boolean
(3) Dim sz As Integer
(4) Dim s As String
(5) sz = size()
(6) s = Space(sz)
(7) bb = test(StrPtr(s))
(8) End Function
line 5 works fine - sz
receives 7. But line 7 gives "Bad DLL calling convention".
Trying to declare the C++ function with
WINAPI
as one mentioned in a post i've read, gives:Can't find DLL entry point size in C:\development\MathLibrary\Release\Trial.dll
.Changing the
test
VBA declaration to
Public Declare Function test Lib "C:\development\MathLibrary\Release\Trial.dll" (ByRef p As String) As Boolean
and calling (line7) as bb = test(s)
- causes Excel to crash
- Changing the
test
VBA declaration to
Public Declare Function test Lib "C:\development\MathLibrary\Release\Trial.dll" (ByRef p As Long) As Boolean
and calling (line7) as bb = test(StrPtr(s))
- gives: "Bad DLL calling convention"
Seems nothing is working. Does someone have a working example for such setup?