Problem
I have a library written in C++ and compiled as a DLL using Visual Studio 2010. The DLL has multiple exported functions. The exported functions are accessed from Excel using Declare Function
.
I am trying to implement a new feature in the program which requires nested structures in the C++ portion which are then accessed from VBA. The C++ code looks like this.
First Structure
struct Parameter {
double value;
char* label;
char* description;
char* units;
};
Second Structure
This structure is used to build another structure as follows:
struct Output {
Parameter field_1;
Parameter field_2;
Parameter field_3;
};
There are couple of ways that I am thinking about accessing the structure from VBA. One of them is from a void
function such as this.
void Function1(Output* output_function1);
The other is a function that returns the Output
structure, such as this.
Output Function2();
The internals of the two functions above do not matter at this point. I have verified that both implementations work as intended in the C++ code.
Issue
I am unable to access these two structures from VBA using either Function1
or Function2
.
I declared two custom types in VBA.
Type Parameter
Value as Double
Label as String
Description as String
Units as String
End Type
Type Output
Field1 as Parameter
Field2 as Parameter
Field3 as Parameter
End Type
For Function1
I declared the exported function as follows.
Declare Sub Function1 Lib "C:\Path\to\library.dll" (ByRef OutputStruct as Output)
and for Function2
, the following.
Declare Sub Function2 Lib "C:\Path\to\library.dll" () as Output
Function2
crashes Excel and Function1
gives me the error vba byref argument type mismatch
.
What am I doing wrong here? What is the correct approach?
Function1 will work fine if you enclose definitions of your structures in
#pragma pack(4)
...#pragma pack()
directives.https://msdn.microsoft.com/en-US/en-en/library/office/bb687915.aspx
C:
VB:
You can't pass VBA
Types
as arguments. (I know. I know. VBA....)What you'll need to do is pass in/out the individual properties. Something like this (I don't know C++ so bear with me.)
And then on the VBA side
Or whatever data type is appropriate. This MSDN doc on the Declare statement might help as well.
Don't nest
Type
s when you're trying to call into a DLL. Instead make a compositeType
that contains all the members:Unfortunately, I don't think you can put a
String
in aType
the way you want and have it be compatible with C. You'll have to just put aLong
in there to hold the pointer and use accessor functions to convert between theLong
and aString