在Paulo Bueno的项目https://github.com/buenop/MinXL中,他从C++ dll返回一个Variant,例如:
Declare PtrSafe Function IncrementArrayBy _
Lib "/Library/Application Support/Microsoft/YourLibrary.dylib" _
(ByRef v as Variant, ByVal d as Double) As Variant
我想做同样的事情,但在C.这里是我的减少代码到目前为止:
x一个一个一个一个x一个一个二个x
目前,这两个函数都向VBA返回了一个Empty。这是有意义的,就像我从回答前几个(即Vt为0)中查看16个字节一样,例如使用此代码。
Private Declare PtrSafe Sub memcpy _
Lib "/usr/lib/libSystem.dylib" _
(ByVal dest As LongPtr, ByVal src As LongPtr, ByVal count As Long)
Function peekMem(ptr As LongPtr, size As Long) As Byte()
ReDim answer(1 To size) As Byte
memcpy VarPtr(answer(1)), ptr, size
peekMem = answer
End Function
Sub testVar()
Dim fred As Variant, joe As Variant, p As LongPtr
fred = 1#
joe = peekMem(VarPtr(fred), 16)
p = jinni_new_VT_DOUBLE_PTR2(5#)
joe = peekMem(VarPtr(fred), 16) ' this has the correct values is it
fred = jinni_new_VT_DOUBLE_PTR(5#)
joe = peekMem(VarPtr(fred), 16) ' but this doesn't
fred = jinni_new_VT_DOUBLE(5#)
joe = peekMem(VarPtr(fred), 16) ' and neither does this
End Sub
任何想法如何让这个工作?是vba期待一个变体**?
我并不想把数据复制到一个预先分配的变量中,因为我喜欢在堆栈上返回一个变量的简单性。
Paulo确认他返回了堆栈上的变量,将问题简化为,为什么下面的变量显示为16个零?
VARIANT2 doubleInVariant(double x, VARIANT2 * out) {
VARIANT2 answer;
answer.vt = VT_R8;
answer.data.dblVal = x;
memcpy(out, &answer, sizeof(VARIANT2));
return answer;
}
和
Private Declare PtrSafe Function jinni_doubleInVariant _
Lib "/Library/Application Support/Microsoft/jinni.dylib" Alias "doubleInVariant" _
(ByVal x As Double, ByRef cpy As Variant) As Variant
Paulo指出,变量是24字节而不是16字节。因此将变量结构体更改为:
typedef struct {
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union {
DOUBLE dblVal;
} data;
WORD padding[4]; // due to __VARIANT_NAME_4 in the tagVARIANT struct
} VARIANT2;
现在一切都正常了-请参阅https://github.com/coppertop-bones/jinni以获取src代码和示例电子表格。
1条答案
按热度按时间g2ieeal71#
定义VARIANT时,使用额外的填充将结构从16字节变为24字节。
我感觉自己有点像个学生,但快速搜索的结果似乎表明,16字节是一个常见的误解。