C# application crashes after I get a string from a C++ dll

Answered C# application crashes after I get a string from a C++ dll

  • Friday, March 16, 2012 2:59 AM
     
     

    Hi there,

    I try to get a string from my C++ dll in C# application.

    My code snippet is below:

    ===== C++ dll =====

    __declspec(dllexport) void GetSzString(char** pszString, size_t nLength)
    {
        if(*pszString == NULL) {
            return;
        }

        strcpy_s(*pszString, nLength, "Hello,World");
    }

    ===== C# App =====

    class Program

        [DllImport("CppDll.dll")]
        public static extern void GetSzString(ref string rStr, int length);

        static void Main(string[] args)
        {
            string myStr = "";
            GetSzString(ref myStr, 128);
            Console.WriteLine("The string is {0}", myStr);

            Console.Read();
        }
    }

    I get the string "Hello,World" successfully. it shows on my console window.

    However, my C# application crashes when it is closing.

    What's wrong with my code.

    What's the correct way to get a string from a C++ dll.

All Replies

  • Friday, March 16, 2012 4:31 AM
     
     

    I think .NET is trying to free memory that it doesn't own, and already freed when doing execution environment tear down.

    Try change the import signiture to use StringBuilder instead of ref string, the C# compiler has hardcoded to make necessary changes to the call when it sees StringBuilder as parameter.



  • Friday, March 16, 2012 5:02 AM
     
      Has Code

    You can try using the attribute MarshalAs

        [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]

    http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute.aspx

    If allowed please upload the dll so we can try it out here:


    Resolving n Evolving in C# (http://jeanpaulva.com)


  • Friday, March 16, 2012 6:14 AM
     
     Answered

    Hi Cheong,

    I modify my C# code

    ===== C# application =====

    [DllImport("CppExDll.dll")]
    public static extern void GetSzString(StringBuilder sb, int length);

    static void Main(string[] args)
    {
        StringBuilder mySB = new StringBuilder(128);
        GetSzString(mySB, 128);
        Console.WriteLine("The string is {0}", mySB);

        Console.Read();
    }

    It gets a empty string, the "Hello,World" doesn't show on my console window.

    But, there is no crash when app is closing.

    Then, I modify my code again (use ref StringBuilder instead)

    ===== C# application =====

    [DllImport("CppExDll.dll")]
    public static extern void GetSzString(ref StringBuilder sb, int length);

    static void Main(string[] args)
    {
        StringBuilder mySB = new StringBuilder(128);
        GetSzString(ref mySB, 128);
        Console.WriteLine("The string is {0}", mySB);

        Console.Read();
    }

    It works. I get the "Hello,World" successfully and there is no crash when app is closing.

    I think that it might be a correct way to get a string from C++ dll.

    Thanks

  • Friday, March 16, 2012 6:24 AM
     
     

    Hi Jean,

    I use the attribute MarshalAs, and I get a strange string.

    (Because the UnmanagedType.LPWStr is used?)

    ===== C# application =====

    [DllImport("CppExDll.dll")]
    public static extern void GetSzString(
        [MarshalAsAttribute(UnmanagedType.LPWStr)]
        ref string rStr, 
        int length);

    static void Main(string[] args)
    {
        StringBuilder mySB = new StringBuilder(128);
        GetSzString(ref mySB, 128);
        Console.WriteLine("The string is {0}", mySB);

        Console.Read();
    }

    And my app still crash.

    By the way, I don't know how to upload my dll.

    Thanks.

  • Friday, March 16, 2012 6:32 AM
     
     

    Hello Lee,

    You can upload the file to rapidshare/skydrive/web servers and provide the link.

    But as of now you got the problem solved, I think it is not needed.


    Resolving n Evolving in C# (http://jeanpaulva.com)

  • Friday, March 16, 2012 8:46 AM
     
     
    You pass ref StringBuilder since the function expects a char**. Passing StringBuilder without the ref keyword would pass a char* only.
  • Friday, March 16, 2012 9:07 AM
     
     
    True. You would need to set the CharSet of the DllImport attribute. It doesn't matter anyway, since the OP is using char**.
  • Friday, March 16, 2012 10:14 AM
     
     
    You're right. I've overlooked the char** here. (Not seeing your reply before decided to delete the post)