2013-03-07 9 views
8

機能に関する問題は、次のようになります。C言語でPInvoke char *がC#でStringとして処理されるDLL。 C DLL内のヌル文字

int my_Funct(char* input, char* output); 

私はC#のアプリからこれを呼び出す必要があります。私は次のようにこれを行います:

...DllImport stuff... 
public static extern int my_Funct(string input, string output); 

入力文字列はDLLに完全に送信されます(私はそれを証明しています)。関数が間違っていても、出力は出力されます。私は次のように、それにヘキサデータを持っている:

3F-D9-00-01 

しかし残念ながら二つのゼロの後にあるすべてのものが切断され、最初の2つのバイトは、私のC#のアプリに来ます。それは、(私が推測する)それがヌル文字として扱われ、文字列の終わりとしてそれをとるので、起こります。

どうすればいいですか?私は文字列ではなくIntPtrとして指定しようとしましたが、後でそれをどうするかわかりません。 私は後に実行しようとしました:

byte[] b1 = new byte[2]; 
Marshal.Copy(output,b1,0,2); 

2は、通常、バイト配列の長さでなければなりません。しかし、私はすべての種類のエラーが発生します:「要求された範囲は配列の終わりを過ぎて広がっています。または "保護されたメモリを読み書きしようとしました..."

何か助けていただきありがとうございます。

+0

(1)C#文字列がcharよりも広い。 (2)この関数によって返されるchar *は、正しい幅のものであっても、有効なC#文字列であるために必要な追加構造を持たないでしょう。 –

+0

この操作の実行方法については、COM InteropおよびP/Invokeを参照する必要があります。それを行い、その資料であなたが持っている質問でコールバックしてください。 –

+0

pinvoke marshallerはC文字列のみをサポートします。それは明らかにC文字列ではなく、0の後で重要なバイトを持つときです。それはバイト[]です。しかし、重要なハングアップでは、誰も* *多くの*バイトがどのように関係しているか把握することはできません。この関数は、Cコードでも使用するのが非常に難しく、ピンボケしてもそれほど良くなりません。あなたはそれを修正する方がよいでしょう。長さが予測可能な場合は、MarshalAs.SizeConstを使用します。 –

答えて

12

出力文字列のマーシャリングが正しくありません。 p/invoke宣言でstringを使用すると、データを管理対象からネイティブに渡すときに適切です。しかし、データが他の方向に流れているときは、それを使うことはできません。代わりにStringBuilderを使用する必要があります。このように:

[DllImport(...)] 
public static extern int my_Funct(string input, StringBuilder output); 

そして、出力用のメモリ割り当て:

StringBuilder output = new StringBuilder(256); 
//256 is the capacity in characters - only you know how large a buffer is needed 

をそして、あなたは関数を呼び出すことができます。一方

int retval = my_Funct(inputStr, output); 
string outputStr = output.ToString(); 

これらのパラメータは、それらの中にヌル文字を持っている場合は、文字列としてマーシャリングすることはできません。これは、マーシャラーがnullを過ぎたものをマーシャリングしないためです。バイト配列としてマーシャリングする必要があります。

public static extern int my_Funct(
    [In] byte[] input, 
    [Out] byte[] output 
); 

これはC宣言に一致します。

は、その後、あなたがこのようなバイト配列に入力文字列を変換するANSIエンコーディングを想定して:あなたは別のエンコーディングを使用したい場合は

byte[] input = Encoding.Default.GetBytes(inputString); 

、それはそうする方法は明らかです。

出力用に配列を割り当てる必要があります。

byte[] output = new byte[input.Length]; 

を何とか自分のCの関数は、配列の長さを知るために持っている:それはあなたがこれを行うだろう入力と同じ長さだと仮定。私はあなたにそのビットを残します!

次に、あなたは

int retval = my_Funct(input, output); 

関数を呼び出すことができます。そして、バック再度Encodingクラスを使用するC#の文字列への出力配列を変換します。

string outputString = Encoding.Default.GetString(output); 
+0

ありがとうございます! [アウト]バイト[] ...バージョンの作品! – user2124150

関連する問題