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 / C++ / MFC
  4. LPCWSTR Problem.?

LPCWSTR Problem.?

Scheduled Pinned Locked Moved C / C++ / MFC
helpc++visual-studioquestion
17 Posts 5 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.
  • CPalliniC CPallini

    Sauro Viti wrote:

    As far as I know, the VB6 strings are unicode

    Yes, that's the reason I was talking about 'conversion'.

    Sauro Viti wrote:

    and their VC correspondant is the BSTR type...

    That holds for VB6 interacting with C++ COM components, however for standard C++ DLLs the scenario is a bit different (according to MSDN[^]):

    In order to develop your C DLL, it is important to know how Visual Basic handles strings internally in order to know how they will be passed to your DLL functions. Most C functions expect a string to be a null-terminated, ASCII character array. But Visual Basic uses a type-safe Automation string called a BSTR. For the Win32 platform, a BSTR is a long pointer to an allocated memory structure containing a Unicode character string and a 32- bit integer prefix that stores the length of the string. You can ignored most of this difference, because Visual Basic will automatically convert any Unicode BSTRs to ASCII before passing them to an external function.

    BTW: Note the typo in 'ignored'... :-D

    If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
    This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
    [My articles]

    S Offline
    S Offline
    Sauro Viti
    wrote on last edited by
    #8

    CPallini wrote:

    You can ignored most of this difference, because Visual Basic will automatically convert any Unicode BSTRs to ASCII before passing them to an external function.

    This will mean that VB pass strings to DLLs as ANSI, but what's about the opposite: what VB does with strings returned by a DLL function call?

    CPalliniC 1 Reply Last reply
    0
    • S Sauro Viti

      CPallini wrote:

      You can ignored most of this difference, because Visual Basic will automatically convert any Unicode BSTRs to ASCII before passing them to an external function.

      This will mean that VB pass strings to DLLs as ANSI, but what's about the opposite: what VB does with strings returned by a DLL function call?

      CPalliniC Offline
      CPalliniC Offline
      CPallini
      wrote on last edited by
      #9

      Of course VB6 takes care of performing the opposite conversion (you know, that language was highly engineered... :rolleyes: ). However that doesn't happen on the function return value but on passed parameter (I need to update the reply to the OP). From the same MSDN article (did you read it?):

        void \_\_stdcall FillString(LPSTR pszString, LONG cSize)
        {
           // Create a temp buffer with our string
           char buffer\[\] = "Hello from the C DLL!";
      
           // Copy our temp string to pszString
           // but check the size to make sure we have a buffer
           // big enough to hold the entire string.
           if (cSize > strlen(buffer))
              strcpy(pszString, buffer);
        }
      

      :)

      If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
      This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
      [My articles]

      In testa che avete, signor di Ceprano?

      G 1 Reply Last reply
      0
      • CPalliniC CPallini

        Of course VB6 takes care of performing the opposite conversion (you know, that language was highly engineered... :rolleyes: ). However that doesn't happen on the function return value but on passed parameter (I need to update the reply to the OP). From the same MSDN article (did you read it?):

          void \_\_stdcall FillString(LPSTR pszString, LONG cSize)
          {
             // Create a temp buffer with our string
             char buffer\[\] = "Hello from the C DLL!";
        
             // Copy our temp string to pszString
             // but check the size to make sure we have a buffer
             // big enough to hold the entire string.
             if (cSize > strlen(buffer))
                strcpy(pszString, buffer);
          }
        

        :)

        If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
        This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
        [My articles]

        G Offline
        G Offline
        goldenrose9
        wrote on last edited by
        #10

        thanx. but if i want to change this function for unicode what changes have to be done, so this function supports unicode.

        gold

        CPalliniC 1 Reply Last reply
        0
        • G goldenrose9

          thanx. but if i want to change this function for unicode what changes have to be done, so this function supports unicode.

          gold

          CPalliniC Offline
          CPalliniC Offline
          CPallini
          wrote on last edited by
          #11

          I suppose you should make a COM component. :)

          If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
          This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
          [My articles]

          In testa che avete, signor di Ceprano?

          1 Reply Last reply
          0
          • CPalliniC CPallini

            Actually, in this particular case, the local variable points to a string literal that is, of course, not freed. :)

            If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
            This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
            [My articles]

            S Offline
            S Offline
            Stefan_Lang
            wrote on last edited by
            #12

            I wouldn't be too sure about that. The variable hello is not declared const, so it would be valid to modify the content of this string later in the code like this:

            hello[3]=0;

            This means the compiler does have to create a local string variable on the stack, inside this function. And this particular string variable will indeed be destroyed upon return. You might argue that there is no such modification, but since the function itself passes a (non-const) pointer to this string, the caller might modify the contents instead! Also, later calls to that function need to initialize hello with the original string, not an address to a presumed literal which in the meantime might have been changed to god knows what. So what you'll want to pass is a copy of the literal being used for intialization, not the address of the literal itself!

            CPalliniC 1 Reply Last reply
            0
            • S Stefan_Lang

              I wouldn't be too sure about that. The variable hello is not declared const, so it would be valid to modify the content of this string later in the code like this:

              hello[3]=0;

              This means the compiler does have to create a local string variable on the stack, inside this function. And this particular string variable will indeed be destroyed upon return. You might argue that there is no such modification, but since the function itself passes a (non-const) pointer to this string, the caller might modify the contents instead! Also, later calls to that function need to initialize hello with the original string, not an address to a presumed literal which in the meantime might have been changed to god knows what. So what you'll want to pass is a copy of the literal being used for intialization, not the address of the literal itself!

              CPalliniC Offline
              CPalliniC Offline
              CPallini
              wrote on last edited by
              #13

              Stefan63 wrote:

              This means the compiler does have to create a local string variable on the stack, inside this function. And this particular string variable will indeed be destroyed upon return.

              You are wrong, at least on Microsoft compiler, these strings have static storage duration, see http://msdn.microsoft.com/en-us/library/0h227906.aspx[^]. :)

              If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
              This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
              [My articles]

              In testa che avete, signor di Ceprano?

              S 1 Reply Last reply
              0
              • G goldenrose9

                Hi to everybody, I am creating a native win32 dll with the following function.

                LPCWSTR __stdcall DisplayInfo()
                {
                wchar_t* hello =_T("Yahoooooooooo!");
                return (LPWSTR)hello;
                }

                Program compiles successfully. But when i use it in my visual basic application, the entire IDE crashes.

                Private Declare Function DisplayInfo Lib "dllexample1" () As String

                Private Sub Command1_Click()
                MsgBox DisplayInfo
                End Sub

                Help?????:confused:

                :: Roses ::

                S Offline
                S Offline
                Stefan_Lang
                wrote on last edited by
                #14

                The problem you try to solve is passing a string to a caller, where the caller has no knowledge of the length of that string, and therefore cannot easily provide a buffer variable to store that string into. The posted solution does not work, because the compiler will create a local copy of the string literal you used for initialization, and the address to that copy will be invalidated upon return. If you used const wchar_t* instead of wchar_t*, and the appropriate const string types, it might have worked. But if you want a non-const string, then there are really only two possible ways to deal with this: 1. use a secondary function that enables the caller to inquire about the expected length of the string, and then pass a buffer of sufficient size to DisplayInfo.

                const wchar_t* HELLO = _T("Yahoooooo");
                int DisplayInfoSize()
                {
                return wcslen(HELLO);
                }
                LPCWSTR __stdcall DisplayInfo(wchar_t* hello)
                {
                return wcscpy(hello, HELLO);
                }

                2. Have DisplayInfo allocate memory on the heap to story that string.

                const wchar_t* HELLO = _T("Yahoooooo");
                LPCWSTR __stdcall DisplayInfo()
                {
                wchar_t* hello = new wchar_t*[wcslen(HELLO)+1];
                return wcscpy(hello, HELLO);
                }

                Solution 1 is awkward, but it makes sure the caller can release the allocated memory once the string is no longer needed. Solution 2 might create a memory leak, if the caller has no way to properly release the string being passed to it (which may very well be the case if it's called from VB), but it would not require a change of the interface. P.S.: Just realized that the return type on your DisplayInfo function is a const string! This means that the compiler should indeed just return a pointer to the literal as others already pointed out. I'm sorry, I got confused by the cast in your return statement (which is non-const string!) The suggestions above might still work if none of the other responses are helping.

                modified on Monday, January 10, 2011 6:34 AM

                1 Reply Last reply
                0
                • CPalliniC CPallini

                  Stefan63 wrote:

                  This means the compiler does have to create a local string variable on the stack, inside this function. And this particular string variable will indeed be destroyed upon return.

                  You are wrong, at least on Microsoft compiler, these strings have static storage duration, see http://msdn.microsoft.com/en-us/library/0h227906.aspx[^]. :)

                  If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
                  This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
                  [My articles]

                  S Offline
                  S Offline
                  Stefan_Lang
                  wrote on last edited by
                  #15

                  Duh

                  Microsoft wrote:

                  Microsoft Specific

                  You win :doh: P.S.: if a DLL uses a static variable, and gets called just once, will the variable be released after the last (and only) call, or at the end of the lifetime of the application that calls it? I'm pretty sure about a C++ app calling a C++ DLL; but not so much about another language app that might use other DLL bindings...

                  CPalliniC 1 Reply Last reply
                  0
                  • S Stefan_Lang

                    Duh

                    Microsoft wrote:

                    Microsoft Specific

                    You win :doh: P.S.: if a DLL uses a static variable, and gets called just once, will the variable be released after the last (and only) call, or at the end of the lifetime of the application that calls it? I'm pretty sure about a C++ app calling a C++ DLL; but not so much about another language app that might use other DLL bindings...

                    CPalliniC Offline
                    CPalliniC Offline
                    CPallini
                    wrote on last edited by
                    #16

                    Actually it looks a more general fact, see, for instance http://stackoverflow.com/questions/267114/scope-of-string-literals[^] (look at reported sentences of the C++ standard). Static variables are, ehm, static, in other words, must be there... :)

                    If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
                    This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
                    [My articles]

                    In testa che avete, signor di Ceprano?

                    S 1 Reply Last reply
                    0
                    • CPalliniC CPallini

                      Actually it looks a more general fact, see, for instance http://stackoverflow.com/questions/267114/scope-of-string-literals[^] (look at reported sentences of the C++ standard). Static variables are, ehm, static, in other words, must be there... :)

                      If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
                      This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
                      [My articles]

                      S Offline
                      S Offline
                      Stefan_Lang
                      wrote on last edited by
                      #17

                      Thanks for the link. My problem with the original question was that I didn't notice the 'C' part of the return type, assuming it was LPWSTR, like the cast on the return statement. Also the variable hello is not a const string pointer. At the very least the local variable used to temporarily store a pointer to the literal is a non-const pointer however, and thus should be usable for modifying the string it points to! I've tested it in Visual Studio though, and it appears that even a non-const string pointer initialized to point to a string literal may not be used to change that literal: code that tries to do this does compile without warnings, but when run causes a run-time exception. For all I know this behaviour is Microsoft Specific. Consider this example

                      char* DisplayInfo()
                      {
                      char* hello = "hello!";
                      return hello;
                      }

                      int _tmain(int argc, _TCHAR* argv[])
                      {
                      char* h = DisplayInfo();
                      if (strlen(h)>0)
                      h[0] = 0;
                      return 0;
                      }

                      When you call DisplayInfo, normally all you should care about is the function prototype, which states it returns a pointer to characters. By testing the string length you assert that the pointer is non-zero and points to an array of characters of non-zero length. it should be totally legitimate to alter individual characters within that array, as the return type was non-const. But it turns out doing so might result in a run-time error, depending on how DisplayInfo is being implemented, and based on how string literals are being treated, even when dealing with non-const string types! The link you provided mentions const string types only, and thus doesn't apply here - this is indeed compiler-specific, and might indeed just be Microsoft Specific. Regarding my PS question: I was just being overly cautious. A dynamic library will only be loaded once it's used, not neccessarily upon starting the application that uses it. So the static variables will not exist from the start. I wondered whether for similar reasons the DLLs might be discarded once they are no longer needed. But of course, that is absurd, as the application wouldn't know in advance when a DLL is being called for the last time... :-O P.S. (another one): I just noticed that the last section of the quote from the standard states

                      The C++ Standard wrote:

                      The effect of attempting to modify a string literal is undefined.

                      This implies you do in fact have a non-const string pointer. Before it says

                      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