0

最近、C++ と C++/CLI (.NET) が混在するプログラムを継承しました。これは、ネットワークを介して他のコンポーネントとインターフェイスし、一部の特別なハードウェアのドライバー DLL とインターフェイスします。ただし、使用されているものが最適ではないように思われるため、ネットワーク経由でデータを送信する最良の方法を見つけようとしています。

データは、次のような C++ 定義の構造体に格納されます。

    struct myCppStructure {
        unsigned int field1;
        unsigned int field2;
        unsigned int dataArray[512];
    };

C++/CLI から構造自体にアクセスすると、プログラムは正常に動作します。問題は、ネットワーク経由で送信するために、現在のコードが次のようなことを行っていることです。

    struct myCppStructure* data;
    IntPtr dataPtr(data);
    // myNetworkSocket is a NetworkStream cast as a System::IO::Stream^
    System::IO::BinaryWriter^ myBinWriter = gcnew BinaryWriter(myNetworkSocket);
    __int64 length = sizeof(struct myCppStructure) / sizeof(__int64);
    unsigned __int64* ptr = static_cast<__int64*>(dataPtr.toPointer());
    for (unsigned int i = 0; i < (length / sizeof(unsigned __int64)); i++)
        myBinWriter->Write((*ptr)++);

通常の C++ では、次のような呼び出しになります。

    myBinWriter->Write(ptr,length);

しかし、C++/CLI で同等のものを見つけることができません。System::IO::BinaryWriter には、基本的な型と、そのいくつかの array<>^ バージョンしかありません。より効率的なものはありませんか?

PS これらのレコードは 1 秒間に何度も生成されます。そのため、追加のコピー(マーシャリングなど)を行うことは問題外です。

注: 元の質問は C# に関するものでした。私が C# として考えていたものが、実際には .NET の下の "Managed C++" (別名 C++/CLI) であることに気付きませんでした。上記は、「C#」参照を「C++/CLI」参照に置き換えるように編集されています。これは、Managed C++ のすべてのバージョンで使用していますが、特に .NET 3.5 を使用しています。

4

3 に答える 3

1

やりたいことは、C++ 構造体がどのようにパックされているかを調べ、正しいStructLayout属性で構造体を定義することです。

固定長の int[] を定義するには、その中に固定サイズのバッファーを定義できます。これを使用するには、プロジェクトを /unsafe とマークする必要があることに注意してください。

これで、2 つの手順を使用してその構造体を byte[] に変換する準備が整いました。

  1. GCHandle.Allocを使用して構造体の配列をメモリに固定します。これは高速であり、パフォーマンスのボトルネックにはなりません。
  2. 次に、ソース IntPtr = handle .AddrOfPinnedObjectでMarshal.Copyを使用します(心配しないでください。これは memcpy と同じくらい高速です) 。

GCHandle を破棄すると、Serg Rogovtsev が言及した「書き込み」オーバーロードを使用してバイトを書き込む準備が整います。

お役に立てれば!

于 2012-07-31T21:00:01.513 に答える
1

あなたの構造は「基本型」と「それらの配列」で構成されています。を使用して順番に書き込めないのはなぜBinaryWriterですか?何かのようなもの

binWriter.Write(data.field1);
binWriter.Write(data.field2);
for(var i = 0; i < 512; i++)
    binWriter.Write(data.dataArray[i]);
于 2012-07-31T21:04:02.020 に答える
0

C# では、次のことができます。構造を定義することから始めます。

[StructLayout ( LayoutKind.Sequential )]
internal unsafe struct hisCppStruct
{
    public uint field1;
    public uint field2;
    public fixed uint dataArray [ 512 ];
}

そしてバイナリライタで以下のように書きます。

hisCppStruct @struct = new hisCppStruct ();
@struct.field1 = 1;
@struct.field2 = 2;
@struct.dataArray [ 0 ] = 3;
@struct.dataArray [ 511 ] = 4;

using ( BinaryWriter bw = new BinaryWriter ( File.OpenWrite ( @"C:\temp\test.bin") ) )
{
    int structSize = Marshal.SizeOf ( @struct );
    int limit = structSize / sizeof ( uint );

    uint* uintPtr = (uint*) &@struct;

    for ( int i = 0 ; i < limit ; i++ )
        bw.Write ( uintPtr [ i ] );
}

マネージド C++ でもまったく同じことができると確信しています。

于 2012-08-01T06:42:24.480 に答える