2016-04-21 5 views
3

c#プログラムでzabbix_sender関数を使用しようとしています。ここに私のc#コードです:C#からC DLLを呼び出すと、保護されたメモリを読み書きしようとしました

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct zabbix_sender_value_t 
{ 
    [MarshalAs(UnmanagedType.LPStr)] public String host; 
    [MarshalAs(UnmanagedType.LPStr)] public String key; 
    [MarshalAs(UnmanagedType.LPStr)] public String value; 
} 

[DllImport("zabbix_sender.dll", CharSet = CharSet.Ansi)] 
[return: MarshalAs(UnmanagedType.U4)] 
public static extern int zabbix_sender_send_values(
    [param: MarshalAs(UnmanagedType.LPStr)] String address, 
    [param: MarshalAs(UnmanagedType.U2)] ushort port, 
    [param: MarshalAs(UnmanagedType.LPStr)] String source, 
    [param: MarshalAs(UnmanagedType.Struct)] zabbix_sender_value_t values, 
    [param: MarshalAs(UnmanagedType.U4)] int count, 
    [param: MarshalAs(UnmanagedType.LPStr)] String result 
); 

static void Main() 
{ 
    zabbix_sender_value_t values; 
    values.host = "some_hostname"; 
    values.key = "agent.version"; 
    values.value = "2.0.0"; 
    string res = ""; 
    zabbix_sender_send_values("172.16.1.1", 10051, "127.0.0.1", values, 1, res); 
} 

これは、C関数の定義があり、私はDLLから呼び出すしようとしている:私のC#コードの

int zabbix_sender_send_values(
    const char *address, 
    unsigned short port, 
    const char *source, 
    const zabbix_sender_value_t *values, 
    int count, 
    char **result); 

typedef struct 
{ 
    char *host; 
    char *key; 
    char *value; 
} 
zabbix_sender_value_t; 

実行は例外で終わる「読み取りまたは書き込みをしようとしましたこれはしばしば他のメモリが壊れていることを示しています。

私はマーシャルパラメータで多くの演奏をしましたが、運はありません。

初めて私は使用するネイティブDLLコードc#プログラムで直面しており、私は本当に何をしなければならないのか分かりません。

手がかりを見つけるには、どんな助けを求めても、異議を申し出てください。

おかげ

+0

最も明白な間違いは*値*引数である、あなたがzabbix_sender_value_tを取得する* * REFとして宣言する必要があり*:ここでは

は私の最終的なコードです。 * result *の引数は非常に面倒ですが、文字列は不変なので、* string *として宣言することはできません。 char **はあいまいです。文字列の配列である可能性があります。おそらく解釈は 'Out IntPtr'です。 Marshal.PtrToStringAnsi()に変換されました。非常に重要なハングアップでは、文字列バッファを解放する方法がわからないので、呼び出すたびにメモリがリークする可能性があります。これはinterop-friendly関数ではなく、C++/CLIを使用します。 –

答えて

0

ジャストオフカフの推測はできますが、プロジェクトのプロパティで「安全でないコードを許可する」と危険な{}句で呼び出しをラップしようとして使用可能にしましたか?

0

この関数は、この引数としてByVal文字列を送信している間に結果(最後の)引数としてchar**を受け取ります。文字列オブジェクトはchar*としてマーシャリングされますので、ref IntPtrまたはout string(この場合は推奨)として機能する文字列のポインタを送信する必要があります。
しかし、主な問題は、ByVal zabbix_sender_value_tvalues引数として送信することです。この関数はこの構造体の配列を受け入れます。インスタンスを1つだけ送信する場合は、配列として宣言するか、refパラメータとして宣言できます。

0

ご協力ありがとうございます。

私はこの

[DllImport("zabbix_sender.dll", CharSet = CharSet.Ansi)] 
[return: MarshalAs(UnmanagedType.U4)] 
public static extern int zabbix_sender_send_values(
    [param: MarshalAs(UnmanagedType.LPStr)] String address, 
    [param: MarshalAs(UnmanagedType.U2)] ushort port, 
    [param: MarshalAs(UnmanagedType.LPStr)] String source, 
    ref zabbix_sender_value_t values, 
    [param: MarshalAs(UnmanagedType.U4)] int count, 
    out IntPtr result 
); 

を試してみましたが、このような関数を呼び出します。

zabbix_sender_send_values("10.0.236.1", 10051, "10.0.236.12", ref values, 1, out res); 
string output = Marshal.PtrToStringAnsi(res); 
Console.WriteLine(output); 

それは動作しますが、私はデバッグモードで実行しようとした場合、例外PInvokeStackImbalanceがスローされます。それは生産で使用するのは適切ではありませんか?

ありがとう

0

ありがとう、もう一度ありがとうございます。私はこのコードをデバッグモードでも例外なく終了します。例外の問題は、x86プラットフォームでプログラムをビルドしようとしたときにのみ表示されました。 x64またはAnyCPU(64ビットDLL)を使用すると、すべて正常に動作します。多分設定ミス?

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
public struct zabbix_sender_value_t 
{ 
    [MarshalAs(UnmanagedType.LPStr)] public string host; 
    [MarshalAs(UnmanagedType.LPStr)] public string key; 
    [MarshalAs(UnmanagedType.LPStr)] public string value; 
} 

[DllImport("zabbix_sender.dll", CharSet = CharSet.Auto)] 
[return: MarshalAs(UnmanagedType.U4)] 
public static extern int zabbix_sender_send_values(
    [param: MarshalAs(UnmanagedType.LPStr)] string address, 
    [param: MarshalAs(UnmanagedType.U4)] int port, 
    [param: MarshalAs(UnmanagedType.LPStr)] string source, 
    [param: MarshalAs(UnmanagedType.Struct)] ref zabbix_sender_value_t values, 
    [param: MarshalAs(UnmanagedType.U4)] int count, 
    out IntPtr result 
); 

static void Main() 
{ 
    zabbix_sender_value_t values; 
    values.host = "some_hostname"; 
    values.key = "zbx.trap"; 
    values.value = "99"; 
    IntPtr res ; 
    unsafe { 
     try 
     { 
      zabbix_sender_send_values("10.0.236.1", 10051, "10.0.236.12", ref values, 1, out res); 
      string output = Marshal.PtrToStringAnsi(res); 
      Console.WriteLine(output); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.Message); 
     } 
    } 
} 
関連する問題