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.
  • 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