Returning a const char * pointer from C++ to C#?
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13

Thread: Returning a const char * pointer from C++ to C#?

  1. #1
    Join Date
    Jun 2009
    Posts
    1

    Returning a const char * pointer from C++ to C#?

    I have a C++ function that I am trying to return a const char * pointer to C#. I know about interop and have other functions that return int's and those work. Can C# receive const char * pointers from C++?


    In the .dll:

    extern "C" {
    __declspec(dllexport) const char * test(int k);
    }

    In C#:

    I've tried a few things, but can't get it to compile:

    [DllImport("DLL.dll")]
    static extern (What C# type goes here?) test(int k);

    I've messed with StringBuilder also. That compiles but I can't get it to work.

    thanks,
    William

  2. #2
    Join Date
    Mar 2004
    Location
    3311'18.10"N 9645'20.28"W
    Posts
    1,808

    Re: Returning a const char * pointer from C++ to C#?

    string

  3. #3
    Join Date
    Jun 2009
    Posts
    3

    Re: Returning a const char * pointer from C++ to C#?

    Quote Originally Posted by wwuster View Post
    I have a C++ function that I am trying to return a const char * pointer to C#. I know about interop and have other functions that return int's and those work. Can C# receive const char * pointers from C++?


    In the .dll:

    extern "C" {
    __declspec(dllexport) const char * test(int k);
    }

    In C#:

    I've tried a few things, but can't get it to compile:

    [DllImport("DLL.dll")]
    static extern (What C# type goes here?) test(int k);

    I've messed with StringBuilder also. That compiles but I can't get it to work.

    thanks,
    William
    It must be IntPrt

  4. #4
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Returning a const char * pointer from C++ to C#?

    I haven't done a lot of interop, but you can always use an 'unsafe' context and simply use a char*.
    Last edited by BigEd781; June 4th, 2009 at 12:24 PM.

  5. #5
    Join Date
    Mar 2004
    Location
    3311'18.10"N 9645'20.28"W
    Posts
    1,808

    Re: Returning a const char * pointer from C++ to C#?

    char is the equiv. of a .net byte. a char in .net is the same as a ushort.

    Assuming what is being used here is a Cstring, a string object will suffice.

    Quote Originally Posted by dktundwal View Post
    It must be IntPrt
    that is not correct. strings can be marshaled to and from a char* so a string will work. you *could* use an IntPtr but why on earth would you? If you're going to be p/invoking some C function, I would think it would be more important to make the signature correct for .NET (unless what they're returning is actually a byte array).

    for things like win32 a lot of times the api's deal with handles, and in this situation it is important to maintain that (most of these api's return handles, and accept handles as their parameters). For something that is returning a char* it would be better to deserialize that to a string to be used in .NET.

  6. #6
    Join Date
    May 2007
    Posts
    1,546

    Re: Returning a const char * pointer from C++ to C#?

    you *could* use an IntPtr but why on earth would you?
    If you marshal the char* as a 'string' type, then the .NET framework will automatically call Marshal.FreeHGlobal () on the char* pointer once the .NET string has been created. If your application expects the string to *not* be freed or if it allocates/frees memory using custom functions, you cannot marshal as 'string', you must use IntPtr.

    My bible on this stuff is http://www.mono-project.com/Interop_...tive_Libraries . It has a very detailed section on strings and how to marshal them correctly.

    EDIT: Most of the time you will not have to use IntPtr, but if you start experiencing strange crashes, this could be what's causing it.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  7. #7
    Join Date
    Mar 2004
    Location
    3311'18.10"N 9645'20.28"W
    Posts
    1,808

    Re: Returning a const char * pointer from C++ to C#?

    are you absolutely sure about that? I haven't read the link you posted (and it may have examples in there), but I'd find it hard to believe that the runtime would free a const char*.

  8. #8
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Returning a const char * pointer from C++ to C#?

    If you marshal the char* as a 'string' type, then the .NET framework will automatically call Marshal.FreeHGlobal
    Actually, no it won't.

    The .NET framework has no idea what heap the memory is created on. It can either be HGLOBAL, CoAllocTaskMem or the good old 'C++' heap. Indeed since .NET dynamically loads dlls (rather than statically) it may even be using a different version of the C runtime library than .NET so may have a different C++ heap. Or it may not even be on a heap : it could be static memory e.g.

    Code:
    const char *hello = "hello";
    
    __declspec(dllexport) const char *GetHello()
    {
        return hello;
    }
    in which case it shouldn't be released.

    Good practice has always been with dlls - do not deallocate memory outside a dll which was allocated inside it. And do not deallocate memory inside a dll which was allocated outside it. If a dll allocated memory, the dll should destroy it and the same goes for the client code.

    And in answer to the question, if the const char * is a null terminated C++ string then :

    (1) Look at your dll in depends.exe. Download it (just google for depends.exe) if necessary. See the function name for test is all garbled : this is what you need to provide as the 'EntryPoint' in your DllImport call.

    (2) Your C# code should look like this

    Code:
    [DllImport("Dll.dll", EntryPoint="---- from depends.exe ----")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    static extern public string test(int k);
    Darwen.
    Last edited by darwen; June 5th, 2009 at 04:51 PM.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  9. #9
    Join Date
    May 2007
    Posts
    1,546

    Re: Returning a const char * pointer from C++ to C#?

    [QUOTE=darwen;1848946]Actually, no it won't.
    [/code]
    http://msdn.microsoft.com/en-us/libr...kz(VS.80).aspx

    You're right, it's 'CoTaskMemFree' that's called on objects marshalled as 'string', I was close

    Code:
    const char *hello = "hello";
    
    __declspec(dllexport) const char *GetHello()
    {
        return hello;
    }
    That will be freed and thus cause corruption. That's why you need to marshal as 'IntPtr' if you don't want automatic free'ing of char* pointers, or use a custom marshaller.

    EDIT: If you want to pass a managed string to native code (C# -> C or C++) then you should read the docs i've linked to make sure you do it right.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  10. #10
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Returning a const char * pointer from C++ to C#?

    That will be freed and thus cause corruption.
    Let's try that again... no it won't. See included project.

    I think you're getting mixed up between COM interop (which does indeed free BSTR and SAFEARRAY output parameters, because that's according to the COM specification) and straight PInvoke.

    Darwen.
    Attached Files Attached Files
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  11. #11
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Returning a const char * pointer from C++ to C#?

    Actually, I was wrong ! I learned something today - Mutant_fruit is quite right about the marshaling of strings

    http://social.msdn.microsoft.com/For...e-b118627b8768

    My example code demonstrates that an error is reported in debug builds in RtlFreeHeap because the default marshaler for strings attempts to deallocate the string using CoFreeTaskMem.

    However this does not cause a crash : just a debug message saying that the address is wrong for RtlFreeHeap.

    I have to say this seems to me to be very unexpected behaviour for the default marshaling of PInvoke : who CoAllocTaskMem's strings for returning through C++ method calls ? I certainly never have.

    But I stand corrected...

    My apologies

    Darwen.
    Last edited by darwen; June 9th, 2009 at 03:34 PM.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  12. #12
    Join Date
    May 2007
    Posts
    1,546

    Re: Returning a const char * pointer from C++ to C#?

    However this does not cause a crash : just a debug message saying that the address is wrong for RtlFreeHeap
    Yeah, i suppose it isn't true to say it'll cause a crash. What is true is that it'll cause undefined behaviour. Basically once you try to free that pointer, anything can happen. Things could operate fine, things could crash immediately, you could get a crash at a random point in the future when that memory is re-used.

    I have to say this seems to me to be very unexpected behaviour for the default marshaling of PInvoke
    It was actually done this way to mirror the COM behaviour. I can only assume this was to minimise subtle differences which could easily lead to a memory leak/crash.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  13. #13
    Join Date
    Feb 2007
    Location
    Lahore
    Posts
    18

    Re: Returning a const char * pointer from C++ to C#?

    you can try bye array(Byte []) in C# to receive char * from C++
    O Allah, You cause the night to pass into the day, and You cause the day
    to pass into the night; You bring forth the living from the dead, and You
    bring forth the dead from the living, and You give sustenance to whom You
    like, without measure.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center