 |
|
|
Hi guys. I'm trying to write a method: in the managed part it should preffereabley receive a string array, but in not, a string ref would be fine, the string should change in the unmanged part (allocation and stuff). something like that: c#: { string s = ""; updateString(ref s); (the c++ method); console.writeLn(s); Marshal.FreeBstr(Marshal.StringToBSTR(s)); } c++: void updateString(BSTR * s){ *s = SysAllocString(L"whatever"); //or: Cstring cstring = ""whatever"; *s = cstring.AllocSysString(); }
In both ways, the data gets to the managed part ok, but the memory isn't freed, not entirely anyways (after checking the Task manager and looping over the function call for a large number of iterations)
What am I missing??! 
Thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Is it possible to do this with mixed structures? My program is accessing an area of memory being written as a C structure by a piece of external hardware. Within this structure there are ints, char, floats and arrays, and I need to be able to access them all.
I have had a reasonable amount of success with a C# class, but it falls over because arrays tend to be included as references, not as actual memory space. 
Paul
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Is it possible to create a function to create a global string to struct function?
Because in this example, I would need a different function for each struct.
Thanks! and excelent work btw!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Absolutely, You can create global strings and functions in an internal class as static types and then create a static reference to that class. That is the only way that I know of that can simulate a C++ header file that could contain global variables. If this doesn't help send me some pseudo code for your situation and what you want to achieve and then I'll see if I could whip it up for you.
Diego
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
My problem is this:
I need to write a function for each struct I use, because of the casting. I cannot find other solution as long as I dont use generics (which I can't at the moment) I tried to send a parameter as 'Type' but you cannot use it for casting.
private void CopyStringToHeader(string sBuffer, out InterfaceRecordStruct ms) { IntPtr pBuf = Marshal.StringToBSTR(sBuffer); ms = (InterfaceRecordStruct)Marshal.PtrToStructure(pBuf,typeof(InterfaceRecordStruct)); Marshal.FreeBSTR(pBuf); }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
It's only purpose in life is for a TCP/IP client/server setup where a proprietary buffer protocol is used to pass string transactions via sockets.
A traditional client/server database architecture would have little need of this.
Diego
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I am able to successfully overlay a string buffer on a structure using your code, but when I am trying to convert a structure back to a string, the null character is placed in the end, just cutting out the last character of each member. We are also using a proprietary buffer protocol to pass string transactions via sockets. Any tips to handle this?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Unfortunately, this causes a memory leak. After the string is marshaled to the structure, you should call the static FreeBSTR method on the Marshal class to release the pointer returned from StringToBSTR.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
I knew you guys were going to start dumping on me;P As I was driving home I thought about the memory leaks and you beat me to the punch before I could edit the code to destroy the struct and pointer. I appreciate your comments. So what you think about this for a beginner? I couldn't find one decent example of this anywhere.
Diego
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Diego,
I think that this is ok, but I don't see why you wouldn't use Serialization, or something else. This is completely dependent on the structure being composed of strings, as well as the strings being embedded in the structure.
I think it is good for a specific use case, but for the general case, it needs some work.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
You're absolutely right in it's current form that it has one specific use. We have our own proprietary protocol to send transactions from different servers with some being Unix and all of our clients on windows so our owners wanted a universal solution without having to perform a total rewrite. The current method of managing those buffer changes uses substringing and that is a nightmare if I have 50 fields and field position 10 changed in the number of bytes. In that case I would have to readjust fields 11 to 50 to compensate for that. If I use a struct all I have to do is pass the buffer into the struct and let it handle the byte ordering and if I needed to change one of the field lengths I only have to change the SizeConst and the struct will automatically adjust the byte order for me.
I am very interested in serialization as I am new to C#. How would you implement my issue using serialization?
Diego
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Deigo,
No, in this case, I would not use serialization, as the specific use that you have is applicable to your unique situation (and, as a matter of fact, seems to handle it quite well). Actually, from a management perspective, it is quite novel. Good work.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Diego,
I think you should be congratulated for, as we say in the land of OZ, "having a go". This topic is of interest to me and is far from "pointless" when you have to interact with existing systems.
I took a different approach to resolve the moving field issue, using individual Marshal calls and an enum to define the field positions.
public class SomePacket { enum Fields { PktLength, PktLenghByte2, // Pad out the length with additional fields Command, CommandByte2, CommandByte3, CommandByte4, SmallIntData, SmallIntDataByte2, Last }
private Int16 m_smallData;
public int ToBuffer(Byte [] buf, int offset /* offset to start writing buffer*/) { Marshal.WriteInt16(buf, offset + (int)Fields.PktLength], (int_Fields.Last); Marshal.WriteInt32(buf, offset + (int)Fields.Command], 1234); Marshal.WriteInt16(buf, offset + (int)Fields. SmallIntData], m_smallData); } } Another issue with you approach is the extra marshal into a string, what happens is the data contains a null, not to mention the overhead of an extra copy.
Cheers, Mark Abela
Mark Abela Software Engineer Inner Range
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
That's really cool Mark. Did you have as bad a time as I did trying to come up with a fix for this? This whole concept with marshalling is a bit new to me and I'm trying to understand it. It almost seems every little thing can lead up to a memory leak if marshalling isn't properly understood. I don't know if you've seen my update to the article but one of the other guys(casperone) pointed out that I wasn't freeing up my pointer so I added that.
Thanks for the tip on receiving nulls I never thought about that one. I am less than a beginner(7 days experience with sharp ) and probably not even worthy of conversing with you guys about sharp but I definetly welcome all the help I can get.
Diego
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Diego,
Never let a chance go by to use an enum . I didn't think too long about it, however if I did I might have defined a struct or class with the required packet layout and used Marshal.OffsetOf().
Chears, Mark Abela
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Gotta use those enums .
OffsetOf seems to be a good way of determining the size of objects and data types and a nice feature if you need to drill down to the bit level. I wonder how it would act between unicode and ansi values?
Sounds like a good idea to help each other out. You know what I learned yesterday? C sharp doesn't directly support indexed properties . I need that because I built class properties around my struct values in order for our vb6 apps to use it.
Diego
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |