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