2012-03-01 29 views
1

私は(C/C++のDLLで)このようになりますDLL関数を呼び出すようにしようとしている:コールVBからC DLL内の関数:アクセス違反

__declspec(dllexport) void execute(char** ReturnMsg, char* serverAddress, char* commandLine) 

VB「ラッパー」機能次のようになります。

<DllImport("TPClient.dll", EntryPoint:="execute", CallingConvention:=CallingConvention.Cdecl, CharSet:=CharSet.Auto, ExactSpelling:=True)> _ 
Public Shared Sub tg_execute(<Out()> <MarshalAs(UnmanagedType.LPStr)> ByRef returnString As System.Text.StringBuilder, _ 
          <MarshalAs(UnmanagedType.LPStr)> ByVal serverAddress As String, _ 
          <MarshalAs(UnmanagedType.LPStr)> ByVal commandLine As String) 
End Sub 

パラメータは次のとおりです。 ReturnStringに:私は戻っ機能から取得する必要があり、文字列、送信されたコマンドの結果。 serverAddress:文字列、入力のみ(IPまたはDNS名)。そして コマンドライン:私は、コードを実行すると

Dim returnString As New System.Text.StringBuilder(128) 

tg_execute(returnString, TextBox_serverName.Text.Trim, TextBox_Command.Text.Trim) 

:文字列、入力のみ(任意のコマンド)

は、関数を呼び出すには、私はいくつかの十分な容量を持つStringBuilderオブジェクトがReturnStringに変数として使用するために作ります、私はreturnString(私はデバッガで見ることができます)で期待される文字列を取得しますが、私はまた、AccessViolationExceptionを取得します。コマンドラインで "uname -r"コマンドを使用するとreturnStringに "2.6.30.8-x86"と表示されます。しかし、メモリエラーのためにコードがハングします。

私はVBとP/Invokeにあまり慣れていないので、DLLに渡された引数を取得するためにいくつかの試行錯誤をしなければなりませんでした。これはまた、「MarshalAs(UnmanagedType.LPStr)」属性を使用して終了した方法です。しかし、今私はなぜ私はこれらのメモリエラーを取得しているのか分からない。

私はIntPtr引数を使って他のいくつかの試みをしましたが、私はこの作業を行うことができず、私の理解によれば、マーシャリングは自動的に処理されるべきです(正しいですか?

ご迷惑をおかけして申し訳ありません。

+0

この関数は、Cプログラムから正しく呼び出すのが非常に難しく、C#からうまく機能しません。最初の引数が渡されたバッファの長さを示す余分な引数を持つchar *になるように、Cコードを修正することを検討する必要があります。 –

+0

ご意見ありがとうございます。私が今解決している問題がまだ残っていると思われる場合は、これを検討します。そのことは、呼び出されたコードが何をしているのかを詳しく知らないことです。 – Pieter

答えて

1

戻り値char** ReturnMsgは、ReturnMsgがC文字列へのポインタであることを示唆しています。これは、ネイティブコードがバッファの割り当てを担当していたことを意味します。したがってStringBuilderはここでは適切ではありません。

この関数の呼び出し方法を知るには、実際には十分な情報がありません。欠落しているのは、文字列の割り当てを解除するのがどのパーティーであるかに関する知識です。いずれかのパーティーになる可能性があります。Cコードは、おそらく文字列が静的に割り当てられていると仮定します。定数。

私はVB p/invokeに関する経験がないので、C#のバージョンを教えてもらえれば幸いです。私はあなたが簡単に十分に翻訳できると思います。

[DllImport("TPClient.dll", CallingConvention=CallingConvention.Cdecl, 
    CharSet=CharSet.Ansi, EntryPoint="execute", ExactSpelling=true)] 
private static void tg_execute(out IntPtr returnString, 
    string serverAddress, string commandLine) 

あなたはこのように関数を呼び出す:

IntPtr returnStringPtr; 
tg_execute(out returnStringPtr, serverAddress, commandLine); 
string returnString = Marshal.PtrToStringAnsi(returnStringPtr); 

注あなたの文字セットが質問に間違っていたことを。ネイティブコードがcharを使用するため、Ansiを使用する必要があります。私はまたあなたのMarshalAs属性は、それらのパラメータタイプのデフォルトマーシャリングを再記述しているので、擬似であると考えています。

ネイティブコードが呼び出し側がメモリを解放することを期待するならば、ネイティブコードは関数をエクスポートしなければなりません。その場合は、returnStringPtrという値で渡します。

+0

OK、ありがとう!私は今働いている。私は実際にネイティブコードがバッファを割り当てていると思う、私はそのプロジェクトのすべてのコードを知りません。 私は今使用しているVBコード: – Pieter

+0

' _ \t公共の共有サブtg_execute(のIntPtrとしてのByRef ReturnStringに、文字列としてByVal serverAddressで、文字列としてByValコマンドライン) エンドSub' 電話をかける: '薄暗いreturnStringPtrのIntPtrとして tg_execute(returnStringPtr、TextBox_serverName.Text.Trim 、TextBox_Command.Text.Trim) MessageBox.Show(Marshal.PtrToStringAnsi(returnStringPtr)) ' – Pieter

+0

これはよく見えます。申し訳ありませんが、私はVB.netで答えを書くことができませんでした。 –

関連する問題