在 Compact Framework 3.5 中,我尝试调用具有 IDL 函数签名的 ActiveX 对象:
HRESULT MyFunc([out] SAFEARRAY(float) *var)
互操作生成创建 msil
[out] class [mscorlib]System.Array& marshal( safearray float32)
这似乎很合理,但我不断收到“NotSupportedException”。根据一篇题为“互操作:常见问题和调试技术”的文章(我不能发布多个超链接,这是该短语的第一个 google 结果),在“编组”标题下的第一个要点中,紧凑框架没有正确编组 SAFEARRAY。
我试图通过操纵这个 MSDN 论坛帖子中描述的答案(最后一个条目描述了他的方法)来解决这个问题:http: //social.msdn.microsoft.com/forums/en-US/clr/thread/6641abfc -3a9c-4976-a523-43890b2b79a2/
因此,我创建了以下定义:
[StructLayout(LayoutKind.Sequential)]
struct SafeArray
{
public ushort dimensions; // Count of dimensions in the SAFEARRAY
public ushort features; // Flags to describe SAFEARRAY usage
public uint elementSize; // Size of an array element
public uint locks; // Number of times locked without unlocking
public IntPtr dataPtr; // Pointer to the array data
public uint elementCount; // Element count for first (only) dimension
public int lowerBound; // Lower bound for first (only) dimension
}
并将函数签名的 IDL 重新定义为:
HRESULT MyFunc([out] long *var)
然后发出以下代码:
IntPtr safeArrayPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(SafeArray)));
SafeArray safeArray;
safeArray.dimensions = 1;
safeArray.features = 0;
safeArray.elementSize = (uint)(Marshal.SizeOf(typeof(float)));
safeArray.locks = 0;
safeArray.elementCount = 6;
safeArray.lowerBound = 0;
safeArray.dataPtr = Marshal.AllocCoTaskMem((int)(safeArray.elementCount * safeArray.elementSize));
Marshal.StructureToPtr(safeArray, safeArrayPtr, false);
int iTmp = safeArrayPtr.ToInt32();
MyFunc(out iTmp)
虽然代码似乎成功,但当我尝试使用 Marshal.Copy(dataPtr, myFloatArr, false) 函数读回数据值时,我得到的数据全为 0,这告诉我 ActiveX DLL 的指针得到可能是完全虚假的,它已经被遗忘了。
关于我在这些定义中可能搞砸的任何建议,或对解决此问题的其他方法的建议?
提前致谢...