Отправка структуры C # в C ++ через сокет - PullRequest
1 голос
/ 08 апреля 2011

Я хочу отправить структуру в C # на C ++, используя сокеты.

Например, я использую эту структуру:

[StructLayout(LayoutKind.sequential, Pack = 1)]
struct pos {
    public int i;
    public float x;
};

Если я каким-то образом преобразую ее в байты и отправлю черезсеть, я должен быть в состоянии привести его к этому в C ++:

struct pos {
    int i;
    float x;
};

... Я думаю.

1) как вы разбиваете экземпляр структуры в C #, чтобы отправить егопо сети?

2) можно ли безопасно привести его к структуре c ++, как только я ее получу?

Спасибо

Ответы [ 2 ]

5 голосов
/ 08 апреля 2011

Маршаллер помогает конвертировать структуры .NET и необработанные байты.В этом ответе я опубликовал простое решение, которое сводится к Marshal.StructureToPtr и Marshal.PtrToStructure.В отличие от более продвинутых решений, предложенных Иоганном дю Туа, это, на мой взгляд, лучшее, что вы можете сделать, если все, что вы хотите сделать, это протолкнуть некоторые структуры через поток байтов.

Если вы сделаете этовы можете безопасно привести к структуре C ++, если длина верна, и ваша структура C ++ объявлена ​​с той же упаковкой, что и структура C # (т. е. #pragma pack в VC ++ или __attribute__((packed)) в GCC).

Обратите внимание, что это также работает со строками C фиксированной длины, но не будет заботиться о порядке следования больших значений.Я нашел простое решение - предоставить геттеры и сеттеры для последней проблемы, которые просто поменяют байты соответствующим образом (с BitConverter).


Некоторая проработка упаковки: Возьмите следующую структуру:

struct MyStruct {
    uint8_t a;
    float b;
};

С объявлением C # с StructLayout, Pack = 1, эта структура будет иметь размер пять байтов.Структура C ++, однако, может иметь восемь байтов (или даже больше), в зависимости от упаковки компилятора по умолчанию, который может с радостью вставить некоторые байты заполнения для выравнивания значения с плавающей точкой на 32-битной границе (просто пример).Из-за этого вы должны применять одну и ту же упаковку к структуре C # и C ++.В Visual C ++:

#pragma pack(push, 1)
// ... struct declarations...
#pragma pack(pop)

Это означает, что все структуры, объявленные между двумя прагмами, будут иметь упаковку из одного.В GCC:

struct x {
// ...
} __attribute__((packed));

Это будет делать то же самое.Вы можете #define __attribute__(x) на платформах Windows и #ifdef _WIN32 вокруг прагм, чтобы сделать код совместимым с обоими мирами.

1 голос
/ 08 апреля 2011

Вы можете либо закодировать его в формате, подобном JSON (существует множество парсеров JSON, посмотрите список на сайте json.org), XML илипросто сверните свое собственное.Вы также можете попробовать уже созданные библиотеки, такие как Protobuf , который позволяет сериализовать ваши структуры, которые вы создадите, с помощью файла в формате .proto (и использовать Protobuf-Net для C #).Другой вариант будет Thrift , который обеспечивает способ сериализации, но также предоставляет готовую к использованию систему RCP.Он поддерживает c #, c ++ и множество других языков по умолчанию.

Так что это зависит от вкуса, выбирайте: D

...