Hier finden Sie genauere Beispiele für beides:
Beispiel für Serialisierung:
#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;
}
Bei der Serialisierung werden die Daten so flach gemacht, dass sie gespeichert und später wieder entflacht werden können.
Marshalling Demo:
( 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);
}
Beim Marshaling müssen die Daten nicht unbedingt reduziert werden, aber sie müssen in eine andere Darstellung umgewandelt werden.
Marshaling erfordert keine dynamische Zuweisung beteiligt zu sein, kann es auch nur Transformation zwischen Strukturen sein. Zum Beispiel könnten Sie ein Paar haben, aber die Funktion erwartet, dass das erste und zweite Element des Paares andersherum sind; Sie casting/memcpy ein Paar zu einem anderen wird nicht die Arbeit tun, weil fst und snd umgedreht werden.
#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;
}
Das Konzept des Marshaling wird besonders wichtig, wenn man mit vielen Arten von Tagged Unions zu tun hat. So ist es zum Beispiel schwierig, eine JavaScript-Engine dazu zu bringen, einen "c-String" für Sie zu drucken, aber Sie können sie bitten, einen "wrapped c-String" für Sie zu drucken. Oder wenn Sie eine Zeichenkette von der JavaScript-Laufzeit in einer Lua- oder Python-Laufzeit ausgeben wollen. Das sind alles Strings, aber oft kommen sie nicht ohne Marshaling aus.
Ein Ärgernis, das ich vor kurzem hatte war, dass JScript Arrays Marshal zu C# als "__ComObject", und hat keine dokumentierte Möglichkeit, mit diesem Objekt zu spielen. Ich kann die Adresse finden, wo es ist, aber ich weiß wirklich nichts anderes darüber, so dass der einzige Weg, um es wirklich herauszufinden, ist es in irgendeiner Weise möglich zu stochern und hoffentlich nützliche Informationen über sie zu finden. So wird es einfacher, ein neues Objekt mit einer freundlicheren Schnittstelle wie Scripting.Dictionary zu erstellen, die Daten aus dem JScript-Array-Objekt hineinzukopieren und dieses Objekt anstelle des Standard-Arrays von JScript an C# zu übergeben.
( 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);
}
}
}
oben gibt "__ComObject" aus, was aus Sicht von C# so etwas wie eine Blackbox ist.
Ein weiteres interessantes Konzept besteht darin, dass Sie vielleicht wissen, wie man Code schreibt, und einen Computer haben, der weiß, wie man Anweisungen ausführt, so dass Sie als Programmierer das Konzept dessen, was der Computer tun soll, von Ihrem Gehirn auf das Programmbild übertragen. Hätten wir genügend gute Marshaller, könnten wir einfach daran denken, was wir tun/ändern wollen, und das Programm würde sich entsprechend ändern, ohne auf der Tastatur herumtippen zu müssen. Wenn Sie also eine Möglichkeit hätten, alle physikalischen Veränderungen in Ihrem Gehirn für die wenigen Sekunden zu speichern, in denen Sie wirklich ein Semikolon schreiben wollen, könnten Sie diese Daten in ein Signal zum Drucken eines Semikolons umwandeln, aber das ist ein Extrem.