Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Char* in C++ 6 to C# .Net [modified]

Char* in C++ 6 to C# .Net [modified]

Scheduled Pinned Locked Moved C#
csharpc++visual-studioquestion
13 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    KeithF
    wrote on last edited by
    #1

    Hi Guys, I have a DLL created in Visual Studio 6 / C++ with the following function

    MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )

    i am trying to reference it like so in c# 2005

    [DllImport("mydll.dll", CharSet = CharSet.Auto)]
    public static extern int MyMethod(ref string strA, ref string strB, ref string strC);

    Here is the debugging code i added to MyMethod but the params are garbage when presented on screen:

    MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
    int ret_val = 0;
    char cA[161] = {0};
    char cB[161] = {0};
    char cC[161] = {0};
    LPSTR buffer = NULL;
    char cMsg[161] = {0};

    buffer = (LPSTR)strA;
    strncpy( cA, buffer, 161);
    
    buffer = (LPSTR)strB;
    strncpy( cB, buffer, 161);
    
    buffer = (LPSTR)strC;
    strncpy( cC, buffer, 161);
    
    sprintf( cMsg, "Params A=%s,B=%s,C=%s", strA, strB, strC );
    MessageBox( NULL, cMsg, "Dispense", MB\_OK );
    

    the function gets called but all i see is garbage in the parameters passed in, other than a string what else can i use to pass to the Char*? Thanks In Advance

    modified on Tuesday, March 22, 2011 10:29 AM

    L K L 3 Replies Last reply
    0
    • K KeithF

      Hi Guys, I have a DLL created in Visual Studio 6 / C++ with the following function

      MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )

      i am trying to reference it like so in c# 2005

      [DllImport("mydll.dll", CharSet = CharSet.Auto)]
      public static extern int MyMethod(ref string strA, ref string strB, ref string strC);

      Here is the debugging code i added to MyMethod but the params are garbage when presented on screen:

      MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
      int ret_val = 0;
      char cA[161] = {0};
      char cB[161] = {0};
      char cC[161] = {0};
      LPSTR buffer = NULL;
      char cMsg[161] = {0};

      buffer = (LPSTR)strA;
      strncpy( cA, buffer, 161);
      
      buffer = (LPSTR)strB;
      strncpy( cB, buffer, 161);
      
      buffer = (LPSTR)strC;
      strncpy( cC, buffer, 161);
      
      sprintf( cMsg, "Params A=%s,B=%s,C=%s", strA, strB, strC );
      MessageBox( NULL, cMsg, "Dispense", MB\_OK );
      

      the function gets called but all i see is garbage in the parameters passed in, other than a string what else can i use to pass to the Char*? Thanks In Advance

      modified on Tuesday, March 22, 2011 10:29 AM

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      The default marshalling type for C# strings is Unicode (2 bytes per character) as described here[^]. You will need to modify your C++ code to handle Unicode characters, or add a front end converter from WCHAR to CHAR.

      I must get a clever new signature for 2011.

      K 1 Reply Last reply
      0
      • K KeithF

        Hi Guys, I have a DLL created in Visual Studio 6 / C++ with the following function

        MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )

        i am trying to reference it like so in c# 2005

        [DllImport("mydll.dll", CharSet = CharSet.Auto)]
        public static extern int MyMethod(ref string strA, ref string strB, ref string strC);

        Here is the debugging code i added to MyMethod but the params are garbage when presented on screen:

        MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
        int ret_val = 0;
        char cA[161] = {0};
        char cB[161] = {0};
        char cC[161] = {0};
        LPSTR buffer = NULL;
        char cMsg[161] = {0};

        buffer = (LPSTR)strA;
        strncpy( cA, buffer, 161);
        
        buffer = (LPSTR)strB;
        strncpy( cB, buffer, 161);
        
        buffer = (LPSTR)strC;
        strncpy( cC, buffer, 161);
        
        sprintf( cMsg, "Params A=%s,B=%s,C=%s", strA, strB, strC );
        MessageBox( NULL, cMsg, "Dispense", MB\_OK );
        

        the function gets called but all i see is garbage in the parameters passed in, other than a string what else can i use to pass to the Char*? Thanks In Advance

        modified on Tuesday, March 22, 2011 10:29 AM

        K Offline
        K Offline
        KeithF
        wrote on last edited by
        #3

        Just an update on this, I found that if i do the following in C#

        [DllImport("mydll.dll", CharSet = CharSet.Auto)]
        public static extern int MyMethod(
        [param: MarshalAs(UnmanagedType.VBByRefStr)]
        ref string strA,
        [param: MarshalAs(UnmanagedType.VBByRefStr)]
        ref string strB,
        [param: MarshalAs(UnmanagedType.VBByRefStr)]
        ref string strC);

        That my messagebox in MyMethod in the dll shows the first character of the strings eg passing 1, 234, 5 the results are A=1,B=2,C=5

        L I 2 Replies Last reply
        0
        • L Lost User

          The default marshalling type for C# strings is Unicode (2 bytes per character) as described here[^]. You will need to modify your C++ code to handle Unicode characters, or add a front end converter from WCHAR to CHAR.

          I must get a clever new signature for 2011.

          K Offline
          K Offline
          KeithF
          wrote on last edited by
          #4

          Thanks Richard, I cant modify the dll as its from a third party and they just sent me on a samepl of the code they use how would I go about adding a front end converter from WCHAR to CHAR? Thanks In Advance

          L 1 Reply Last reply
          0
          • K KeithF

            Thanks Richard, I cant modify the dll as its from a third party and they just sent me on a samepl of the code they use how would I go about adding a front end converter from WCHAR to CHAR? Thanks In Advance

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            Just write your own C/C++ function that interfaces to the C# code and takes the three strings and converts them from Unicode to char using the WideCharToMultiByte()[^] function. You can then pass the converted strings to the DLL routines.

            I must get a clever new signature for 2011.

            1 Reply Last reply
            0
            • K KeithF

              Just an update on this, I found that if i do the following in C#

              [DllImport("mydll.dll", CharSet = CharSet.Auto)]
              public static extern int MyMethod(
              [param: MarshalAs(UnmanagedType.VBByRefStr)]
              ref string strA,
              [param: MarshalAs(UnmanagedType.VBByRefStr)]
              ref string strB,
              [param: MarshalAs(UnmanagedType.VBByRefStr)]
              ref string strC);

              That my messagebox in MyMethod in the dll shows the first character of the strings eg passing 1, 234, 5 the results are A=1,B=2,C=5

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #6

              That sounds about right as the Unicode characters for these values are the same as ANSI. However, because the Unicode are 2-byte characters, and the second byte in these cases will be zero, you effectively see a 1 character string in each parameter.

              I must get a clever new signature for 2011.

              K 1 Reply Last reply
              0
              • L Lost User

                That sounds about right as the Unicode characters for these values are the same as ANSI. However, because the Unicode are 2-byte characters, and the second byte in these cases will be zero, you effectively see a 1 character string in each parameter.

                I must get a clever new signature for 2011.

                K Offline
                K Offline
                KeithF
                wrote on last edited by
                #7

                Hi Richard, Thanks for all the help. After playing around with a few other things i found that this works

                [DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
                public static extern int MyMethod(
                [param: MarshalAs(UnmanagedType.LPStr)]
                StringBuilder strA,
                [param: MarshalAs(UnmanagedType.LPStr)]
                StringBuilder strB,
                [param: MarshalAs(UnmanagedType.LPStr)]
                StringBuilder strC);

                changeg need were to remove the ref keyword, changes string to stringbuilder and the unmanaged type to LPStr

                L 1 Reply Last reply
                0
                • K KeithF

                  Just an update on this, I found that if i do the following in C#

                  [DllImport("mydll.dll", CharSet = CharSet.Auto)]
                  public static extern int MyMethod(
                  [param: MarshalAs(UnmanagedType.VBByRefStr)]
                  ref string strA,
                  [param: MarshalAs(UnmanagedType.VBByRefStr)]
                  ref string strB,
                  [param: MarshalAs(UnmanagedType.VBByRefStr)]
                  ref string strC);

                  That my messagebox in MyMethod in the dll shows the first character of the strings eg passing 1, 234, 5 the results are A=1,B=2,C=5

                  I Offline
                  I Offline
                  Ian Shlasko
                  wrote on last edited by
                  #8

                  I'm no expert on C++ interfacing, so I'd defer to Richard on this, but I think marshaling as UnmanagedType.LPStr might take care of this. According to the MSDN docs, that'd send them through as single-byte, null-terminated strings. Would eliminate the need to convert from Unicode. EDIT: Never mind, looks like you already figured this out :)

                  Proud to have finally moved to the A-Ark. Which one are you in?
                  Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                  1 Reply Last reply
                  0
                  • K KeithF

                    Hi Guys, I have a DLL created in Visual Studio 6 / C++ with the following function

                    MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )

                    i am trying to reference it like so in c# 2005

                    [DllImport("mydll.dll", CharSet = CharSet.Auto)]
                    public static extern int MyMethod(ref string strA, ref string strB, ref string strC);

                    Here is the debugging code i added to MyMethod but the params are garbage when presented on screen:

                    MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
                    int ret_val = 0;
                    char cA[161] = {0};
                    char cB[161] = {0};
                    char cC[161] = {0};
                    LPSTR buffer = NULL;
                    char cMsg[161] = {0};

                    buffer = (LPSTR)strA;
                    strncpy( cA, buffer, 161);
                    
                    buffer = (LPSTR)strB;
                    strncpy( cB, buffer, 161);
                    
                    buffer = (LPSTR)strC;
                    strncpy( cC, buffer, 161);
                    
                    sprintf( cMsg, "Params A=%s,B=%s,C=%s", strA, strB, strC );
                    MessageBox( NULL, cMsg, "Dispense", MB\_OK );
                    

                    the function gets called but all i see is garbage in the parameters passed in, other than a string what else can i use to pass to the Char*? Thanks In Advance

                    modified on Tuesday, March 22, 2011 10:29 AM

                    L Offline
                    L Offline
                    Luc Pattyn
                    wrote on last edited by
                    #9

                    Some of the replies you got contain too much attributes IMO. Passing strings between C# and native code is pretty easy, you don't even need all those Marshal thingies, a simple CharSet = CharSet.Unicode [ADDED] or CharSet = CharSet.ASCII [ADDED] in your DllImport should do it. You must get rid of the ref keywords obviously, as a string is always passed as a pointer anyway. And if one or more of those strings are meant to be output parameters, the easiest way is by using a StringBuilder. I think I covered all these essentials in this article[^]. :)

                    Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum

                    Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.

                    modified on Tuesday, March 22, 2011 12:32 PM

                    K 1 Reply Last reply
                    0
                    • L Luc Pattyn

                      Some of the replies you got contain too much attributes IMO. Passing strings between C# and native code is pretty easy, you don't even need all those Marshal thingies, a simple CharSet = CharSet.Unicode [ADDED] or CharSet = CharSet.ASCII [ADDED] in your DllImport should do it. You must get rid of the ref keywords obviously, as a string is always passed as a pointer anyway. And if one or more of those strings are meant to be output parameters, the easiest way is by using a StringBuilder. I think I covered all these essentials in this article[^]. :)

                      Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum

                      Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.

                      modified on Tuesday, March 22, 2011 12:32 PM

                      K Offline
                      K Offline
                      KeithF
                      wrote on last edited by
                      #10

                      Hi Luc, I tried what you said as well but I only get see the first character in the C++ method, here is the code:

                      [DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
                      public static extern int MyMethod(
                      string strA,
                      string strB,
                      string strC);

                      I took out the

                      [param: MarshalAs(UnmanagedType.LPStr)]

                      but it seems that this is needed

                      L 1 Reply Last reply
                      0
                      • K KeithF

                        Hi Luc, I tried what you said as well but I only get see the first character in the C++ method, here is the code:

                        [DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
                        public static extern int MyMethod(
                        string strA,
                        string strB,
                        string strC);

                        I took out the

                        [param: MarshalAs(UnmanagedType.LPStr)]

                        but it seems that this is needed

                        L Offline
                        L Offline
                        Luc Pattyn
                        wrote on last edited by
                        #11

                        sorry, my mistake, if your native code wants ASCII, just say CharSet.ASCII. There is automatic marshaling that will allocate and later free buffers, translate the strings and everything for you. Warning: you are not allowed to remember those string pointers (actually any pointer unless the object remains pinned) and use them after the function return! :)

                        Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum

                        Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.

                        K 1 Reply Last reply
                        0
                        • L Luc Pattyn

                          sorry, my mistake, if your native code wants ASCII, just say CharSet.ASCII. There is automatic marshaling that will allocate and later free buffers, translate the strings and everything for you. Warning: you are not allowed to remember those string pointers (actually any pointer unless the object remains pinned) and use them after the function return! :)

                          Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum

                          Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.

                          K Offline
                          K Offline
                          KeithF
                          wrote on last edited by
                          #12

                          Hi Luc, Thanks that works perfectly, you learn something new every day ;)

                          1 Reply Last reply
                          0
                          • K KeithF

                            Hi Richard, Thanks for all the help. After playing around with a few other things i found that this works

                            [DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
                            public static extern int MyMethod(
                            [param: MarshalAs(UnmanagedType.LPStr)]
                            StringBuilder strA,
                            [param: MarshalAs(UnmanagedType.LPStr)]
                            StringBuilder strB,
                            [param: MarshalAs(UnmanagedType.LPStr)]
                            StringBuilder strC);

                            changeg need were to remove the ref keyword, changes string to stringbuilder and the unmanaged type to LPStr

                            L Offline
                            L Offline
                            Lost User
                            wrote on last edited by
                            #13

                            Great stuff. I see that you also got some help from Ian, and Luc who knows far more about this than I do.

                            I must get a clever new signature for 2011.

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • World
                            • Users
                            • Groups