I'm writing a c++ project with MS Visual Studio 2015. In my project I have to call some variables declared and defined in a C file.
As you can see below, the variables are enclosed within the extern "C" structure:
#if defined __cplusplus
extern "C" {
#endif
GainType MYDLL_API BestCost; /* Cost of the tour in BestTour */
int MYDLL_API *BestTour; /* Table containing best tour found */
double MYDLL_API LowerBound; /* Lower bound found by the ascent */
#if defined __cplusplus
}
#endif
But, however, the compiler isn't able to resolve these three variables.
I've searched everywhere, i've tried all the proposed solutions, but it still doesn't work.
How can I solve it?
Thanks to everybody!
This looks like the c code is in a DLL
For the compiler to find this.
Need to define MYDLL_API as __declspec(dllimport) for C++
Need to link with .lib file
Seems that the symbols come from a DLL library. Then you need to add the import library (*.lib) of the DLL to the list of libraries the application is linked with.
In Visual Studio options, this can be done under project properties, Linker / Input / Additional Dependencies (add the lib name there).
Also make sure that the path to the *.lib is set in Linker / General / Additional Library Directories.
Related
#if COMPILING_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
How / where do I define COMPILING_DLL ?
Seen here:
what does __declspec(dllimport) really mean?
Sounds like I can't use load-time dynamic linking at all if I can't use the same header?
One another option:
Use the default defined macro local to the project.
You can see the default defined macros local to the project in the below location:
Properties -> C/C++ -> Preprocessor -> Preprocessor Definition.
Example:
Suppose your Project Name is: MyDLL
Default Macro Local to that project: MYDLL_EXPORTS
#ifdef MYDLL_EXPORTS
/*Enabled as "export" while compiling the dll project*/
#define DLLEXPORT __declspec(dllexport)
#else
/*Enabled as "import" in the Client side for using already created dll file*/
#define DLLEXPORT __declspec(dllimport)
#endif
Best place to define COMPILING_DLL=1 is command line of compiler. If you use Visual Studio IDE then it is in Project properties ... C/C++ ... Preprocessor ... Preprocessor Definitions.
__declspec(dllimport) is Microsoft specific extension to C++. Microsoft has excellent online documentation.
In the DLL project, you add a #define (either in a header file or in the project properties) for COMPILING_DLL. As this will not be set for any other project (especially if you name it something better than COMPILING_DLL) then the #if directive will work properly.
You (actually Visual Studio in ideal cases) defines the COMPILING_DLL as an argument to the compiler when you build the DLL. So, it will default to __declspec(dllexport). On the other end, when you USE the DLL's header file, you don't define this, so DLLEXPORT will be evaluated by default to __declspec(dllimport).
If you use CMake to generate your build configuration, you should be able to use
the macro <projectname>_EXPORTS the way you want to use COMPILING_DLL, where projectname was defined with the CMake command project(projectname):
A preprocessor macro, <target_name>_EXPORTS is defined when a shared library compilation is detected.
source
I tested and it works on Windows using the Ninja generator with compiler MSVC from Visual Studio 2015 Express.
Related: CMake adds -Dlibname_EXPORTS compile definition
You can't define function body that way in the header file. It is prohibited by __declspec(dllimport). This specifier can only be specified on function declaration, not definition.
You have to move the function body to a source file.
in header file:
extern DLLEXPORT void test2();
In .cpp file:
void test2()
{
// ...
}
As folks said, don't forget to add COMPILING_DLL to the project preprocessor definitions.
Actually, the real problem is the preprocessor directive.
You should use #ifdef and not #if to test if the variable is really defined (and we don't care about the defined value or if there is any).
NOTE: I know this thread is 1-year old but it still may be useful for somebody who have this problem in the future.
I am trying to create a dynamic library and use it in a console application. The library is Multisite.lib.
My problem is that when I add the project as a reference and add the header files directory it works well, however, when I try to use this library in an independent project I get the unresolved external symbol error.
What I did in the independent project is to add the library to the Linker > Input > Additional Dependencies and add the header directories
#pragma once
#ifndef MultiSite_IMPORTS
#define MATHLIBRARY_API extern "C" __declspec(dllexport)
#else
#define MATHLIBRARY_API extern "C" __declspec(dllimport)
#endif
#define STACKMODE __stdcall
#include <string>
struct interfaceManager;
MATHLIBRARY_API interfaceManager* STACKMODE createInstance();
MATHLIBRARY_API void STACKMODE bert_init(interfaceManager * inst , int bid);
MATHLIBRARY_API bool STACKMODE bert_connect(interfaceManager * inst, std::string IP);
These are the functions that I am trying to export and that are considered unresolved external symbols
EDIT
I tried to use the VS developer tools using dumpbin /EXPORTS MultiSite.lib and all my functions are there
The header doesn't contain the magic line needed to make Visual Studio link the right library. That's #pragma comment(lib, "MultiSite.lib"). It goes after #define MATHLIBRARY_API extern "C" __declspec(dllimport).
Alternatively, you can indeed tell the linker directly that MultiSite.lib is an additional input. See the Visual Studio linker property pages of your executable project.
"What I did in the independent project is to add the library to the Linker > Input > Additional Dependencies and add the header directories"
As far as I'm concerned, the project lacks MultiSite.lib. I suggest you should add the path to the .lib file to the Additional Library Directories (property -> linker -> General -> Additional Library Directories).
The problem was using a 64-bit library on a 32-bit application.
That's why it was working fine when I added it to the same solution but not in my independent project.
I used to think that visual studio can detect a wrong format but turns out that just the exported symbol's names change between two same libraries with different bit configuration.
Hence this explains the unresolved external symbol error that I encountered
I had a question about DLL building / linking in Visual Studio 2005 and later. Basically my understanding and experience is this:
To build a DLL, I specify the project properties to build a DLL, and then I but __declspec(dllexport) in front of any functions or members that I want to publically expose from the DLL. Building the project will result in a DLL, a Lib, and a header file that can be deployed as say an API or something.
On the other end, to have your other compiled executable application dynamically link to the DLL and use its functions, you simply need to have your executable project include the header files and link with the small lib file that was created when the DLL was built. As long and the compiled application can find the DLL, everything will work.
That has been my experience and that is also how the Microsoft DLL building tutorial described everything on MSDN. I am wondering: is this standard practice? When would you ever need to use __declspec(dllimport) anywhere? Am I missing something?
Thanks!
Yes you would use __declspec(dllimport) and you generally have a macro that controls whether a source file either exports (if it's part of your DLL) or imports (if it's part of the using-executable) symbols.
In your DLL you can set a manifest constant to the build settings of some sort, say 'BUILDING_MY_DLL' and then create the macro like this within your header file:
#ifdef BUILDING_MY_DLL
#define MY_DLL_EXPORT __declspec(dllexport)
#else
#define MY_DLL_EXPORT __declspec(dllimport)
#endif
and then decorate your exported functions like this:
MY_DLL_EXPORT int func(int y);
You can also export entire classes this way too:
class MY_DLL_EXPORT InterestingClass
{
...
};
I had a question about DLL building / linking in Visual Studio 2005 and later. Basically my understanding and experience is this:
To build a DLL, I specify the project properties to build a DLL, and then I but __declspec(dllexport) in front of any functions or members that I want to publically expose from the DLL. Building the project will result in a DLL, a Lib, and a header file that can be deployed as say an API or something.
On the other end, to have your other compiled executable application dynamically link to the DLL and use its functions, you simply need to have your executable project include the header files and link with the small lib file that was created when the DLL was built. As long and the compiled application can find the DLL, everything will work.
That has been my experience and that is also how the Microsoft DLL building tutorial described everything on MSDN. I am wondering: is this standard practice? When would you ever need to use __declspec(dllimport) anywhere? Am I missing something?
Thanks!
Yes you would use __declspec(dllimport) and you generally have a macro that controls whether a source file either exports (if it's part of your DLL) or imports (if it's part of the using-executable) symbols.
In your DLL you can set a manifest constant to the build settings of some sort, say 'BUILDING_MY_DLL' and then create the macro like this within your header file:
#ifdef BUILDING_MY_DLL
#define MY_DLL_EXPORT __declspec(dllexport)
#else
#define MY_DLL_EXPORT __declspec(dllimport)
#endif
and then decorate your exported functions like this:
MY_DLL_EXPORT int func(int y);
You can also export entire classes this way too:
class MY_DLL_EXPORT InterestingClass
{
...
};
How can I remove this link warning? You can see code segment that causes this warning.
static AFX_EXTENSION_MODULE GuiCtrlsDLL = { NULL, NULL };
//bla bla
// Exported DLL initialization is run in context of running application
extern "C" void WINAPI InitGuiCtrlsDLL()
{
// create a new CDynLinkLibrary for this app
new CDynLinkLibrary(GuiCtrlsDLL);
// nothing more to do
}
warning C4273: 'InitGuiCtrlsDLL' : inconsistent dll linkage
I have also export and import definitions, like:
#ifdef _GUICTRLS
#define GUI_CTRLS_EXPORT __declspec(dllexport)
#else
#define GUI_CTRLS_EXPORT __declspec(dllimport)
#endif
The purpose of the preprocessor statements:
#ifdef _GUICTRLS
#define GUI_CTRLS_EXPORT __declspec(dllexport)
#else
#define GUI_CTRLS_EXPORT __declspec(dllimport)
#endif
is to make sure that the header file declares the class or function as __declspec(dllexport) in the .dll where it is defined, and as __declspec(dllimport) for any other .dll that might want to use it.
For this to work, _GUICTRLS must be defined when compiling the exporting .dll, and not defined for any other .dll. Generally you would expect _GUICTRLS to be defined in the project properties, under C/C++ -> Preprocessor -> Preprocessor Definitions.
The compiler error you are seeing usually happens because either _GUICTRLS is not defined for the project that is doing the export, or it is defined for multiple projects, usually resulting from cutting an pasting from one project to another. You will also see this if _GUICTRLS is defined in a header file that is included in multiple projects.
There are multiple possibilities:
1) static AFX_EXTENSION_MODULE GuiCtrlsDLL = { NULL, NULL };
You use AFX_EXTENSION_MODULE. This means that you are implementing an MFC extension DLL. For such extension dlls you have to define the preprocessor _AFXEXT. Set this in the C++ compiler settings of your Visual C++ project
see:
How To Use _declspec(dllexport) in an MFC Extension DLL: http://support.microsoft.com/kb/128199
AFX_EXTENSION_MODULE Structure: http://msdn.microsoft.com/en-us/library/sxfyk0zk.aspx
TN033: DLL Version of MFC: http://msdn.microsoft.com/en-us/library/hw85e4bb.aspx
2) It is likely that you have a duplicated definiton/declaration.
In addition to reading the warning message, pay attention to where it occurs if you have multiple projects as part of a workspace.
I wasted time looking for a problem in my DLL which was compiling and linking correctly. The workspace was also building the main application and my error was that I had inadvertently included a new (DLL) source file into the build file list of the application itself.
The main program requires the DLL header mynewdll.h to import things but does not require the source file mynewdll.cpp. (The code is brought in at run time with a DLL.) I have a habit of including header and code files into projects as a pair, and this is where I had gone wrong.
I would have detected the error much sooner if I had been alert and noticed that the DLL project linked with no errors and it was the main program that complained!
My DLL source code and project was error free and it was only the way I tried to build my executable that was faulty.
That warning is usually caused by a duplicate definition of a function with different use of dllimport. Are you sure you didn't do this?
[ CMake inconsistent dll linkage ]
I encountered the following issue + solution with the __declspec(dllexport) + __declspec(dllimport) :
# # #CMakeLists.txt
add_defintions(-DMYLIB=1)
# The above was the solution...
# (MYLIB is used in the standard ifdef + define MYLIB_EXPORT syntax)
# Below: seems to get overruled by other directory's headers:
set_source_files_properties( file1.h file2.h COMPILE_FLAGS "-DMYLIB=1")
This was annoying because a number of sources say to use the 'set source file properties' command to get better granularity but the doc is not clear on what happens to file1.h's declares when included from a different directory... better stick with add_definitions( -DMYLIB=1 ) for now!
To catch this problem: in your Foo.cpp file:
#include "export.h"
#if defined(MYLIB)
#if defined(OTHERLIB)
static_assert(0,"error, check your definitions!");
// OTHER depends on MY; can't have both of these flags being set!
#endif
#endif
struct OTHER_EXPORT foo
{
};
See that you are not defining the exported symbols in a different project. Also clean all the intermediate files by hand and recompile.
To elaborate the answer of damian with an example. I read it but didn't understand at first glance.
You have a shared library with a source file compiled in that contains the function. In a new project you use the library and in addition you compile also the source file to use the function (I forgot that it is already in the library). Within the library the functions label is exported, within the additional compiled source file the functions label is marked to be imported. That's the conflict.
In my case, error C4273 was caused by trying linking to .lib file from a DLL dynamic load tester app in Qt5 by msvc2017_64 toolchain. Removing the reference to .lib file by changing LIBS setting in .pro file have the problem solved.