|
Read the documentation for the StructLayoutAttribute . It does have a Pack property which allows you to control the packing.
Remoting is basically serialization over transport channels and gives you the capability for aspect-oriented programming (inserting channel sinks to log calls, encrypt/decrypt messages, compress messages, and otherwise mangle messages). For talking to a legacy C++ socket listener, this wouldn't work. Remoting is best used between .NET applications but could - with a LOT of work - work between managed and unmanaged solutions. Web Services - for its greatly simplified interfaces - is better suited for legacy solutions.
When it comes to performance, marshaling the class/struct to a buffer would definitely be faster. Remoting and Web Services both require serialization. The .NET FCL provides both SOAP and binary formatters for serialization, the latter of which is MUCH faster than the former and uses less bandwidth (since SOAP - being yet another grammar derived from XML - has a lot of overhead).
Corinna's original idea I think is the right track, which is basically what you asked for.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thank you very much. That was very helpful.
|
|
|
|
|
I have tried this successfully. But only with a class and struct that does not contain a string or byte array field. For example:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct MyPacket
{
public MyPacket(DateTime dateTime, int line, int msgLen)
{
dt = DateTime.Now;
iLine = 0;
iMsgLen = 0;
msg = new byte[80];
}
public DateTime dt;
public int iLine;
public int iMsgLen;
public byte[] msg;
}
Marshal.Sizeof(MyPacket) returns 20. So when it is sent over the network I the contents of msg is lost. Obviously because byte[] is a reference to an array.
So, now the question is how can I pass classes or structures as binary data if they contain arrays, for example a message that contains a stock quote needs to include a symbol name (i.e. "MSFT").
Can you help me out with this as well? I have not been able to find any examples or documentation that shows StructLayout being used with structures or classes that contain strings or arrays.
|
|
|
|
|
I have tried this successfully. But only with a class and struct that does not contain a string or byte array field. For example:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct MyPacket
{
public MyPacket(DateTime dateTime, int line, int msgLen)
{
dt = DateTime.Now;
iLine = 0;
iMsgLen = 0;
msg = new byte[80];
}
public DateTime dt;
public int iLine;
public int iMsgLen;
public byte[] msg;
}
Marshal.Sizeof(MyPacket) returns 20. So when it is sent over the network I the contents of msg is lost. Obviously because byte[] is a reference to an array.
So, now the question is how can I pass classes or structures as binary data if they contain arrays, for example a message that contains a stock quote needs to include a symbol name (i.e. "MSFT").
Can you help me out with this as well? I have not been able to find any examples or documentation that shows StructLayout being used with structures or classes that contain strings or arrays.
By the way, what does Microsoft MVP mean? Are you a Most Valuable Player at Microsoft?
Thanks for the assistance,
Robert G. Ellis
|
|
|
|
|
See the MarshalAsAttribute documentation. To make your implementation easier, use string instead of byte[] but be sure to marshal it as an ANSI string (since you're obviously using bytes for chars and not double-byte chars):
[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
public struct Packet
{
public Packet(DateTime dt, int line, string msg)
{
if (msg == null) throw new ArgumentNullException("msg");
this.dt = dt;
this.line = line;
this.msglen = msg.Length;
this.msg = msg;
}
public DateTime dt;
public int line;
public int msglen;
[MarshalAs(UnmanagedType.LPStr)]public string msg;
} Now it's also possible that you may need to send a by-value string, in which case you use UnmanagedType.ByValTStr (it will be an ANSI string because of the CharSet property in the StructLayoutAttribute ) and specify a constant size, which I know is often a valid limitation of chat software. This latter case is most likely what you'll need to do.
Also, keep in mind that the DateTime in .NET and whatever date/time struct/value you're using in C++ will most likely have different epochs. The DateTime struct uses 00:00:00 Jan 1, 0001 AD. Adjust your time as necessary. Often - depending on how your legacy solution is already coded, you should also use DateTime.ToUniversalTime or DateTime.UtcNow to use a UTC date which is based on zulu time (Greenwhich Mean Time). This ensures that your dates always have a common base. The clients use their locale information to get the local time.
goodpilot wrote:
By the way, what does Microsoft MVP mean? Are you a Most Valuable Player at Microsoft?
It means "Most Valuable Professional". You can read more about the program at http://mvp.support.microsoft.com[^].
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I was able to get it working with your help sir. Thank you very much.
|
|
|
|
|
I think you can do this in more than one way. Any way has it's pros and cons.
One way would be using MS Messaging Queue to transport your object. Besides beeing a simple way without too much pain on thinking how to transmit it on the networking part, this requires to have the MSMQ services running.
An other way is remoting. I haven't done much with remoting yet, so perhaps I may be wrong here.
An other way would be to serialize the object (you can choose between XML or binary for example) and send the serialized object via TCP/IP and deserialize on the other machine. This includes a bit more work (serializing) and has the lower level transport. If the last part is already done, this might be a fast switch.
[Sorry: I've overseen "without serialization", so forget the last possibility.]
HTH,
Sascha
--
http://www.livingit.de
http://www.mobile-bookmarks.info
http://www.not2long.net
|
|
|
|
|
Did you read his post? He doesn't want to use serialization because he's talking to a socket listener already written in C++ - a legacy solution. Remoting and a serialized graph over a socket connection are out. MSMQ is out because he's already using a socket listener. Should he decide to redo the server solution.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi,
have you read my edit of the post? I wrote I have just overseen the "without serialization", and just after I clicked 'Submit' I read this two words.
Using the marshalling way is possible the best way for his problem.
Bye,
Sascha
--
http://www.livingit.de
http://www.mobile-bookmarks.info
http://www.not2long.net
|
|
|
|
|
I want to programatically check wether a url exists without trying to download it.
previously ive just used a webclient and tryed to download it inside a try catch block but this obviously isnt the best way
any help would be much appreciated
-Kris
|
|
|
|
|
The only way to determine whether a file exists without going to all the trouble using WebDAV extensions (which may not be supported by the web server, and often isn't for unauthenticated users) would be to make a request for it. You wouldn't have to necessary stream the response to a file, though, just check the HttpWebResponse.StatusCode .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi, everyone
1. When I call a function imported from a VC6 dll, it returns 42949672970 when it is supposed to return -1. Anyone knows why?
2. There's another function in this VC6 dll like this loginDlg(LPCTSTR Name, long NameLength). This function will return the login name by the first parameter, 2nd parameter is tell the function how long the buffer is.
How to import and use this kind of functions properly?
Thanks in advance.
|
|
|
|
|
Looks like the address of a return value is being returned. How are you declaring the native function to be P/Invoked?
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Here is how the function declare in the VC6 dll head file
#ifndef LONG<br />
typedef long LONG; <br />
#endif<br />
<br />
LONG _stdcall SelectChildProjects<br />
(<br />
LONG lProjectId <br />
);
Here is how I declare the function in my .Net code
<br />
[DllImport("dcli.dll", EntryPoint="SelectChildProjects")]<br />
public static extern long SelectChildProjects(long lProjectId);
Thanks.
|
|
|
|
|
A LONG (long ) in C++ is a 32-bit integer. A long (Int64 ) is a 64-bit integer. You're marshaling is all wrong which might explain why you're getting extra data from overflow. You should declare it as:
[DllImport("dcli.dll")]
public static extern int SelectChildProjects(int lProjectId); Notice I also dropped the EntryPoint property, which you only need in cases where your declared method differs in name from the entry point exported by the native DLL.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thank you very much! It works prefectly now.
|
|
|
|
|
Hi,
Is it possible to loop through a datagrid? For eg.
for (int i=0;i
|
|
|
|
|
Loop through the underlying data source, not the DataGrid itself.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Actually the source is a dummy query which has no underlying table or any such database connection. The query exists only because I wanted to populate the datagrid. Its the data grid I want to manipulate actually. Or if there is another way to populate the rows and cols of a datagrid into an array that would be fine. Do you know if I can do that? I could the loop through the array and retreive the records I want.
Thanks
Al
|
|
|
|
|
Read the documentation for the DataGrid.DataSource property in the .NET Framework SDK. It just has to be an object that implements IList or IListSource , so you could use an array or a collection as well. This is true for the rest of the data-bindable controls using a CurrencyManager .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
A liitel addition to what Heath Stewart said....
grid1.DataSource = dataTable;
CurrencyManager cm = (CurrencyManager)this.BindingContext[grid1.DataSource, grid1.DataMember];
DataView dv = (DataView)cm.List;
for(int i = 0; i < dv.Count ; i++)
{
//do what u want
}
Ruchi
|
|
|
|
|
Whether you're binding to a DataSet or DataTable , it's a lot easier to just get the table you want to enumerate and create a DataView over that table using:
DataView dv = new DataView(dataTable1);
DataView dv = dataTable1.DefaultView;
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
What is a limitation on a property ? I think none of the below are but am i correct ?
Choice 1
Properties cannot be inherited.
Choice 2
Properties do not allow for lazy initialization.
Choice 3
Properties cannot be defined as write-only.
Choice 4
Properties cannot return unsigned value types.
Choice 5
Properties cannot be used as method parameters.
II
(I feel "abstract" is right. Can anyone confirm ?
What modifier do you use in a base class to require any derived class to implement a property?
Choice 1
sealed
Choice 2
virtual
Choice 3
protected
Choice 4
abstract
Choice 5
mustoverride
Thanks
GK
|
|
|
|
|
Properties do not allow for lazy initialization.
I never heard of lazy initialization.
Properties cannot be inherited.: Property itself of corse it cannot be inheriated, but as a part of a class there is no probblem.
As for second abstract is correct.
// btw: May I ask from where these questions are?
Q:What does the derived class in C# tell to it's parent?
A:All your base are belong to us!
|
|
|
|
|
CWIZO wrote:
I never heard of lazy initialization.
Then I suggest you look at ROTOR's codebase. Its full of it. EG
object foo = null;
public object Foo
{
get {return (foo == null) ? (foo = new object()) : foo;}
}
CWIZO wrote:
Properties cannot be inherited.: Property itself of corse it cannot be inheriated, but as a part of a class there is no probblem.
Now only a VB person would think that way!
top secret
|
|
|
|