2017-08-18 64 views
0

编组字符数组。C#pinvoke C字符数组

的风格函数的C类型定义是:

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]); 
} 

有没有一种更好的方式做这个而不释放指针的内存。只需将字符串数组作为字符串数组复制?

回答

0

首先,你的代码的一些问题,因为它代表:

  1. 调用约定是cdecl,你需要在你的属性CallingConvention = CallingConvention.Cdecl
  2. 您设置了SetLastError = true,但非托管功能肯定不会调用SetLastError。如果是这样,请删除SetLastError = true
  3. 您致电AllocHGlobal,但没有与FreeHGlobal匹配的呼叫,因此内存泄漏。
  4. 你的假设没有任何字符串会超过100的长度(包括空终止符)似乎是脆弱的,并存在缓冲区溢出的风险。

只要你的问题的主体去,编组不会为你编组字符串。根据上述条款,您目前的方法是解决问题的正确方法。