私はこれについて Google でぐるぐる回っており、あらゆる種類の議論、多くの提案を見つけることができますが、何もうまくいかないようです. イメージをバイト配列として受け取る ActiveX コンポーネントがあります。TLB のインポートを行うと、次の署名が付いてきます。
int HandleImage([MarshalAs(UnmanagedType.Struct)] ref object Bitmap);
それにバイト[]を渡すにはどうすればよいですか?
同様の署名でデータを返すことができる別の関数があり、「null」を渡すことができるため機能します。返される型は byte[1..size] (非ゼロ境界 byte[]) です。しかし、戻ってきたものを渡そうとしても、型の不一致の例外が発生します。
詳細:
IDispatch インターフェイス シグネチャのメソッドを編集してきました (ILSpy を使用して、自動生成された相互運用アセンブリからインターフェイスを抽出します)。次のほぼすべての組み合わせを試しましたが、常にタイプの不一致例外が発生します。
- 「ref」の追加と削除
- パラメータのデータ型を「byte[]」または「Array」に変更する
- [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UI1)] としてマーシャリングします。MarshalAs をかなりいじってみると、IDispatch はこれらの属性を使用しないことに確信が持てるようになりました。
また、「ref object」インターフェースをそのまま使用して、別のタイプを渡そうとしました: byte[], Array.CreateInstance(typeof(byte) (どちらも同じだと思いますが、誰かがそれを提案しているのを見つけたので、できませんでした)しようとすると痛い)。
渡す適切な配列を作成する Delphi コードの例を次に示します。
var
image: OLEVariant;
buf: Pointer;
image := VarArrayCreate([0, Stream.Size], VarByte);
Buf := VarArrayLock(image);
Stream.ReadBuffer(Buf^, Stream.Size);
VarArrayUnlock(image);
同じことを行う C コードを次に示します。C# から動作させることができない場合は、マネージ C++ を介して呼び出すことができると思いますが、すべてを 1 つのプロジェクトにまとめたいと思います。
long HandleImage(unsigned char* Bitmap, int Length)
{
VARIANT vBitmap;
VariantInit (&vBitmap);
VariantClear(&vBitmap);
SAFEARRAYBOUND bounds[1];
bounds[0].cElements = Length;
bounds[0].lLbound = 1;
SAFEARRAY* arr = SafeArrayCreate(VT_UI1, 1, bounds);
SafeArrayLock(arr);
memcpy(arr->pvData, Bitmap, Length);
SafeArrayUnlock(arr);
vBitmap.parray = arr;
vBitmap.vt = VT_ARRAY | VT_UI1;
long result;
static BYTE parms[] = VTS_PVARIANT;
InvokeHelper(0x5e, DISPATCH_METHOD, VT_I4, (void*)&result, parms,
&vBitmap);
SafeArrayDestroy(arr);
VariantClear(&vBitmap);
return result;
}