C#pinvoke C char数组

时间:2017-08-18 08:06:48

标签: c# pinvoke

编组字符数组。

该函数的C typedef是:

typedef bool (*get_VariableInfoFunc)(int *, char * *, int *, int *);

它的用法如下:

pnVariableIdArray = new (nothrow) int[numVars];
pcVariableName = new (nothrow) char*[numVars];
for (int i = 0; i < numVars; i++)
{
    pcVariableName[i] = new char[100];
}
pnUnVariableIdArray = new (nothrow) int[numVars];
pnVariableType = new (nothrow) int[numVars];
res = get_VariableInfo(pnVariableIdArray, pcVariableName, pnUnVariableIdArray, pnVariableType);

我的C#签名是:

[DllImport(AUTODYNResultsApiDll, EntryPoint = "get_VariableInfo", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetVariableInfo(
    int[] pnVariableIdArray,
    IntPtr[] pcVariableName,
    int[] pnUnVariableIdArray,
    int[] pnVariableType);

我用它像:

var stringPointers= new IntPtr[numVars];
for (int i = 0; i < numVars; i++)
{
    by[i] = Marshal.AllocHGlobal(100);
}
GetVariableInfo(pnVariableIdArray, stringPointers, pnUnVariableIdArray, pnVariableType);

然后回到字符串:

var strings = new string[numVars];
for (int i = 0; i < numVars; i++)
{
    strings[i] = Marshal.PtrToStringAnsi(by[i]);
}

如果没有释放指针的内存,有没有更好的方法。只需将char数组复制为字符串数组?

1 个答案:

答案 0 :(得分:0)

首先,您的代码存在一些问题:

  1. 调用约定为cdecl,您需要在属性中加入CallingConvention = CallingConvention.Cdecl
  2. 您设置SetLastError = true,但非托管功能肯定不会调用SetLastError。如果是这样,请删除SetLastError = true
  3. 您拨打AllocHGlobal,但没有与FreeHGlobal匹配的呼叫,因此内存泄露。
  4. 您认为没有字符串超过100的长度(包括空终止符)似乎很脆弱,并且存在缓冲区溢出的风险。
  5. 就问题的主体而言,编组人员不会为你编组一串字符串。根据上述条件,您当前的方法是解决问题的正确方法。