1

我很难把这个编组下来。

我有如下所示的非托管代码:

WORD HLP_GetDeviceNames (LPSTR *DevNames, WORD Max_Len, WORD Max_Num)

仅供参考,我没有编写此非托管代码,但必须使用它。

返回: WORD 指示错误。

DevNames:指向字符数组数组的指针。基本上是一个字符串数组,将被修改并返回给我!

Max_Len:每个字符串的长度(我被告知这必须是 256)

Max_Num:数组的长度。我正在使用另一个正在运行的 Invoke 调用,它告诉我设备的数量,所以我确切地知道要发送多少个字符串。

我已经使用 P/Invoke interop signatureToolkit 来解决这个问题,但也阅读了一堆以获得更进一步的信息。我现在在这里:

[DllImport("UsbMeasLib.dll")]
public static extern ushort HLP_GetDeviceNames([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] ref StringBuilder[] DevNames, ushort Max_Len, ushort Max_Num);

我这样称呼我的代码:

StringBuilder[] DevNames = new StringBuilder[deviceCount];
     for(int i = 0; i< deviceCount; i++)
     {
           DevNames[i] = new StringBuilder().Append(' ', 256);
     }

     HachUsbMeasLib.HLP_GetDeviceNames(ref DevNames, 256, Convert.ToUInt16(DevNames.Count())); 

我正在使用字符串生成器数组,因为我需要非托管代码来修改字符串生成器,以便它可以返回新字符串,因为字符串是不可变的。

当我运行代码时,我的数组未修改!

我不太确定发生了什么,但我认为这与 CLR 告诉非托管代码不要修改我的数组而是创建一个新的引用(指针)有关。即使是这种情况,我也不知道如何解决它。

感谢任何人可以提供的任何见解!

4

2 回答 2

2

尝试在低水平上工作。将 DevNames 参数声明为 IntPtr[]。通过以下方式准备它:

IntPtr[] devNames = new IntPtr[deviceCount];

for(int i = 0; i < deviceCount; i++)
{
    devNames[i] = Marshal.AllocHGlobal[256];
}

将此数组传递给 HLP_GetDeviceNames。要处理输出数据,请将 Marshal.PtrToStringAnsi 应用于每个 DevNames 成员。最后不要忘记使用 Marshal.FreeHGlobal 发布 DevNames[i]。

于 2010-08-16T15:33:09.787 回答
0

我想出了这个。感谢任何回答的人。

我发现它是如何工作的。我只是提供内存空间,但我必须让封送处理知道我期望与该对象一起进出,以便它允许非托管代码修改分配的空间。

我是这样做的:

[DllImport("UsbMeasLib.dll")]
private static extern ushort HLP_GetDeviceNames([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] string[] DevNames, ushort Max_Len, ushort Max_Num);

我使用字符串而不是字符串生成器,因为非托管代码将简单地替换可以的字符串。我正在取回数组指针,而不是修改过的字符串。托管代码只是更改指针数组以指向新的字符串对象(我认为)。

int numDev = HLP_GetNumDevices();


string[] names = new string[numDev];

for (int i = 0; i < names.Length; i++)
{
    names[i] = new StringBuilder().Append(' ', 256).ToString();
}

ushort errorCode = HLP_GetDeviceNames(names, 256, Convert.ToUInt16(numDev));

我为非托管代码分配内存,然后让非托管代码在那里更改字符串。

这可行,但我不知道我是否有任何潜在的内存泄漏或其他潜在问题。

于 2010-08-17T18:15:48.943 回答