none
unresolved external symbol _wfopen RRS feed

  • Question

  • Please treat me as an absolute beginner in VS Express 2013, and also pretty raw at C programming! :-)

    I'm writing a program to read a UTF-8 .txt file containing Win7 filenames containing UTF-8 characters (accented foreign characters, for example).  I then wish to do some processing on those names and write them back out to a UTF-8 batch file to run in a DOS window.

    Here are a few pertinent extracts from my .C file:

    #include <stdio.h>
    #include <stddef.h>
    #include <stdlib.h>
    #include <wchar.h>
    #include <string.h>
    #include <ctype.h>
    #include <io.h>
    #include <errno.h>
    #include <process.h>
    
    #define UNICODE						// don't know if these actually achieve anything, but
    #define _UNICODE					// eventually I want the code to be UTF-8 compliant
    
    .....
    
    void
    main(sShort_16 argCount, sChar_8 *argValue[])
    {
    .....
    
    	if ((listIn = _wfopen(ucOldNames, L"rt+, ccs=UTF-8")) == NULL)
    	{	// no file list
    		puts("\nCan't open file list!");
    		exit(1);
    	}
    

    My problem is that compiling my program from a Developer Command Prompt for VS2013, using

    cl makexxx.c

    throws up this error (as well as a number of warnings):

    unresolved external symbol _wfopen

    My understanding is that _wfopen is an available function in VS Express 2013.  So why do I get this error, and how do I avoid it?

    Thursday, May 23, 2019 5:47 AM

Answers

  • OK, a number of good points made there, all noted.  And Darren, yes I'm using Visual Studio 2013 Express for Windows Desktop.

    However, my problem is now solved.  I made a few changes following Tim's advice, including changing the first _wfopen back to a fopen.  But I still needed a second _wfopen as I was creating files whose filenames could contain Unicode characters.  At the same time, I thought it wise to change the encoding of my .C source file to UTF-8 (no BOM).

    And when I next tried compiling/linking (with cl), I no longer received an error about _wfopen not being found!  I still received several warnings about mismatched types, but after working through those one-by-one, I finally was able to compile/link with no warnings and no errors.  So that particular program is now running correctly, as I want it.

    So I thought I would now turn my new-found Unicode-handling knowledge to another old C program I wrote long ago (these date from when I used Quick-C on a 16-bit Windows machine – I only changed to VS when I migrated to a 64-bit Windows, and needed to recompile all  my old programs for 32-bit 'DOS').  So I made similar changes to that other program, which performs a similar (but slightly different) task, and eventually got it also to compile/link without warnings or errors.  But when it ran, it crashed and Windows popped up the usual dialogue asking me to close it.

    Thinking, with my limited knowledge, it would take ages for me to find and fix the cause, I went back to my previous (pre-Unicode) version (since I had an immediate need to use it), but before recompiling it, I changed its file to UTF-8 encoding too.  And to my astonishment, after recompiling/linking, that old (otherwise unchanged) code, I found if I ran it after changing the codepage with chcp 65001 (in the Windows Console – thanks Wayne!), it would read-in filenames including Unicode characters (from a directory listing redirected to a text file), and write them out to another text file still including those Unicode characters!   So it seems all my effort to use wide character variables and 'wide' versions of fopen, etc, were unnecessary, as I can continue to use the old standard string and open functions, and somehow it all still works with Unicode-containing filenames.

    PS: I might not check this page much more now, as this site won't send me alerts to new posts.  I requested them, and it asked again for my e-mail address (why? – I already registered [months ago] with an eddress) and then sent me a validation e-mail.  But clicking on that link takes me to a page saying "Forums Home> Internal Server Error

    Sorry, we were unable to service your request. Please try again later."   I've tried several times over a few days, always receiving that same message.  (Perhaps it's Micro$oft's hatred for Google, so they block gmail eddresses?)  So I can't validate my eddress and thus don't receive alerts. :-(

    • Marked as answer by DanielFFF Thursday, May 30, 2019 7:16 AM
    Saturday, May 25, 2019 11:21 AM

All replies

  • Hi DanielFFF,

    Welcome to the MSDN forum.

    According to the description, this issue is about the C/C++ development and our forum is to discuss the VS IDE, I will help you move this thread to the appropriate forum for better support, thanks for your understanding.

    Best regards,

    Sara


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com

    Thursday, May 23, 2019 8:58 AM
  • Hello,

    you don't have to #define UNICODE in your source Code.

    You must set the project settings in VS instead. Then the linker knows which libraries to use.

    Go to menu Project -> Project Settings. In Projectstandards set the key set to UNICODE. (I think it is still set to MBCS, multi-byte character set)

    Regards, Guido

    Thursday, May 23, 2019 9:04 AM
  • I installed Visual Studio 2013 Express for Windows Desktop and checked the both libcmt.lib and msvcrt.lib, and _wfopen was available in both. I was also able to build a small application that referenced this function on the command line.

    So are you using Visual Studio 2013 Express for Windows Desktop?

    Also, if you run Visual Studio itself and create a project using the Win32 Console Application template, do you get the same error?


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Thursday, May 23, 2019 2:19 PM
  • Please treat me as an absolute beginner in VS Express 2013, and also pretty raw at C programming! :-)


    void
    main(sShort_16 argCount, sChar_8 *argValue[])
    

    Why are you ignoring the standard definition of main?  While this may work on your little-endian machine, you have lost any hope of portability:

         1 - main() returns an int.
         2 - the first argument has type int.
         3 - the second argument is a pointer to an array of pointers to char (not signed char, not unsigned char, just char).

    As an absolute beginner, you would be much better off sticking to the standard features of the language.


    Thursday, May 23, 2019 4:42 PM
  • When you say "UTF-8 compliant", you need to be specific about what you mean.  By defining UNICODE, your code will be working with UTF-16, not UTF-8.  That might be OK, because the stdio file routines will translate from UTF-8 files into UTF-16 strings in your code when you use the "ccs=" flag.

    It is not necessary to use _wfopen for that.  The only difference between _wfopen and fopen is that _wfopen expects its parameters to be wchar_t strings instead of char strings.  It doesn't have any bearing on how the text is translated.  So, this works fine for me:

    #define UNICODE
    #define _UNICODE
    
    #include <stdio.h>
    #include <stddef.h>
    #include <stdlib.h>
    #include <wchar.h>
    #include <string.h>
    
    int main( int argc, char ** rrgv )
    {
        FILE * listIn = fopen("xxx.txt", "rt+, ccs=UTF-8");
        if( !listIn )
        {	// no file list
            puts("\nCan't open file list!");
            exit(1);
        }
    
        wchar_t line[80];
        fgetws( line, 80, listIn );
        fputws( line, stdout );
    }

    However, your root problem is something else.  _wfopen is part of the standard runtime library.  Are you sure you were using a Visual Studio command prompt, and not just a Command Prompt from the Start Menu?  The standard command prompt doesn't have the include and library paths you need.  You can get the paths set up by calling

        "c:\path-to-vs2013\vc\vcvarsall.bat" x64


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.


    Thursday, May 23, 2019 5:20 PM
  • According to the description, this issue is about the C/C++ development and our forum is to discuss the VS IDE, I will help you move this thread to the appropriate forum for better support, thanks for your understanding.

    Sara, I assumed from the forum description 'Visual Studio general' that it covered all aspects of VS, which would include its use from a Command prompt.  And since my problem relates specifically to VS libraries, I thought this would be a good place to start.

    But if you disagree, I'm happy to follow your advice.

    Daniel

    Friday, May 24, 2019 11:43 AM
  • You must set the project settings in VS instead. Then the linker knows which libraries to use.

    Guido, thanks for your comments.  But I have enough trouble with other IDE's I use, that I don't want to have to learn another one.  I'd much rather create simple C files (for exe output running in a DOS window) in a decent editor (e.g. Notepad++) and compile them from the VS developer command prompt.

    Daniel

    Friday, May 24, 2019 11:46 AM
  • Darran, thanks for your response, but please see my reply to Guido.

    Daniel

    Friday, May 24, 2019 11:47 AM
  • Barry, thanks for your comments.  You're right about the main() return type; I should have specified it as sShort_16.

    The type 'int' has different sizes on different machines (sometimes 16-bit, sometimes 32), so is too vague for portability.  If I want a 16-bit variable, it is better to specify it as short (the same size on all machines) rather than int.  As for 'just' char, what is it?  As far as I know it's standard description is a signed byte, so I prefer to make that clear with my typedefs.  All the types I use include their size, so there can be no misunderstanding of what type/size the variable is, unlike vague terms like 'int' and 'char' that convey little sense of their type or size.

    Daniel

    Friday, May 24, 2019 11:56 AM
  • Tim, thanks for your reply, perhaps the most useful, so far.  I'll try your suggestion and report back in due course.

    As for the Developer command prompt, this is the command executed by the shortcut I click to get the developer prompt, and I suspect (it was a long time ago) it was provided by the Visual Studio Express instructions:

    %comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd.bat""

    VsDevCmd.bat was, I presume, supplied with the VSE download, and has not been modified by me.  I don't see any button here to attach files, and pasting the batch commands into this body would be messy (139 lines of code).

    Daniel

    Friday, May 24, 2019 12:06 PM
  • Barry, thanks for your comments.  You're right about the main() return type; I should have specified it as sShort_16.

    The type 'int' has different sizes on different machines (sometimes 16-bit, sometimes 32), so is too vague for portability.  If I want a 16-bit variable, it is better to specify it as short (the same size on all machines) rather than int.  As for 'just' char, what is it?  As far as I know it's standard description is a signed byte, so I prefer to make that clear with my typedefs.  All the types I use include their size, so there can be no misunderstanding of what type/size the variable is, unlike vague terms like 'int' and 'char' that convey little sense of their type or size.

    Daniel

    1 - You are correct that the size of an int can vary on different machines.  But that is irrelevant to the point I made.  The size of the first argument passed to main is determined by the system, not by the type you code in your program.  For a compliant system, that argument will have type int regardless of what you specify.  If your code runs on a system with an int bigger than 16, you already have undefined behavior before you even start.  The same is true regarding the return value.

    2 - You know wrong.  A char is a type distinct from both signed char and unsigned char.  It will however have a representation that is the same as one of these two.

    You claim to be a beginner.  You should limit your use of typedefs to object types you can control.  For functions defined by the standard, you should use the standard types specified in the description of those functions.

    Friday, May 24, 2019 5:12 PM

  • I don't see any button here to attach files, and pasting the batch commands into this body would be messy (139 lines of code).

    The usual procedure here is to post needed files on a file sharing service and
    then to post a link to the file(s) here so we can retrieve the file(s) as and
    when desired. Microsoft Onedrive is a common choice as you can log into it
    using the same username and password as used for these forums.

    Since it appears that nobody else can replicate your error, you need to provide
    a more complete and directly usable test case that others can try. In the snippet
    that you posted you have elided lines of code. No doubt that was based on certain
    assumptions about their relevance. That may be a mistake, there may be something
    relevant in the omitted lines.

    Similarly you made reference to a "number of warnings". Again there may be 
    something relevant in those warnings that offers a clue as to the cause of
    the link error you posted. Ignoring warnings is often imprudent. We need to 
    see *all* output messages from the build.

    As to the environment variables that need to be set for the command line tools,
    you can check them directly from the command line. For example, entering

    set lib<Enter>

    should show the environment variables that begin with "lib" such as
    LIB=
    LIBPATH=

    Post the output here.

    You can also capture all environment variables to a file via redirection. e.g. -

    set > set.txt

    A word about terminology: There is no such thing as a DOS window anymore unless
    you are running a DOS emulator. Under Win32/64 what looks like a "DOS window"
    is a Windows console. This is more than just pedantry, using the correct
    terminology can avoid misunderstandings. Such as in cases where someone truly
    needs to work with DOS applications.

    - Wayne

    Friday, May 24, 2019 5:48 PM
  • While that answers why you won't create a project in the IDE, that does not answer my question about what version of Visual Studio 2013 Express you are using.

    As I quite clearly stated, I installed Visual Studio 2013 Express for Windows Desktop. I built on the command line using a source file that uses _wfopen, and it worked without issue. This is because the files msvcrt.lib, msvcrtd.lib, libcmt.lib and libcmtd.lib, which are the default libraries for the compiler depending on command line options all resolve this function.

    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib>dumpbin /exports msvcrt.lib   | find "fopen"
                      _fopen_s
                      _fopen
                      __wfopen_s
                      __wfopen
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib>dumpbin /exports msvcrtd.lib   | find "fopen"
                      _fopen_s
                      _fopen
                      __wfopen_s
                      __wfopen

    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib>dumpbin /symbols libcmt.lib   | find "fopen"
    018 00000000 SECT4  notype ()    External     | __wfopen
    019 00000000 SECT6  notype ()    External     | __wfopen_s
    018 00000000 SECT7  notype ()    External     | _fopen
    019 00000000 SECT9  notype ()    External     | _fopen_s
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib>dumpbin /symbols libcmtd.lib   | find "fopen"
    018 00000000 SECT4  notype ()    External     | __wfopen
    019 00000000 SECT6  notype ()    External     | __wfopen_s
    018 00000000 SECT7  notype ()    External     | _fopen
    019 00000000 SECT9  notype ()    External     | _fopen_s

    The extra _ is automatically added by the compiler, so they will match.

    I was asking this to make sure that you were using the correct environment in the first place.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    • Edited by Darran Rowe Saturday, May 25, 2019 10:04 AM
    Friday, May 24, 2019 10:54 PM
  • OK, a number of good points made there, all noted.  And Darren, yes I'm using Visual Studio 2013 Express for Windows Desktop.

    However, my problem is now solved.  I made a few changes following Tim's advice, including changing the first _wfopen back to a fopen.  But I still needed a second _wfopen as I was creating files whose filenames could contain Unicode characters.  At the same time, I thought it wise to change the encoding of my .C source file to UTF-8 (no BOM).

    And when I next tried compiling/linking (with cl), I no longer received an error about _wfopen not being found!  I still received several warnings about mismatched types, but after working through those one-by-one, I finally was able to compile/link with no warnings and no errors.  So that particular program is now running correctly, as I want it.

    So I thought I would now turn my new-found Unicode-handling knowledge to another old C program I wrote long ago (these date from when I used Quick-C on a 16-bit Windows machine – I only changed to VS when I migrated to a 64-bit Windows, and needed to recompile all  my old programs for 32-bit 'DOS').  So I made similar changes to that other program, which performs a similar (but slightly different) task, and eventually got it also to compile/link without warnings or errors.  But when it ran, it crashed and Windows popped up the usual dialogue asking me to close it.

    Thinking, with my limited knowledge, it would take ages for me to find and fix the cause, I went back to my previous (pre-Unicode) version (since I had an immediate need to use it), but before recompiling it, I changed its file to UTF-8 encoding too.  And to my astonishment, after recompiling/linking, that old (otherwise unchanged) code, I found if I ran it after changing the codepage with chcp 65001 (in the Windows Console – thanks Wayne!), it would read-in filenames including Unicode characters (from a directory listing redirected to a text file), and write them out to another text file still including those Unicode characters!   So it seems all my effort to use wide character variables and 'wide' versions of fopen, etc, were unnecessary, as I can continue to use the old standard string and open functions, and somehow it all still works with Unicode-containing filenames.

    PS: I might not check this page much more now, as this site won't send me alerts to new posts.  I requested them, and it asked again for my e-mail address (why? – I already registered [months ago] with an eddress) and then sent me a validation e-mail.  But clicking on that link takes me to a page saying "Forums Home> Internal Server Error

    Sorry, we were unable to service your request. Please try again later."   I've tried several times over a few days, always receiving that same message.  (Perhaps it's Micro$oft's hatred for Google, so they block gmail eddresses?)  So I can't validate my eddress and thus don't receive alerts. :-(

    • Marked as answer by DanielFFF Thursday, May 30, 2019 7:16 AM
    Saturday, May 25, 2019 11:21 AM
  • Hmm, in response to this I have to ask, are you forced to use Visual Studio 2013 Express or do you have the option to use Visual Studio 2019 or 2017 Community/Build Tools?

    One of the compiler options that they added with the newer versions of Visual Studio is the /utf-8 option which sets the source and execution character set to UTF-8. Also, if you have the option, is it possible for this development to occur on Windows 10?

    While you can use chcp 65001 on Windows, technically Windows doesn't support UTF-8 as a codepage which is what you need to make what you want to do run smoothly.

    However, either Windows 10 17134 or 17763 added this:

    This sets the codepage for Windows to UTF-8 and all of the character set translations happen automatically.

    Of course, if you can't/don't want to use Windows 10 then just remember that the chcp 65001 in a console is technically an unsupported workaround.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Saturday, May 25, 2019 2:51 PM
  • Hmm, in response to this I have to ask, are you forced to use Visual Studio 2013 Express or do you have the option to use Visual Studio 2019 or 2017 Community/Build Tools?

    One of the compiler options that they added with the newer versions of Visual Studio is the /utf-8 option which sets the source and execution character set to UTF-8. Also, if you have the option, is it possible for this development to occur on Windows 10?

    Darran, thanks for your further comments.  My adoption of VS2013 goes back to 2015 when I built this PC, installed Win7Pro64 on it, and suddenly found all my old Quick-C programs no longer ran!  Yes, I probably could use VS2019, which I recently downloaded but have not yet installed.  I'll probably give it a try next time I need to compile a program.

    Based on my observations of behaviour on my wife's PC, which was upgraded to Win10 without my knowledge, I don't wish to migrate to 10.  One of its big omissions is a virtual XP machine, which I occasionally use (in Win7) for ancient software that doesn't run in 7 or later.  And I have little faith in third-party virtual machine software.

    Tuesday, May 28, 2019 3:00 AM
  • Hi,

    I am glad you have got your solution and thanks for your sharing. 

    Have you got any updates? If your case has been solved, please help to mark answers.

    Your understanding and cooperation will be grateful.

    Best Regards,

    Jeanine Zhang

    Tuesday, May 28, 2019 5:59 AM
    Moderator
  • If you type "set lib" in that command prompt, you should see that the LIB environment variable contains a list of directories to search for its libraries.  I can't imagine that's getting messed up.

    You can try, as an experiment, adding /MT or /MD to your command line to select different runtime library options.  Are you linking with some other third-party library?  Occasionally, you'll get a library that turns off the default library search (using the linker /NODEFAULTNAME option). but I didn't see that in your text.


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Tuesday, May 28, 2019 6:51 PM