2017-08-18 13 views
0

マーシャル文字配列。C#pinvoke C char配列

機能のC言語のtypedefがある:

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

それは `sの使い方は次のようである:

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配列を文字列配列としてコピーするだけですか?すべての

答えて

0

まず、それはスタンドとしてあなたのコードを持ついくつかの問題:

  1. 呼び出し規約がcdeclで、あなたの属性にCallingConvention = CallingConvention.Cdeclを含める必要があります。
  2. SetLastError = trueを設定しますが、アンマネージ機能は必ずSetLastErrorを呼び出しません。その場合はSetLastError = trueを削除してください。
  3. AllocHGlobalに電話しましたが、FreeHGlobalと一致する呼び出しがないため、メモリがリークします。
  4. 文字列が長さ100(NULL終端文字を含む)を超えないと仮定すると、脆弱になり、バッファオーバーフローの危険があります。

あなたの質問の主要なところでは、マーシャラーは文字列の配列をマーシャリングしません。上記の条件を前提とした現在のアプローチは、問題に取り組む正しい方法です。