Exporting static data in a DLL - c++

I have a DLL which contains a class with static members. I use __declspec(dllexport) in order to make use of this class's methods. But when I link it to another project and try to compile it, I get "unresolved external symbol" errors for the static data.
e.g.
In DLL, Test.h
class __declspec(dllexport) Test{
protected:
static int d;
public:
static void m(){int x = a;}
}
In DLL, Test.cpp
#include "Test.h"
int Test::d;
In the application which uses Test, I call m().
I also tried using __declspec(dllexport) for each method separately but I still get the same link errors for the static members.
If I check the DLL (the .lib) using dumpbin, I could see that the symbols have been exported.
For instance, the app gives the following error at link time:
1>Main.obj : error LNK2001: unresolved external symbol "protected: static int CalcEngine::i_MatrixRow" (?i_MatrixRow#CalcEngine##1HA)
But the dumpbin of the .lib contains:
Version : 0
Machine : 14C (x86)
TimeDateStamp: 4BA3611A Fri Mar 19 17:03:46 2010
SizeOfData : 0000002C
DLL name : CalcEngine.dll
Symbol name : ?i_MatrixRow#CalcEngine##1HA (protected: static int CalcEngine::i_MatrixRow)
Type : data
Name type : name
Hint : 31
Name : ?i_MatrixRow#CalcEngine##1HA
I can't figure out how to solve this. What am I doing wrong? How can I get over these errors?
P.S. The code was originally developed for Linux and the .so/binary combination works without a problem
EDIT: In the given case, the static variables are not directly referred by the application but the method is inlined since it's in the header. I was able to resolve the link errors by moving the methods to the .cpp file.

In this thread at cprogramming.com it is suggested that a static variable is local to the dll and not exported.
Summary of discussion below
The static member is not accessed directly by code in the calling application, only through member functions of the class in the dll. However there are several inline functions accessing the static member. Those functions will be inline expanded into the calling applications code makeing the calling application access the static member directly. That will violate the finding referenced above that static variables are local to the dll and cannot be referenced from the calling application.

My guess is that the class which uses the DLL should see dllimport instead of dllexport in the header. If I am correct, this can typically be achieved by defining a preprocessor macro like:
#ifdef EXPORTING
#define DECLSPEC __declspec(dllexport)
#else
#define DECLSPEC __declspec(dllimport)
#endif
and then use it in the class declaration:
class DECLSPEC Test{
protected:
static int d;
public:
static void m(){}
}
So that in Test.cpp (or wherever it makes sense in your DLL project) you can specify that you are exporting so that it will be exported with dllexport:
#define EXPORTING
#include "Test.h"
int Test::d;
while the other project, which does not define EXPORTING, will see dllimport.
Does it make sense?

With Windows DLLs, there is a specific distinction between __declspec(dllexport) vs __declspec(dllimport), dllexport should be used when compiling the DLL, dllimport should be used when compiling programs that link to this DLL. The standard way of defining this would be with a macro.
The following is the visual studio example:
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the DLL_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// DLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

Despite the summary, one can export static data from a DLL. However, there is a problem that comes up with the standard macros supplied by the Visual Studio DLL project:
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
If you have multiple DLLs calling code from one DLL to another or between EXE and DLL, there is going to be a problem with this macro because every header is going to be exporting. One needs unique macros that handle __declspec. The safest way to handle this problem is as follows:
#ifdef MYPROJECT_DLL_EXPORTS
#define MYPROJECT_API __declspec(dllexport)
#else
#define MYPROJECT_API __declspec(dllimport)
#endif
Then only in the compiler preprocessor options for the DLL project define MYPROJECT_API.
In your header code:
struct/class MYPROJECT_API myclass {
static int counter;
};
And in a .cpp file:
int myclass::counter = 0;

Although it's kinda an old post. I would like to add that (for some reason) to resolve this problem I needed to add the (Windows) __declspec(dllexport)/(import) also INSIDE the .cpp file so the outside code could access it.
// From another answer to ilustrate this =)
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
some_app.h
class DLL_API SomeApp
{
static void MyFunc();
}
some_app.cpp
DLL_API void SomeApp::MyFunc()
{
// Some impl of my app.
}
In my case that was specially required because my functions are templated. Maybe this could work for someone else too.

use inline for c++17
static inline std::string static_variable

Related

Dll access by excel from c++ code

I am trying to create a DLL from C++ code using visual studio 2015.
I have a DLL_Tutorial.h file :
#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream>
extern "C"
{
DECLDIR int Add( int a, int b );
}
#endif
\\
\ Then I created a DLL_Tutorial.cpp
#include <iostream>
#include "DLL_Tutorial.h"
#define DLL_EXPORT
extern "C"
{
__declspec(dllexport) int Add(int a, int b)
{
return(a + b);
}
}
I got a Dll file
I would like to call my function in VBA and apply that to an excel sheet
so in VBA I did :
Public Declare Function Add _
Lib "C:\Users\hasna\Desktop\Projet VBA-C++\projet5\Debug\projet5.dll" (byval a As integer,byval b As integer) As integer
Then in an excel sheet, I enter 2 values (for example 6 and 4 ) I call add function but it gave me : #VALEUR!
Where is the problem ?
Could you please help me resolve that
Thanks
In your DLL header file, it does not appear that you've prefixed the exported API with __declspec(dllexport). Which is usually defined so that the API can use __declspec(dllexport) when building the DLL, and __declspec(dllimport), when the header is being used in an external project. The best thing would be to just create the DLL using the VS 2015 project template, it includes the correct headers, and export definitions for you, so you just need to focus on writing the APIs. Here's a working example from a VS 2015 project:
Example *.h:
#pragma once
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the DLLAPI_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// DLLAPI_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef DLLAPI_EXPORTS
#define DLLAPI_API __declspec(dllexport)
#else
#define DLLAPI_API __declspec(dllimport)
#endif
// This is an example of an exported function.
DLLAPI_API int fnDLLAPI(void);
Example *.cpp:
// DLLAPI.cpp : Defines the exported functions for the DLL application.
//
#include "DLLAPI.h"
// This is an example of an exported function.
DLLAPI_API int fnDLLAPI(void)
{
return 42;
}
The Windows Via C/C++ book is also a very good resource regarding writing DLLs. Now regarding the VB import, I am not sure as I am not familiar with importing APIs via VB.

How to declare a class shared between a library and an application

I have a common utility class that is shared between two projects, an desktop application project and a library project (dll). I'm working under VS2013.
To make this class available to external calls when it's compiled as part of my library, I use a macro like this:
#include "global.h"
class MYCLASS_EXPORT UtilityClass {
public:
...
My global.h file contains the following:
#ifdef MYCLASS_LIBRARY
# define MYCLASS_EXPORT __declspec(dllexport)
#else
# define MYCLASS_EXPORT __declspec(dllimport)
#endif
So when I use that class inside my library I set the preprocessor macro MYCLASS_LIBRARY and an application that link my library can use the UtilityClass.
Instead, when I use that class as part of my C++ desktop application project (that doesn't have the preprocessor macro MYCLASS_LIBRARY), I get from the compiler an "inconsistent dll linkage" error because of MYCLASS_EXPORT declaration.
So, how to declare my class so that can be used both in a library project and in a desktop application project (so without the need to export that class)?
Just to be more clear, a working solution I've found is the following:
#ifdef MYCLASS_LIBRARY
#include "global.h"
#endif
#ifdef MYCLASS_LIBRARY
class MYCLASS_EXPORT UtilityClass {
#else
class UtilityClass {
#endif
public:
...
Now everything compile and run fine, but does not seem a good approach...
I can think of the following option:
In the desktop application, define a macro, MYCLASS_STATIC and change the .h file to use:
#ifdef MYCLASS_STATIC
# define MYCLASS_EXPORT
#elif defined(MYCLASS_LIBRARY)
# define MYCLASS_EXPORT __declspec(dllexport)
#else
# define MYCLASS_EXPORT __declspec(dllimport)
#endif

What could be causing this linker error?

I been trying to resolve this unresolved external symbol on a static variable for hours now, and I'm at my wits' end. I'm using Visual Studio 2010. Here's a simplified overview of the situation:
Projects in question:
-ProjA (outputs a .dll and .lib)
-ProjB (outputs a .exe)
In ProjA, I have these two files:
//foo.h
#pragma once
class SUP
{
public:
static int staticint;
};
and
//foo.cpp
#include "foo.h"
int SUP::staticint = 10;
ProjB links to ProjA.lib
//main.cpp
#include "{Full_Path}foo.h"
int main(){
std::cout << SUP::staticint << std:: endl;
}
Now, main.cpp compiles without any problems, but when I try to build the project, I get the following error:
main.obj : error LNK2001: unresolved external symbol "public: static int SUP::staticint" (?staticint#SUP##2HA)
I'm almost 100% certain I've set up ProjB's options correctly. Under "Additional Dependencies" all I have "ProjA.lib", and under "Additional Library Directories" I have the path to the directory where the ProjA.lib file is generated.
I've even had ProjA output a .map file, and in the map I find:
0003:00004458 ?staticint#SUP##2HA 10049458 foo.obj
So I'm guessing that it means that staticint has been defined correctly.
What could possibly be going wrong? Obviously, I'm doing something wrong, but I fail to see what. I've made sure that ProjB is linking with the correct .lib file. I've made sure the include directories are good. I've made sure that the definition of the static variable is sound. I will provide any other information if necessary.
Under MSVS you must explicitly declare the symbols you want exported with __declspec(dllexport).
Since SUP is in a different library, only exported symbols will be available to other modules, which must mark them as __declspec(dllimport).
This dual behavior is usually achieve through a macro:
#ifdef EXPORT_MODULE
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP __declspec(dllimport)
#endif
and the class declared as
class DLLIMPEXP SUP
{
public:
static int staticint;
};
where EXPORT_MODULE is defined in the project which exports the symbol.

Visual C++: Exporting decorated function name in a def file

I want to export a decorated function name in a def file like this:
LIBRARY Example
EXPORTS
??0__non_rtti_object#std##QAE#ABV01##Z=myfunc #1
The Problem is that the linker strips the function name at the first #-sign and places just
"??0__non_rtti_object" into the export table. My question is now, if there is a way to include
the #-characters as well? I use Visual Studio 2010. Maybe there is someone who can help me.
Thanks in advance, Hannes.
Preamble
You didn't answer my comment about the use of the .DEF file, so I assume you must be unfamiliar with the the dllexport and dllimport qualifiers. With them, there is no need for the .DEF file to export symbols.
If there is a particular need for the .DEF file that invalidate the use of the dllimport/dllexport feature, please ignore the following.
How to use dllimport/dllexport?
In your public header (say, public.hpp), write something like:
#ifdef MY_PROJECT_EXPORTS
#define MY_PROJECT_API __declspec(dllexport)
#else
#define MY_PROJECT_API __declspec(dllimport)
#endif
This way, the macro MY_PROJECT_API will enable the export/import of your symbols. For example, later, in the same public.hpp, you can declare:
// A global variable
MY_PROJECT_API int myGlobalVariable ;
// A function
MY_PROJECT_API void my_function() ;
// A class or struct
class MY_PROJECT_API MyClass
{
public :
int i;
virtual int foo() ;
// etc.
} ;
Then, what you need to do is, in the project options of your library, define the MY_PROJECT_EXPORTS: This way, when you compile your library, the symbols above are declared dllexport, and when someone else includes your public.hpp header, the symbols above will be dllimport
And if your code is cross-platform (dllimport/dllexport is a MS compiler feature), just wrap the defines above around a compiler test. For example:
#ifdef _MSC_VER
// For MS Visual Studio
#ifdef MY_PROJECT_EXPORTS
#define MY_PROJECT_API __declspec(dllexport)
#else
#define MY_PROJECT_API __declspec(dllimport)
#endif
#else
// For other compilers
#define MY_PROJECT_API
#endif
About the .DEF file?
The .DEF file was used before, when exportable C functions were still "the way to go" on Visual Studio.
For strong type safety, C++ decorate its symbols.
The downside is that each compiler has its own decoration scheme (which never bothered me in 12-years of development), and that finding the exact, decorated name of a symbol can't be painful.
But the merits of that is that:
You can now export overloaded/namespaced functions/symbols
the parameter types are part of the ABI, meaning the linker can verify you aren't screwing up or cheating with your types
The dllimport and dllexport features have the following advantages:
it enables the export to be done at source level, instead of using yet another project file
the programmer can now ignore the particular decoration scheme (which usually only interests the linker), all the while profiting from the strong type safety of C++ extended to the linker.
Sources
For more information, see:
__declspec : http://msdn.microsoft.com/en-us/library/dabb5z75.aspx
dllexport, dllimport : http://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx
Using dllimport and dllexport in C++ Classes : http://msdn.microsoft.com/en-us/library/81h27t8c.aspx

How to write modules on Windows?

I'm currently writing a program that should be working on both Windows and Linux. The program uses dynamic modules (LoadLibrary/dlopen) to simplify deployment of different functions.
The Linux part works just fine: The main program exports functions and variables with -Wl,--export-dynamic so the modules can access them, and the modules can be compiled with gcc's -shared option without the requirement to resolve all symbol dependencies when linking.
With Windows (using MSVC 2010), this seems not to work. I'm exporting functions and variables from the main program using __declspec(dllimport), but I am not able to access functions and variables from the main program because linking fails (unresolved external, LNK1120).
How to deal with this? Thank you.
Edit (code sample):
core-file.cpp
#include "core-file.hpp"
Cls_A cls_instance;
void Cls_A::do_something() {
while(0);
}
core-file.hpp
#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif
class TEST_API Cls_A {
public:
void do_something();
};
extern Cls_A cls_instance;
module.cpp
#include "core-file.hpp"
TEST_API int my_init_function() {
cls_instance.do_something();
return 0;
}
__declspec(dllimport) is for when you're compiling the the program that uses the DLL. When you compiling the actual DLL, you want to use __declspec(dllexport).
Your use of these must be consistent. The typical idiom is to define a macro that will use dllimport and dllexport based on the presence of a macro. In the project the builds the DLL, you define the macro that means to export the functions, and in other projects you don't define it, which means to import them:
#ifdef PROJECT_NAME_BUILD_DLL
#define DLL_SYMBOL __declspec(dllexport)
#else //PROJECT_NAME_BUILD_DLL
#define DLL_SYMBOL __declspec(dllimport)
#endif //PROJECT_NAME_BUILD_DLL
DLL_SYMBOL void SomeFunction(Type value);
The project that builds the DLL will define PROJECT_NAME_BUILD_DLL; projects that use the DLL which include this header do not define this.
On Windows, when you want to link against exported symbols you have to remember to specify all the import libraries that were generated when you linked the modules whose symbols you want to import. (You can just leave the symbols unresolved on Linux because the executable format is different and it's possible to defer symbol resolution to load time.)