I can use write(&stName,sizeof(stName),&FileName) and define a same struct in other program to read the file(XXX.h) when i use C, But I want do the same use C# and I should not use the unsafe mode. How do to solve the problem?
Edit:
thanks all. I will to try them
Edit:
Now if I want to use C write the Struct to file.h and use C# to read the struct from file.h, may I have chance solve that and not to count the offset? Because count the offset is not a good answer when I want to add some variable or other struct in the struct.
Look at the ISerializable interface and Serialization in general.
Even in C, this is a dangerous thing to do IMO. If you use a different compiler, operating system, architecture etc you can very easily "break" your data files - you're absolutely relying on the layout of the data in memory. It's a bit like exposing fields directly instead of properties - the in-memory layout should be an implementation detail which can be changed without the public form (the file) changing.
There are lots of ways of storing data, of course. For example:
Binary serialization (still pretty fragile, IMO)
XML serialization
Google's Protocol Buffers
Thrift
YAML
Hand-written serialization/deserialization e.g. using BinaryReader and BinaryWriter
There are balances in terms of whether the file is human readable, speed, size etc. See this question for answers to a similar question about Java.
You should take a look at the NetDataContractSerializer. You can markup those portions of the struct that you wish to serializer and use a file stream to write them out.
Look at the StructLayoutAttribute
Use Managed C++ or C++/CLI. It can read your .h file struct. It can read and write using:
read(in, &structure, sizeof(structure));
write(out, &structure, sizeof(structure));
and it can transfer that data very simply to anything else in .NET.
You'll have to convert each member of the struct individually using Bitconverter.convert(). This works well when your struct holds numeric data types, but you might have to do something more complex when using structs that contain more complicated data types like strings, arrays, and collections. For purposes like this, you will want to check out the .Net serialization facilities that other have mentioned.
You can look into Google Protocol buffers as well. You may not want to add another dependency into your code, but it's meant to allow you to do this sort of thing.
Related
Can someone tell me if the RTL_BITMAP structure (for use with RtlInitializeBitMap) in C++ is the same as a BitArray in C#? If not, is there anything that can be changed to make it the same? The reason I ask is because I am trying to port some C++ code to C# and some of the code utilizes a code that converts the Bitmap in VOLUME_BITMAP_BUFFER to a RTL_BITMAP structure.
Can someone tell me if the RTL_BITMAP structure (for use with RtlInitializeBitMap) in C++ is the same as a BitArray in C#?
Well, they are not the same in as much as being identical. But these two types (and the associated RtlXXX functions in the case of RTL_BITMAP) essentially implement the same data structure. Namely a compact array of boolean values.
There is quite a lot of high level functionality available for the RTL_BITMAP type that is not offered by the BitArray type. However, you may very well not need any of that, and any that you do need is readily implemented on top of BitArray.
So in summary, BitArray seems like a good starting place for your translation, based on the information that you have provided.
I use BinaryWriter to write my items to stream. How i can write object to Stream and back without BinaryFormatter?
Simply, you need to (one of):
write code that (de)serializes each field/property in turn, using the (reader/)writer API over each member
write code that automates the first option at compile-time, generating C#
write code that automates the first option at runtime, generating IL (or C# which it compiles)
Taking into account nested objects, nulls, reference-tracking, collections, lists, serialization callbacks, string value-vs-reference equality, conversion operators, custom iterators, surrogates, serialization-contexts, IO buffering, etc.
Alternatively, use one of the many binary serializers that exist that already do that. I'm hugely biased as the author, but I'd use protobuf-net.
My biased answer is http://binaryserializer.codeplex.com.
It allows you to define bindings to control the exact format of the data.
Is there a way to customize the way a binary writer writes out to files so that I could read the file from a C++ program?
Eg:
myBinaryWriter.Write(myInt);
myBinaryWriter.Write(myBool);
And in C++:
fread(&myInt, 1, sizeof(int), fileHandle);
fread(&myBool, 1, sizeof(bool), fileHandle);
EDIT: From what I can see, if the length of a string is small enough to fit into one byte then that's how it writes it, which is bad if I want to read it back in in C++.
If you want to guarantee binary compatibility, possibly the easiest approach from c# is to ditch binary writer and just use a stream to write the bytes yourself. That way you get full control of the output data
Another approach would be to create an assembly that can write the data using c++/cli, so you can get direct compatibility with c++ from managed code.
You have some options you can choose:
Writing it byte-byte by yourself. this is possibly the worst option. it requires more work in both sides (the serializing and the de-serializing sides).
Use some cross-platforms serializers like Protobuf. it has ports for almost any platform, including C# (protobuf-net) and C++. and it's also easy to use and has really good performance.
you can use Struct and convert it yo byte array using Marshal.PtrToStructure (if you need the other way, you can use Marshal.StructureToPtr). there are plenty of examples in the internet. If you can use Managed CPP, you can use the same object so you can change the struct in one place and it will change in both places.
if you use Managed CPP, you can use the built-in serializers, such as BinaryFormatter...
i am writing a project in C#
i wanna save a class in binary file and then read that file it in C
i wanna know how can i do it without serialize and deserialize
please help me
You are talking about cross-platform serialization.
A few options:
serialize it as text (xml, json); text is still binary, after all - and simple
serialize it manually
use a third party cross-platform serializer
But whatever you do, don't use BinaryFormatter. The reason I stress this is that it is probably the first thing you'll see if you search for C# binary serialization, but is entirely inappropriate for your purposes. The format is proprietary, and includes type information that only makes sense from .NET (not really from unmanaged C).
I'm quite attached to "protocol buffers" as a serialization API, and there are both C# and C versions here.
Saving the state of an object to a file means serializing it.
Reading the state of an object from a file means deserializing it.
You have to use serialization/deserialization to do what you want.
Since you need to do this across different languages, using the built in serializers would probably not be very helpful.
You can use one of the XML serializers for the C# part, but then would have to parse the XML out in c.
Another option is to write your own custom serizlizer to do this. This way you have full control over the file format.
Do you want to save a class? This is not possible since classes are compiled into assemblies (exe,dll) in .net.
I think what you want is to save the state of an object or better suited, a struct to a file.
You can write all fields of the class to a file using the BinaryWriter class. Also you can have a look at this.
I presume you mean you want to have a C# application write a file. Then have a separate C/C++ application read that file? On that assumption, in C# you'll need to look into the System.IO namespace, and specifically the FileStream class.
On a side note, I'd really recommend writing a C# Class Library project that handles this read/write via .NET serialization classes and then invoke it nativly from your C# code, and use COM ([assembly: ComVisible(true)]) to access your .NET code from your C/C++ code.
I'm looking at protobuf-net for implementing various messaging formats, and I particularly like the contract-based approach as I don't have to mess with the proto compiler. one thing I couldn't quite find information on is, does this make it difficult to work cross-platform? there are a few C++ apps that would need to be able to parse PB data, and while I understand that protobuf-net serializes to the PB standard format, if I use the contract approach and not a proto file, how does the C++ side parse the data?
can (should?) I write a separate proto file for the (very few) cases where C++ needs to understand the data? and if so, how exactly do I know that the C++ class generated from the proto file is going to match the data from the no-proto-file C# side?
Yes, in theory at least they should match at the binary level, but you might want to limit yourself to types that map simply to ".proto" - so avoid things like DateTime, inheritance ([ProtoInclude]), etc. This also has the advantage that you should be able to use:
string proto = Serializer.GetProto<YourType>();
to get the .proto; it (GetProto) isn't 100%, but it works for basic types. But ultimately, the answer is "testing and tweaking"; perhaps design for interop from the outset - i.e. test this early.