使用C ++从VBA访问嵌套结构

问题

我有一个用C ++编写的库,并使用Visual Studio 2010编译为DLL。该DLL有多个导出的函数。 使用Declare Function从Excel中访问导出的函数。

我正在试图在程序中实现一个新的特性,它需要C ++部分中的嵌套结构,然后从VBA中访问这些结构。 C ++代码看起来像这样。

第一个结构

 struct Parameter { double value; char* label; char* description; char* units; }; 

第二种结构

这个结构被用来构build另一个结构如下:

 struct Output { Parameter field_1; Parameter field_2; Parameter field_3; }; 

我正在考虑从VBA访问结构的几种方法。 其中之一是来自这样的voidfunction。

 void Function1(Output* output_function1); 

另一个是返回Output结构的函数,比如这个。

 Output Function2(); 

上面两个函数的内部关系在这一点上并不重要。 我已经validation了这两个实现在C ++代码中的预期工作。

问题

我无法使用Function1Function2从VBA访问这两个结构。

我在VBA中声明了两个自定义types。

 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 

对于Function1我声明了导出的函数如下。

 Declare Sub Function1 Lib "C:\Path\to\library.dll" (ByRef OutputStruct as Output) 

而对于Function2 ,以下。

 Declare Sub Function2 Lib "C:\Path\to\library.dll" () as Output 

Function2崩溃Excel和Function1给我错误vba byref argument type mismatch

我在这里做错了什么? 什么是正确的方法?

如果在#pragma pack(4)#pragma pack()指令中包含结构的定义,Function1将正常工作。

https://msdn.microsoft.com/en-US/en-en/library/office/bb687915.aspx

C:

 #pragma pack(4) struct Parameter{ double value; char* label; char* description; char* units; }; struct Output{ struct Parameter field_1; struct Parameter field_2; struct Parameter field_3; }; #pragma pack() static char Buffer [4096]; static void Append_Field_Values (struct Parameter* field) { static char b [1024]; sprintf (b, "%f %s %s %s\n", field -> value, field ->label, field -> description, field -> units); strcat (Buffer, b); } void _stdcall Function1(struct Output* output_function1) { Buffer [0] = 0; Append_Field_Values (&output_function1 -> field_1); Append_Field_Values (&output_function1 -> field_2); Append_Field_Values (&output_function1 -> field_3); MessageBox (0, Buffer, "FUNCTION1", 0); } 

VB:

 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 Declare Sub Function1 Lib "E:\Serge\StackOverflow\NestedStructures\Debug\NestedStructures.dll" (ByRef OutputStruct As Output) Dim Out1 As Output Sub Test1() Out1.Field1.Value = 3.14 Out1.Field1.Label = "ARINC 429" Out1.Field2.Units = "Miles and Inches" Out1.Field3.Description = "Read MSDN" Call Function1(Out1) End Sub 

在这里输入图像描述

您无法将VBA Types作为parameter passing。 (我知道,我知道,VBA ….)

你需要做的是传入/传出各个属性。 像这样(我不知道C ++如此熊熊)

 void Function1(Output* Field1, Output* Field2, Output* Field3) 

然后在VBA方面

 Declare PtrSafe Sub Function1 Lib "C:\Path\to\library.dll" (ByRef Field1 As LongPtr, ByRef Field2 As LongPtr, ByRef Field3 As LongPtr) 

或者任何数据types是适当的。 Declare语句中的这个MSDN文档也可能有帮助。

当您尝试调用DLL时,不要嵌套Type 。 取而代之的是创build一个包含所有成员的复合Type

 Type Output Value1 as Double Label1 as String Description1 as String Units1 as String Value2 as Double Label2 as String Description2 as String Units2 as String Value3 as Double Label3 as String Description3 as String Units3 as String End Type 

不幸的是,我不认为你可以按照你想要的方式把一个String放在一个Type ,并且它与C兼容。你只需要在那里放一个Long来存放指针并使用存取函数在LongString