2017-08-18 149 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的長度(包括空終止符)似乎是脆弱的,並存在緩衝區溢出的風險。

只要你的問題的主體去,編組不會爲你編組字符串。根據上述條款,您目前的方法是解決問題的正確方法。