C# -> C++ -> C# -> C++ interop question RRS feed

  • Question

  • I'm writing a high-performance server that will be deployed comercially. I'm having problem choosing between StringBuilder or String for interop. Following is the way my application works.

    1. The C# program is started by the user, which loads the C++ core - which has its own threads.

    2. C++ core starts accepting connections using I/O completion ports and responds to them.

    3. During connection establish phase, the c++ core has to interact with database. All the database code is implemented in c#, so it makes interop calls to the c# class.

    Step 3, is where the problem is. I'll be passing a WCHAR* (allocated buffer) from c++ core and the I can't figure out whether I should use StringBuilder or String in c# db class. I basically have two objectives here

    i) Choose the class that will provide better performance and also cause no memory fragmentation.
    ii) Be able to return (out) strings from c# db class.

    I initially went with StringBuilder class, however, I quickly ran into an issue. Even though I was providing a 256-character buffer from c++ core and in c# db class method definition I was specifying sizeconst of 256. The actual capacity of the StringBuilder parameter in c# class depended on the length of string passed, so if I passed a string of length 10, the StringBuilder parameter's maximum possible length would be 10. This makes it impossible for me to return larger texts, is there any workaround for this? I tried ensure capacity but that fails with an exception.

    What I'm doing now is that from c# db class I make another interop call to c++ core and copy text that way.  Since I'm not really getting any advantage from StringBuilder, I was thinking of replacing it with String parameters. Would that be a wise choice for a high-performance server application?

    Wednesday, March 4, 2009 2:18 AM

All replies

  • It isn't clear which way the string is going.  If it goes from unmanaged to managed, you have to use a StringBuilder.  Initialize it properly by setting its Capacity property so it has a large enough buffer to receive the unmanaged string.  From managed to unmanaged, you should use a regular string.
    Hans Passant.
    Wednesday, March 4, 2009 3:25 AM
  • Yes, the string is going from C++ to c#. I am properly allocating 256 character WCHAR buffer on heap before passing to the c# method. As of your second point, I have no idea how to do that because it's a function parameter and Capacity is a property?

    Anyway, here is the C# function definition

    public delegate Int32 OnDbQuery(Int32 QueryType, [MarshalAs(UnmanagedType.LPWStr, SizeConst = 256)] StringBuilder szData, ref Int64 nData);

    It's a pretty simple call and I've even set the SizeConst attribute to 256, shouldn't that do the trick? How can I specify capacity?

    Wednesday, March 4, 2009 3:30 AM
  • You are using a delegate.  That sounds like a callback from C++ to C#.  Does the C# code fill in the string buffer?  Or does it consume the string?  
    Hans Passant.
    Wednesday, March 4, 2009 11:15 AM
  • Yes, it is a callback from c++ to C#. I can see the buffer in c# but its capacity is limited to the length of the string - the one that I set in c++. Despite the fact that I'm providing a 256 character array, I'm also specifying SizeConst = 256 in MarshalAs???
    Wednesday, March 4, 2009 11:19 AM
  • Please answer my question in full.
    Hans Passant.
    Wednesday, March 4, 2009 11:22 AM
  • It does both, for some queries the C# code just consumes the buffer. For other, it first uses the string and then updates it. The problem I'm having is when the new string is longer than original string, in that case only the length of the string equal to the original string gets copied.

    I tried EnsureCapacity but that raises an exception.

    I have also tried setting [in, out] attribute explicitly and that hasn't helped at all either.

    Can you please answer my memory fragmentation & performance question wrt to StringBuilder vs String?

    Wednesday, March 4, 2009 11:27 AM
    nobugz said:

    Please answer my question in full.

    Hans Passant.

    so? anyone else?
    Thursday, March 5, 2009 2:52 PM