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.
  • G Offline
    G Offline
    goldenrose9
    wrote on last edited by
    #1

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

    L CPalliniC S 4 Replies 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 ::

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

      I'm no expert, but I do not think you can call a C++ function directly like this, and expect a String to be returned. I would suggest posting your question in the Visual Basic forum, as someone there will probably know the answer.

      Just say 'NO' to evaluated arguments for diadic functions! Ash

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

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

        The hello string is a local variable within the DisplayInfo() function; so when you return, the memory is freed. You return a pointer to the string, but the string's memory got overwritten. To fix this this particular problem, you could make hello a static variable; this will keep its address valid after returning. Another, more generally usable way would be to pass a string variable to DisplayInfo() and copy hello's content to it inside the function.

        CPalliniC 1 Reply Last reply
        0
        • L Lost User

          The hello string is a local variable within the DisplayInfo() function; so when you return, the memory is freed. You return a pointer to the string, but the string's memory got overwritten. To fix this this particular problem, you could make hello a static variable; this will keep its address valid after returning. Another, more generally usable way would be to pass a string variable to DisplayInfo() and copy hello's content to it inside the function.

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

          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]

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

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

            It looks like VB6, isn't it? As far as I know the Visual Basic Runtime takes for granted that DLLs' functions use ANSI strings and takes care about the conversions, hence you have to use char* instead of wchar_t* inside your DisplayInfo function. BTW have a look, for instance, at the following tutorial http://www.programmers-corner.com/tutorial/4[^]. [update] Please note you mustn't return the string that way, you should instead modify the passed buffer, see this MSDN article[^]. [/update] :)

            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]

            modified on Sunday, January 2, 2011 12:33 PM

            In testa che avete, signor di Ceprano?

            S 1 Reply Last reply
            0
            • CPalliniC CPallini

              It looks like VB6, isn't it? As far as I know the Visual Basic Runtime takes for granted that DLLs' functions use ANSI strings and takes care about the conversions, hence you have to use char* instead of wchar_t* inside your DisplayInfo function. BTW have a look, for instance, at the following tutorial http://www.programmers-corner.com/tutorial/4[^]. [update] Please note you mustn't return the string that way, you should instead modify the passed buffer, see this MSDN article[^]. [/update] :)

              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]

              modified on Sunday, January 2, 2011 12:33 PM

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

              As far as I know, the VB6 strings are unicode and their VC correspondant is the BSTR type...

              CPalliniC 1 Reply Last reply
              0
              • S Sauro Viti

                As far as I know, the VB6 strings are unicode and their VC correspondant is the BSTR type...

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

                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]

                In testa che avete, signor di Ceprano?

                S 1 Reply Last reply
                0
                • 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