Вот более конкретные примеры обоих:
Пример сериализации:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef struct {
char value[11];
} SerializedInt32;
SerializedInt32 SerializeInt32(int32_t x)
{
SerializedInt32 result;
itoa(x, result.value, 10);
return result;
}
int32_t DeserializeInt32(SerializedInt32 x)
{
int32_t result;
result = atoi(x.value);
return result;
}
int main(int argc, char **argv)
{
int x;
SerializedInt32 data;
int32_t result;
x = -268435455;
data = SerializeInt32(x);
result = DeserializeInt32(data);
printf("x = %s.\n", data.value);
return result;
}
При сериализации данные сглаживаются таким образом, чтобы их можно было впоследствии сохранить и развернуть.
Маршаллинг Демо:
(MarshalDemoLib.cpp)
#include <iostream>
#include <string>
extern "C"
__declspec(dllexport)
void *StdCoutStdString(void *s)
{
std::string *str = (std::string *)s;
std::cout << *str;
}
extern "C"
__declspec(dllexport)
void *MarshalCStringToStdString(char *s)
{
std::string *str(new std::string(s));
std::cout << "string was successfully constructed.\n";
return str;
}
extern "C"
__declspec(dllexport)
void DestroyStdString(void *s)
{
std::string *str((std::string *)s);
delete str;
std::cout << "string was successfully destroyed.\n";
}
(MarshalDemo.c)
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char **argv)
{
void *myStdString;
LoadLibrary("MarshalDemoLib");
myStdString = ((void *(*)(char *))GetProcAddress (
GetModuleHandleA("MarshalDemoLib"),
"MarshalCStringToStdString"
))("Hello, World!\n");
((void (*)(void *))GetProcAddress (
GetModuleHandleA("MarshalDemoLib"),
"StdCoutStdString"
))(myStdString);
((void (*)(void *))GetProcAddress (
GetModuleHandleA("MarshalDemoLib"),
"DestroyStdString"
))(myStdString);
}
При маршалинге данные не обязательно должны быть сведены, но их необходимо преобразовать в другое альтернативное представление. весь кастинг является маршалингом, но не весь маршалинг кастингом.
Маршалинг не требует участия в динамическом распределении, он также может быть просто преобразованием между структурами. Например, у вас может быть пара, но функция ожидает, что первый и второй элементы пары будут другими; вы преобразуете / memcpy одну пару в другую, не сделаете эту работу, потому что fst и snd перевернутся.
#include <stdio.h>
typedef struct {
int fst;
int snd;
} pair1;
typedef struct {
int snd;
int fst;
} pair2;
void pair2_dump(pair2 p)
{
printf("%d %d\n", p.fst, p.snd);
}
pair2 marshal_pair1_to_pair2(pair1 p)
{
pair2 result;
result.fst = p.fst;
result.snd = p.snd;
return result;
}
pair1 given = {3, 7};
int main(int argc, char **argv)
{
pair2_dump(marshal_pair1_to_pair2(given));
return 0;
}
Концепция маршалинга становится особенно важной, когда вы начинаете иметь дело с помеченными объединениями разных типов. Например, вам может быть сложно заставить движок JavaScript печатать для вас «c-строку», но вы можете попросить его вывести для вас упакованную c-строку. Или, если вы хотите напечатать строку из среды выполнения JavaScript в среде исполнения Lua или Python. Они все струнные, но часто не обходятся без маршалинга.
Недавно меня раздражало то, что JScript размещает маршал C # как «__ComObject» и не имеет документированного способа играть с этим объектом. Я могу найти адрес, где он находится, но я действительно ничего больше не знаю об этом, поэтому единственный способ по-настоящему понять это - ткнуть в нее любым возможным способом и, надеюсь, найти полезную информацию об этом. Таким образом, становится проще создать новый объект с более дружественным интерфейсом, таким как Scripting.Dictionary, скопировать в него данные из объекта массива JScript и передать этот объект в C # вместо массива JScript по умолчанию.
test.js:
var x = new ActiveXObject("Dmitry.YetAnotherTestObject.YetAnotherTestObject");
x.send([1, 2, 3, 4]);
YetAnotherTestObject.cs
using System;
using System.Runtime.InteropServices;
namespace Dmitry.YetAnotherTestObject
{
[Guid("C612BD9B-74E0-4176-AAB8-C53EB24C2B29"), ComVisible(true)]
public class YetAnotherTestObject
{
public void send(object x)
{
System.Console.WriteLine(x.GetType().Name);
}
}
}
выше печатает «__ComObject», который с точки зрения C # является чем-то вроде черного ящика.
Еще одна интересная концепция заключается в том, что у вас может быть понимание того, как писать код, и компьютер, который знает, как выполнять инструкции, так что, как программист, вы эффективно воплощаете концепцию того, что вы хотите, чтобы компьютер делал из своего мозга к образу программы. Если бы у нас было достаточно хороших маршаллеров, мы могли бы просто думать о том, что мы хотим сделать / изменить, и программа изменилась бы таким образом, не печатая на клавиатуре. Итак, если бы у вас был способ сохранить все физические изменения в вашем мозге в течение нескольких секунд, когда вы действительно хотите записать точку с запятой, вы могли бы преобразовать эти данные в сигнал для печати точки с запятой, но это крайность.