2011-10-12 6 views
10

は、だから私はこのようになりますC++で記述された機能、...なぜC#とVB.NETはchar *を暗黙的にマーシャリングするのですか? (C#で書かれた)

extern "C" __declspec(dllexport) int __stdcall SomeFunction(char *theData) 
{ 
    // stuff 
} 

を持っている...と私は私の現在のプロジェクトでそれを使用しています。 VBで書かれたこの機能を使用する他のプロジェクトは、このように見て、あります

Public Declare Function SomeFunction Lib "MyDLL.dll" _ 
    Alias "[email protected]" (ByVal theData As String) As Integer 

だから私はC#で同等のを書いてみましたが、文字列型を使用して、実際に私のために動作しないことが判明 - 文字列が希望私がそれを渡した同じデータで戻ってきてください。代わりに"ref string"を使って文字列を参照渡ししようとしましたが、メモリアクセス違反がありました。

は、いくつかの掘削を行った後、私は、これはC#での正しい実装であることがわかった:

[DllImport("MyDLL.dll", EntryPoint = "[email protected]")] 
public static extern int SomeFunction(StringBuilder theData); 

は今、私はVB.NETやC#はかなり異なっていることを知っているが、私は常に文字列が文字列だったと仮定したと。 1つの言語がchar*からStringに暗黙的にマーシャリングできる場合、なぜ他のクラスは別のクラスを必要としますか?

(わかりやすくするためにタイトルを編集)

+0

JustDecompileまたは.NET Reflectorで両方のバージョンを調べるのは興味深いかもしれません。 –

答えて

6

今私はVB.NETやC#はかなり異なっていることを知っているが、私は常に文字列が

文字列は、.NETでimmutableている文字列だったと仮定したとします。 ByVal不変のデータ型を渡すと、値が変更されることがあるのはなぜですか?それは通常の機能では発生しません。ちょうどDeclareです。

このようにして行われた従来のVB6のDeclareステートメントとの下位互換性を維持するためには、すべてが関係していると思います。ここの黒い羊は、C#コードではなくVB.netコードです。

+0

また、 'Declare'だけがこれを行います。''はしません(VBはプロパティと定数を渡せるようにByRefパラメータで面白いことを行いますが、これは1つではありません) – Random832

+1

+1。 **これはVB6 Declareステートメントとの下位互換**のためのものです。新しいVB.Netコードでは、あなたは ''を好むかもしれません。彼らの知恵では、VB6デザイナーはVB6 Declareの 'ByVal As String'をC' char * 'と同等にすると決めました。 VB6ランタイムでは、現在のWindowsコードページに従って、元のUnicode文字列のコピーを "ANSI"形式で作成し、そのコピーのアドレスをDLLに渡します。完全性のために、VB6とのDLLの統合に関する[元のMicrosoft VB6のドキュメント](http://vb.mvps.org/tips/vb5dll.asp)があります。 – MarkJ

3

これらは異なる言語であるため、 VB.NETには、C#が多くの理由で不可能なことがたくさんあります。正直言って問題は見えない。

私はあなたが単にref char []を実行しただけで、うまくいけばいいと付け加えるべきです。私が見る1つの問題は、あなたの呼び出し規約が一致しないことです。

また、メモリ例外エラーが発生した可能性があります。

+0

上記のすべてのコードでは、呼び出し規約がうまくいきます。 'stdcall'です。 AVは 'ref string'が' char * 'と単に一致しないためです。そのためにはC#で 'StringBuilder'を使用しなければなりません。ネイティブコードが有効な.net Stringオブジェクトを構築する方法はありません。 –

0

文字列が不変で始まるので、関数によってバッファを変更できるようにVBが何らかの方法でウィザードを呼び出すと思います。おそらく、内部的にはVBが実際にStringBuilderも渡しているのでしょう。

これは、VBチームがVB6のようなAPI呼び出しを行うように設計したコールであれば、私は驚くことはありません。

関連する問題