【发布时间】:2016-11-22 09:51:44
【问题描述】:
我有一个 Excel 工作表中的 vba 代码使用的 dll。一切正常 - 除了有一个功能需要 SAFEARRAY。
缩写的 Excel VBA 代码如下所示:
Private sub ExcelFoo()
Dim v(115,17)
...stuff ...
MyFunctionCollectionLib.SetMatrix v
这调用了一个用 C++ 编写的 Dll。 c++ 函数如下所示:
void _stdcall SetMatrix(SAFEARRAY **psaMatrix)
... store matrix somewhere ...
在 Excel 中一切正常。
现在我想在 C# 中使用相同的函数。 对象浏览器显示以下有关函数的信息(在 dll 中):
Sub SetMatrix(psaMatrix() As Double)
所以我写了一个 Dll 包装器如下:
// void _stdcall SetMatrix(SAFEARRAY **psaMatrix)
[DllImport( "MyFunctionCollectionLib.dll", CallingConvention = CallingConvention.StdCall )]
public extern static void SetMatrix(ref double[,] psaMatrix);
然后在 C# 中我尝试按如下方式使用它:
public void ReadDefaultValues()
{
double[,] tMatrix = _TestData.ReadDefaultValues();
DllWrapper.DllWrapper.SetMatrix(ref tMatrix);
调试器显示 tMatrix 最初是一个 double[115, 17] - 按照定义,但在调用 SetMatrix() 后它被更改为一个 double[1]。
还有其他一些奇怪的地方让我怀疑我这样做是否正确。我真的对 Excel/vba 和所有这些一无所知。所以我被很多“陷阱”抓住了,因为我真的不在我的领域。
是否有容易获得的有关 SAFEARRAY 的文档? (它不必很容易阅读)我的谷歌搜索带来了很多关于 COM 和编组的晦涩难懂的页面。 这些页面似乎没有直接解决我正在寻找的内容。 Microsoft 文档描述了 SAFEARRAY 结构,但似乎没有提供任何关于使用的详细说明。
================================================ =========================
如果我理解建议的文档,我需要做的是更改我的包装器:
// void _stdcall SetMatrix(SAFEARRAY **psaMatrix)
[DllImport( "MyFunctionCollectionLib.dll", CallingConvention = CallingConvention.StdCall )]
[In][Out][MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] double[,] pArrayOfDouble
对于包装器,有一个 VT_DECIMAL,但没有 VT_DOUBLE 类型 - 所以我假设我应该使用 VT_VARIANT 作为类型。
上面的代码失败(复制到这里):
double[,] tMatrix = _TestData.ReadDefaultValues();
DllWrapper.DllWrapper.SetMatrix(ref tMatrix);
当我尝试使用 var 时(这是 c# 变体吗?)它也失败了
var tMatrix = _TestData.ReadDefaultValues();
DllWrapper.DllWrapper.SetMatrix(ref tMatrix);
两种情况下的错误信息都是:指定的数组不是预期的类型。
在哪里可以找到预期的类型?堆栈跟踪显示:
at MyFunctionCOllection.MyFunctionCOllectionWrapper.SetMatrix(Double[,] pArrayOfDouble)
【问题讨论】:
-
我在上面添加了一些链接...如果您能够使其在 C++ 中但不能在 C# 中工作,另一种可能性是在 VBA 和 C# 之间使用 C++/CLI。这允许你做任何你想做的事情,将调用转发到 C#。
-
我不完全确定我是否清楚。我的最终目标是用 c# 应用程序替换 Excel 工作表。 c# 需要使用 Excel 当前正在使用的现有 dll。将审核您的链接。