none
command line pre-processor

    Question

  • I have a DLL project and in the header file is this:

    #ifdef MYDLL_EXPORTS
    #define MYDLL_API __declspec(dllexport)
    #else
    #define MYDLL_API __declspec(dllimport)
    #endif

    When I go to my project's properties C/C++ --> Preprocessor menu, I have MYDLL_EXPORTS listed as a part of "Preprocessor Definitions" yet when I build it turns out that the functions are treated as imports.  And in VS the #define with dllexport is greyed out and the #define with dllimport is in blue.  Why is this backwards?  I can't think of anywhere else to look.  I even tried

    /D MYDLL_EXPORTS /D "MYDLL_EXPORTS"

    on the command line arguments and that didn't help either.
    Monday, April 16, 2012 11:54 PM

Answers

  • Have you opened any .cpp files with this header included in yet? One thing to remember with VS is that for header files, it can't just parse them as C++ source, to get the context for headers, it needs to be parsed in relation to a source file.

    So try opening a source file which includes this header and see if it makes a difference. If not, then you are going to have to provide code.


    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.

    Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this.

    • Proposed as answer by Helen Zhao Tuesday, April 24, 2012 7:32 AM
    • Marked as answer by Helen Zhao Wednesday, April 25, 2012 1:41 AM
    Tuesday, April 17, 2012 12:40 AM
  • Well, it is easy to tell how the code from the C++ file would influence this. Think, if you have two projects in your solution, both of these include the header file, but one of the projects is the DLL project and one of them is the executable project. MYDLL_EXPORTS is only defined for the DLL project.

    In the header file, which is included in a source file where MYDLL_EXPORTS is defined and where it isn't defined, how should Visual Studio deal with that block. If you enable the export block, then it is wrong for the executable, if it enables the import block then in is wrong for the DLL. So the reason why I mentioned the other source files is to allow Visual Studio to get the correct context for the header file.

    And before you say that your solution only has one project, look back over your previous posts and please note how you neglected to mention how many projects your solution has in it.

    Secondly, the code you could provide which would help is the contents of the DLL source files. The reason why is that there are lots of things that could go wrong. Since you mentioned that you have precompiled headers, then the perfect one that could be going wrong is that you included your DLL header before stdafx.h. By doing this, the compiler ignores everything in the headers before stdafx.h. If your header is included before stdafx.h then it would be failing to produce a library because it does not see any functions exported.

    Anyway, to answer your two points.

    1. It is produced automatically when the compiler sees at least one function exported. So you have to do nothing but mark the functions you wish to export in some way.

    2. I only really include any headers that are included into all source files with any definitions needed to get them to work correctly. As to "professional", who knows, depending on my mood and size of project I also have a habit of turning them off too. But to be honest, I have never put the definition to trigger the export of functions in a DLL in the precompiled header, that has always gone on the command line for me.


    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.

    Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this.

    • Proposed as answer by Helen Zhao Tuesday, April 24, 2012 7:33 AM
    • Marked as answer by Helen Zhao Wednesday, April 25, 2012 1:41 AM
    Tuesday, April 17, 2012 3:32 PM
  • Right, have you modified the function prototypes to include this?

    For the functions to be exported, they must be marked as export. The way to do this is to put the MYDLL_API on the functions that you want to export. So if, in this header, you have a function that you want to export.

    void MyFun();

    To make it actually export, you must put MYDLL_API on the function prototype.

    MYDLL_API void MyFun();

    For an example from an actual sample DLL that builds, and produces a .lib file.

    Header file:

    #ifndef MYHEADER_H
    #define MYHEADER_H
    
    #ifdef MYEXPORTS
    #define MYAPI __declspec(dllexport)
    #else
    #define MYAPI __declspec(dllimport)
    #endif
    
    extern"C"
    {
    MYAPI void MyFunc();
    }
    
    #endif

    Source file:

    #include "myheader.h"
    
    extern"C"
    void MyFunc()
    {
    }

    Notice the MYAPI on the forward decleration of MyFunc in the header but not on the definition of MyFunc in the source. For all configurations of the project, in the preprocessor definitions, MYEXPORTS is defined. The output for the compiler is:

    1>------ Build started: Project: testdll, Configuration: Debug Win32 ------
    1>Build started 17/04/2012 17:19:37.
    1>PrepareForBuild:
    1>  Creating directory "d:\testdll\Debug\".
    1>InitializeBuildStatus:
    1>  Creating "Debug\testdll.unsuccessfulbuild" because "AlwaysCreate" was specified.
    1>ClCompile:
    1>  main.cpp
    1>Link:
    1>     Creating library d:\testdll\Debug\testdll.lib and object d:\testdll\Debug\testdll.exp
    1>LinkEmbedManifest:
    1>     Creating library d:\testdll\Debug\testdll.lib and object d:\testdll\Debug\testdll.exp
    1>  testdll.vcxproj -> d:\testdll\Debug\testdll.dll
    1>FinalizeBuildStatus:
    1>  Deleting file "Debug\testdll.unsuccessfulbuild".
    1>  Touching "Debug\testdll.lastbuildstate".
    1>
    1>Build succeeded.
    1>
    1>Time Elapsed 00:00:01.85
    ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

    So this works. Please note, the __declspec(dllexport) only has to be on the function prototype in the header, but besides that, the calling convention and the name mangling (extern"C") must match.


    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.

    Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this.


    • Edited by Crescens2k Tuesday, April 17, 2012 4:25 PM
    • Proposed as answer by Helen Zhao Tuesday, April 24, 2012 7:34 AM
    • Marked as answer by Helen Zhao Wednesday, April 25, 2012 1:41 AM
    Tuesday, April 17, 2012 4:23 PM

All replies

  • Have you opened any .cpp files with this header included in yet? One thing to remember with VS is that for header files, it can't just parse them as C++ source, to get the context for headers, it needs to be parsed in relation to a source file.

    So try opening a source file which includes this header and see if it makes a difference. If not, then you are going to have to provide code.


    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.

    Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this.

    • Proposed as answer by Helen Zhao Tuesday, April 24, 2012 7:32 AM
    • Marked as answer by Helen Zhao Wednesday, April 25, 2012 1:41 AM
    Tuesday, April 17, 2012 12:40 AM
  • There is a chance that you've defined the pre-processor definition for the wrong configuration.

    I mean, you define this for a Debug build and then do a release build for which it is not defined.


    «_Superman_»
    Microsoft MVP (Visual C++)

    Polymorphism in C

    Tuesday, April 17, 2012 8:28 AM
  • check this link this may help you out

    http://www.cplusplus.com/doc/tutorial/preprocessor/

    Tuesday, April 17, 2012 8:46 AM
  • If not, then you are going to have to provide code.


    This is a signature

    I'm not sure what more code I can provide.  I don't see how the code from the C++ file would influence this.  I opened it, then the header, but still no luck.

    However, I went into the header and wrote

    #define MYDLL_EXPORTS

    right directly above the #ifdef statement I showed in my original post. This gets VS2008 to correctly "blue" the dllexport line and grey out the dllimport line. But, it still does NOT produce the .lib file that I need, only the dll and pdb.

    1. How can I get it to produce the .lib?  Properties -> Linker -> Advanced -> Import Library has the name of the .lib specified, and other projects I have specify this also and they produce a .lib.
    2. This project uses precompiled headers. Should I put the "#define MYDLL_EXPORTS" in stdafx.h and #include stdafx.h into the header file? I don't know what the correct use of pre-compiled headers is and so I was hoping someone could tell me the "professional" way to use them.
    Tuesday, April 17, 2012 2:56 PM
  • Well, it is easy to tell how the code from the C++ file would influence this. Think, if you have two projects in your solution, both of these include the header file, but one of the projects is the DLL project and one of them is the executable project. MYDLL_EXPORTS is only defined for the DLL project.

    In the header file, which is included in a source file where MYDLL_EXPORTS is defined and where it isn't defined, how should Visual Studio deal with that block. If you enable the export block, then it is wrong for the executable, if it enables the import block then in is wrong for the DLL. So the reason why I mentioned the other source files is to allow Visual Studio to get the correct context for the header file.

    And before you say that your solution only has one project, look back over your previous posts and please note how you neglected to mention how many projects your solution has in it.

    Secondly, the code you could provide which would help is the contents of the DLL source files. The reason why is that there are lots of things that could go wrong. Since you mentioned that you have precompiled headers, then the perfect one that could be going wrong is that you included your DLL header before stdafx.h. By doing this, the compiler ignores everything in the headers before stdafx.h. If your header is included before stdafx.h then it would be failing to produce a library because it does not see any functions exported.

    Anyway, to answer your two points.

    1. It is produced automatically when the compiler sees at least one function exported. So you have to do nothing but mark the functions you wish to export in some way.

    2. I only really include any headers that are included into all source files with any definitions needed to get them to work correctly. As to "professional", who knows, depending on my mood and size of project I also have a habit of turning them off too. But to be honest, I have never put the definition to trigger the export of functions in a DLL in the precompiled header, that has always gone on the command line for me.


    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.

    Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this.

    • Proposed as answer by Helen Zhao Tuesday, April 24, 2012 7:33 AM
    • Marked as answer by Helen Zhao Wednesday, April 25, 2012 1:41 AM
    Tuesday, April 17, 2012 3:32 PM
  • And before you say that your solution only has one project, look back over your previous posts and please note how you neglected to mention how many projects your solution has in it.

    Good point. I didn't think outside the current project. I have about a dozen, give or take, in this solution. A few of them have .c/.cpp files that include this header.

    Secondly, the code you could provide which would help is the contents of the DLL source files. The reason why is that there are lots of things that could go wrong. Since you mentioned that you have precompiled headers, then the perfect one that could be going wrong is that you included your DLL header before stdafx.h. By doing this, the compiler ignores everything in the headers before stdafx.h. If your header is included before stdafx.h then it would be failing to produce a library because it does not see any functions exported.

    I never thought of this. Thanks. But I checked the one DLL source file and it starts like this:

    #include "stdafx.h"

    #include "myheader.h"

    ...

    #define some stuff

    ...

    #ifdef __cplusplus

    extern "C" {

    #endif

    1. It is produced automatically when the compiler sees at least one function exported. So you have to do nothing but mark the functions you wish to export in some way.

    Ok, I changed the header to be like this:

    #ifdef MYDLL_EXPORTS
    #define MYDLL_API __declspec(dllexport)
    #else
    #define MYDLL_API __declspec(dllexport)
    #endif
    So that it was GUARANTEED to be dllexport and I still don't get the .lib.

    But to be honest, I have never put the definition to trigger the export of functions in a DLL in the precompiled header, that has always gone on the command line for me.


    I would prefer the command line as well, but that doesn't seem to be working.  You use /D right?

    Tuesday, April 17, 2012 4:07 PM
  • Right, have you modified the function prototypes to include this?

    For the functions to be exported, they must be marked as export. The way to do this is to put the MYDLL_API on the functions that you want to export. So if, in this header, you have a function that you want to export.

    void MyFun();

    To make it actually export, you must put MYDLL_API on the function prototype.

    MYDLL_API void MyFun();

    For an example from an actual sample DLL that builds, and produces a .lib file.

    Header file:

    #ifndef MYHEADER_H
    #define MYHEADER_H
    
    #ifdef MYEXPORTS
    #define MYAPI __declspec(dllexport)
    #else
    #define MYAPI __declspec(dllimport)
    #endif
    
    extern"C"
    {
    MYAPI void MyFunc();
    }
    
    #endif

    Source file:

    #include "myheader.h"
    
    extern"C"
    void MyFunc()
    {
    }

    Notice the MYAPI on the forward decleration of MyFunc in the header but not on the definition of MyFunc in the source. For all configurations of the project, in the preprocessor definitions, MYEXPORTS is defined. The output for the compiler is:

    1>------ Build started: Project: testdll, Configuration: Debug Win32 ------
    1>Build started 17/04/2012 17:19:37.
    1>PrepareForBuild:
    1>  Creating directory "d:\testdll\Debug\".
    1>InitializeBuildStatus:
    1>  Creating "Debug\testdll.unsuccessfulbuild" because "AlwaysCreate" was specified.
    1>ClCompile:
    1>  main.cpp
    1>Link:
    1>     Creating library d:\testdll\Debug\testdll.lib and object d:\testdll\Debug\testdll.exp
    1>LinkEmbedManifest:
    1>     Creating library d:\testdll\Debug\testdll.lib and object d:\testdll\Debug\testdll.exp
    1>  testdll.vcxproj -> d:\testdll\Debug\testdll.dll
    1>FinalizeBuildStatus:
    1>  Deleting file "Debug\testdll.unsuccessfulbuild".
    1>  Touching "Debug\testdll.lastbuildstate".
    1>
    1>Build succeeded.
    1>
    1>Time Elapsed 00:00:01.85
    ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

    So this works. Please note, the __declspec(dllexport) only has to be on the function prototype in the header, but besides that, the calling convention and the name mangling (extern"C") must match.


    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.

    Do you want Visual Studio 11 Express to be freely installable on Windows 7 and able to write regular C++ applications? Please vote for this.


    • Edited by Crescens2k Tuesday, April 17, 2012 4:25 PM
    • Proposed as answer by Helen Zhao Tuesday, April 24, 2012 7:34 AM
    • Marked as answer by Helen Zhao Wednesday, April 25, 2012 1:41 AM
    Tuesday, April 17, 2012 4:23 PM
  • Yeah, the only difference I have is that in the source file everything is surrounded by extern "C" like this:

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    void func1() {
    ...
    ...
    }
    void func2() {
    ...
    ...
    }
    
    #ifdef __cplusplus
    }
    #endif

    I clearly must have something wrong in a setting somewhere.  This project only has the precompiled header/src and then one header and one source, so maybe the best bet is to just create a new project.  Who knows what goofy thing could be set wrong.
    Tuesday, April 17, 2012 4:29 PM