問題
したがって、この問題の理由は少し複雑であり、FoxPro が Unicode 文字列をサポートしておらず、COM が文字列データにのみUnicode を使用するように明示的に定義されているという事実に根ざしています。このインピーダンスの不一致を除いて、不透明なバイナリ データを含む文字列を渡すと問題なく動作します。
FoxPro は、文字列引数を返す関数または文字列引数を持つ関数を呼び出すたびに、ユーザー コードに戻る前に内部的にコードページ変換を行います。この変換は明らかに、文字列に隠されているバイナリ データを移動するあらゆる種類の問題を引き起こします。
解決策 (問題あり)
うまくbyte[]
いくはずで、部分的にはうまくいきます。この「部分的に」は、バイナリデータを文字列に隠そうとした原因です。
これが取り引きです(そして、私が使用しているのはVFP 9 SP2でのみこれを確認しました)。C# COM 側では、FoxProは次のように定義されたメソッドを処理できます。
public byte[] GetData() { ... }
そのメソッドを呼び出すと、FoxPro はデータをバイナリとして「マークされた」文字列として正しく返します ( 「マークされたバイナリ文字列」の説明については、 CreateBinary()を参照してください)。これらの文字列は、非バイナリ文字列と同様に、すべての標準文字列操作関数をサポートします。まさに私が必要としていたもの。byte[]
これは、元の例のように、FoxPro によって実装され、パラメーターを持つ C# に渡される COM ソース イベント インターフェイスにも当てはまります。
CreateBinary()
FoxPro が文字列を COM オブジェクトに送信するときにコードページ変換を行わないようにするには、文字列をバイナリとしてマークし、変換をバイパスする関数を使用して文字列を作成する必要があります。
ただし、FoxPro が処理しないのは、次のように定義されたメソッドに「バイナリ」文字列を渡すことです。
public void SendData(byte[] data) { ... }
これを呼び出そうとすると、無効なパラメータ タイプの COM 例外が発生します。
これが適切に機能しない理由はいくつかあります。これは基本的に、FoxPro がマーシャリングを自動的に処理しないことに起因します。
回避策
では、何ができるでしょうか?このような関数を定義します。
public void SendData(object data) { ... }
これで、バイナリ マーク付きの文字列を使用して関数を呼び出すことができます。FoxPro はコードページの変換を行わず、データは .NET に渡されます。しかし、data
パラメーターのデータ型は何ですか? ですSystem.Byte[*]
。そのアスタリスクは何のためですか?私は手がかりがなかったので、優秀な人たちに SO で尋ねました。
ゼロ以外の下限を持つ配列であることがわかります。
byte[]
したがって、FoxPro からバイナリ データを取得する場合、FoxPro 配列が 1 ベースであるという事実を除いて、直接キャストすることができます。
この問題を解決するために、C# で次のことを行います。
public void SendData(object data) {
byte[] buf = FPHelper.ToSZArray(data);
// Use buf here
}
public class FPHelper {
public static byte[] ToSZArray(object param) {
var array = param as Array;
if (array == null)
throw new ArgumentException("Expected a binary array, (did you use CREATEBINARY()?)");
if (array.Rank != 1)
throw new ArgumentException("Expected array with rank 1.", "param");
var dest = new byte[array.Length];
Buffer.BlockCopy(array, 0, dest, 0, array.Length);
return dest;
}
}
FoxPro では、唯一の要件は、バイナリとして「マーク」された文字列で呼び出すことです。
cData = "Hello World!" + CHR(13) + CHR(12) + CHR(0)
oComObject.SendData(CREATEBINARY(cData))