Unable to understand class definition in C++ - c++

I am a newbie to disk-based R-trees although I have coded main memory based R-Trees. In order to understand disk based R-Trees I am using the library "libspatialIndex". While understanding the library I am coming across strange definitions of classes like the one given below:
class SIDX_DLL IStorageManager
{
public:
virtual void loadByteArray(const id_type id, uint32_t& len, byte** data) = 0;
virtual void storeByteArray(id_type& id, const uint32_t len, const byte* const data) = 0;
virtual void deleteByteArray(const id_type id) = 0;
virtual ~IStorageManager() {}
}; // IStorageManager
I fail to understand this new definition of class whereby it uses SIDX_DLL in the class definition. Can someone please give me pointers as to what does SIDX_DLL represent in the class definition.

It's a macro that allows the same include be used from library clients and library implementation. Add attributes required to implement dynamic linking.

Tools.h
47 #if defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64
48 #ifdef SPATIALINDEX_CREATE_DLL
49 #define SIDX_DLL __declspec(dllexport)
50 #else
51 #define SIDX_DLL __declspec(dllimport)
52 #endif
53 #else
54 #define SIDX_DLL
55 #endif
That's just a macro, which adds compiler-specific attributes to class definition

SIDX_DLL is a macro. It's for making the IStorageManager symbol exported in a dll.
This kind of macros are usually defined like this:
#if defined(_MSC_VER) && defined(SIDX_EXPORTS)
# define SIDX_DLL __declspec(dllexport)
#elif defined(_MSC_VER)
# define SIDX_DLL __declspec(dllimport)
#else
# define SIDX_DLL
#endif
SIDX_EXPORTS is a MSVC-defined symbol that only gets defined when compiling the SIDX dll. In that case, SIDX_DLL expands to __declspec(dllexport). In all other cases, it expands to __declspec(dllimport) — which imports the symbol to wherever it is used.
The empty SIDX_DLL (the last #else in the listing) is for non-Windows environments.

It's define. You can read about this at http://libspatialindex.github.com/doxygen/Tools_8h_source.html 54 row.

It's a macro. It probably defines the dll import/export properties.
Go to its definition (F12), and you'll see that it is defined to __declspec(import) and __declspec(export)

Related

How to initialize api function pointers from a dynamic library in a C-API

I'm explicitly loading a c-API dynamic library (dll/so), where it is not possible to link symbols with a lib-file. So I use GetProcAddress and dlsym to find the apropriate functions.
The problem I have is due to the static declaration of "foo" and "baz" I have to use GetProcAddress/dlsym for every implementation file that includes this header.
The behaviour I want is that I only want to lookup the symbols once for the process.
Do I have to declare them all as "extern" then have a own set of function pointers in the project that I then set with GetProcAddress/dlsym?
What is the recommended way to fix it?
Example API header:
#ifdef _WIN32
#define API_IMPORT __declspec(dllimport)
#define API_EXPORT __declspec(dllexport)
#elif defined(__GNUC__)
#define API_EXPORT __attribute__((visibility("default")))
#define API_IMPORT
#else
#error Unsupported for now
#endif
#if LIB_COMPILING
#define API_DECL API_EXPORT
#else
#define API_DECL API_IMPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
API_DECL int ifoo(int bar);
API_DECL void ibaz(int qux);
typedef int (* PFN_FOO_PROC)(int);
typedef void (* PFN_BAZ_PROC)(int);
static PFN_FOO_PROC foo = 0;
static PFN_BAZ_PROC baz = 0;
#ifdef __cplusplus
}
#endif
"ifoo" and "ibaz" contains the actual implemenations in a c-file for the dynamic library.
So in this example to load symbols for linux:
foo = (PFN_FOO_PROC) dlsym(handle, "ifoo");
baz = (PFN_BAZ_PROC) dlsym(handle, "ibaz");
Thanks for any help
The whole idea behind delay loading is that you don't have to use LoadLibrary / GetProcAddress. Instead, if (say) foo is a function in your delay loaded DLL you can simply say if (foo) before calling it to see if it's actually available.
I know less about Linux and macOS, but I do know that macOS has 'weak linking' which operates in a similar way. I don't know what Linux does, sorry, but I imagine it offers something similar.

Defining a struct imported from DLL works only when its constructor is defined in the header file [duplicate]

This question already has answers here:
How do I safely pass objects, especially STL objects, to and from a DLL?
(4 answers)
Closed 7 years ago.
I have a class which has two overloaded functions. How do I export it from a dll and also how to use it by other C++ classes? My class looks like this:
#define DECLDIREXP __declspec(dllexport)
#define DECLDIRIMP __declspec(dllimport)
class DECLDIREXP xyz
{
public:
void printing();
void printing(int a);
};
using namespace std;
void xyz::printing()
{
cout<<"hello i donot take any argument";
}
void xyz::printing(int a)
{
cout<<"hello i take "<< a <<"as argument";
}
A common approach is to have a single macro (let's call it EXPORT) which either expands to dllimport or dllexport depending on whether some sort of "building the DLL right now" define is set, like this:
#ifdef MAKEDLL
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __declspec(dllimport)
#endif
class EXPORT xyz {
// ...
};
The idea is that when building your DLL, you add MAKEDLL to the preprocessor definitions. That way, all the code will be exported. Clients who link against your DLL (and hence include this header file) don't need to do anything at all. By not defining MAKEDLL, they will automatically import all the code.
The advantage of this approach is that the burden of getting the macros right is moved from the many (the clients) to just the author of the DLL.
The disadvantage of this is that when using the code above as it is, it's no longer possible to just compile the code directly into some client module since it's not possible to define the EXPORT macro to nothing. To achieve that, you'd need to have another check which, if true, defines EXPORT to nothing.
On a slightly different topic: in many cases, it's not possible (or desired!) to export a complete class like that. Instead, you may want to just export the symbols you need. For instance, in your case, you may want to just export the two public methods. That way, all the private/protected members won't be exported:
class xyz
{
public:
EXPORT void printing();
EXPORT void printing(int a);
};
As I remember, normally, you export not a class but a factory function that creates a new instance of class and returns a pointer. The class declaration resides in header file for compile time.
I may be wrong about the example (that was long ago), but here how it should approximately look like:
Header file (.h):
class MyClass { ... };
extern "C" DLL_API MyClass* createMyClass();
Source file (.cpp):
DLL_API MyClass* createMyClass() {
return new MyClass();
}
Define MY_DLL_EXPORT while compiling, see foraidt's answer example.
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
class DLLEXPORT Class_Name {
//....
}
When compiling your library you should define a macro (command line preprocessor definition), let's call it MY_DLL_EXPORT.
Then in your library's code do something like this:
#ifdef MY_DLL_EXPORT
# define DLL_API __declspec(dllexport)
#else
# define DLL_API __declspec(dllimport)
#endif
class DLL_API some_class { /*...*/ }

Using the #define macro to standardize class declaration

I'm building a C++ DLL for one of my projects. I am trying to standardize the way that are class are defined. So instead of each time writing:
class __declspec(dllexport) ClassName
I'm building a #define macro to ease this process:
#define CLASS( cName ) class __declspec(dllexport) cName
But, when I'm using it, it gives me the following error:
Error: Expected a ';'
I know you can use a #define macro to define an entire class creation, but can it be used to define only the "class header" ?
Thanks,
Keep in mind that I'm trying to do so because we are going to deal with hundreds of classes, so these kinds of "automation" would be most helpful :)
EDIT:
example:
#define CLASS( nClass ) class __declspec(dllexport) nClass
CLASS( APTest )
{ // Here is the error of missing ';'
public:
APTest();
};
Don't do this.
C++ has already been standardized!
If you ever expect other people to read your code then just write it in conventional C++, not some homecooked dialect that looks different. Get used to the proper C++ syntax, it will make it easier to read other people's C++ code.
One thing that does make sense is to simplify the __declspec part, which you can do like this:
#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif
class DLLEXPORT APTest
{
// ...
};
You're really not making your life any simpler by writing CLASS( APTest ) and you make it harder for others to understand. Just say no.
There is a better way than #Wakely. Do it like this:
#ifdef MYLIB_DLL
#ifndef MYLIB_IFACE
#ifdef MYLIB_IFACE_EXPORT
#define MYLIB_IFACE _declspec( dllexport )
#else // !MYLIB_IFACE_EXPORT
#define MYLIB_IFACE _declspec( dllimport )
#endif // !MYLIB_IFACE_EXPORT
#endif // !MYLIB_IFACE
#else // !MYLIB_DLL
#ifndef MYLIB_IFACE
#define MYLIB_IFACE
#endif // !MYLIB_IFACE
Put a block like that in a header that is used by every file in your dll, and in the public header for your dll.
Every symbol that should be exported from your dll gets tagged like this:
class MYLIB_IFACE MyClass
{
};
void MYLIB_IFACE myFunc();
Then in every .cpp file in your dll the first line should be:
#define MYLIB_IFACE_EXPORT
If you do this, then it will build just fine on POSIX systems that don't use dllexport/dllimport. To build a dll version of your lib you define MYLIB_DLL. ( you can do this in the compiler's flags so it can be controlled from your build system )
To build a static version of your lib, don't define MYLIB_DLL.
#Update:
You can extend this to support GCC visilibity like this:
#ifdef WIN32
#define KX_SYMBOL_EXPORT _declspec( dllexport )
#define KX_SYMBOL_IMPORT _declspec( dllimport )
#else // GCC
#define KX_SYMBOL_EXPORT __attribute__(( visibility ("default")))
#define KX_SYMBOL_IMPORT
#endif
#ifdef KX_DLL
#ifndef KX_IFACE
#ifdef KX_IFACE_EXPORT
#define KX_IFACE KX_SYMBOL_EXPORT
#else // !KX_IFACE_EXPORT
#define KX_IFACE KX_SYMBOL_IMPORT
#endif // !KX_IFACE_EXPORT
#endif // !KX_IFACE
#else // !KX_DLL
#ifndef KX_IFACE
#define KX_IFACE
#endif // !KX_IFACE
#endif // !KX_DLL
I remove the GCC bit in the first example for simplicity. But this is how a really do it. #Wakely is so right.

error C2375: redefinition; different linkage

Error place in api:
#define DLLEXPORT extern "C" __declspec(dllexport)
DLLEXPORT int CAnyseeUSBTVControllerDlg::InitCaptureDevice()
{
In my .h library class and function definition:
class CAnyseeUSBTVControllerDlg : public CDialog
{
// Construction
public:
int InitCaptureDevice(void);
Any idea how to resolve it?
"Error 1 error C2375:
'CAnyseeUSBTVControllerDlg::InitCaptureDevice'
: redefinition; different
linkage c:\Program
Files\toATS_DVS\anysee\anyseee30\anyseee30\anyseeUSBTVControllerDlg.cpp 122 anyseee30"
You have to make sure you use the same declaration in your header file. Otherwise it is seen as different methods.
class CAnyseeUSBTVControllerDlg : public CDialog
{
// Construction
public:
int InitCaptureDevice(void);
DLLEXPORT int CaptureDevice(void);
See Using dllimport and dllexport in C++ Classes
This may happen because
You defined the prototype of a function in different places with
different visibility (extern vs static)
Same as above but
different name mangling (extern "C" vs extern "C++")
Same as above but different dll export (__declspec(dllimport) vs
__declspec(dllexport)).
To solve, enable /p for files to see how they are preprocessed (this has to be in a file by file basis, and will stop generating .obj for that file), look for a .i file with the result.
Or using /displayincludes, or simply greping thru the code.
You can have DLLEXPORT stated in .cpp file, but not in a header file (because otherwise compiler treats these functions as different ones).
Make your definition also DLLEXPORT.
From http://tldp.org/HOWTO/C++-dlopen/thesolution.html
C++ has a special keyword to declare a
function with C bindings: extern "C".
A function declared as extern "C" uses
the function name as symbol name, just
as a C function. For that reason, only
non-member functions can be declared
as extern "C", and they cannot be
overloaded.
I believe static members may also be possible to extern "C", but you can't do what you're trying to do directly. You'll need to make a C-only wrapper interface that calls your class member functions. You can then extern "C" the wrappers and expose that outside your DLL.
//foo.h
#pragma once
#ifdef FOO_EXPORTS
#define FOO_API __declspec(dllexport)
#else
#define FOO_API __declspec(dllimport)
#endif
namespace foo
{
class Baz
{
public:
FOO_API static auto say_hello() -> void;
};
}
The key things, not so much the function names, or my use of the trailing return type, is that you put the name of the #defined __declspec in front of the function you want to export, much like you would a type.
You would also do the same in the function definition:
//foo.cpp
#include "foo.h"
namespace foo
{
FOO_API auto Baz::say_hello() -> void
{
do
{
MessageBox(nullptr, L"Seems to be working okay!", L"OK", MB_OK);
exit(1);
}
while (0);
}
}
The function implementation isn't important, just that you put FOO_API in front.
Today I faced the same issue and for me, I had failed to include the type before my class.
That is I had to change :
class Core
{
private:
py::object cls;
py::object obj;
py::object startFunc;
py::object startFuncAsync;
py::object stopFunc;
...
public:
...
};
to
#ifndef CORE_H
#define CORE_H
/* If we are we on Windows, we want a single define for it.*/
#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))
#define _WIN32
#endif /* _WIN32 */
#if defined(_WIN32) && defined(_CORE_BUILD_DLL)
/* We are building FV as a Win32 DLL */
#define CORE_API __declspec(dllexport)
#elif defined(_WIN32) && defined(CORE_DLL)
/* We are calling FV as a Win32 DLL */
#define CORE_API __declspec(dllimport)
#elif defined(__GNUC__) && defined(_CORE_BUILD_DLL)
/* We are building FV as a shared / dynamic library */
#define CORE_API __attribute__((visibility("default")))
#else
/* We are building or calling CORE as a static library */
#define CORE_API
#endif
class CORE_API Core
{
private:
py::object cls;
py::object obj;
py::object startFunc;
py::object startFuncAsync;
py::object stopFunc;
...
public:
...
};
Side note:
This will allow for building your project as a dll or a lib and neither of them (i.e. use them by including them) and you can also compile this code under linux, so nothing platform specific here.
If you are in visual studio and want to build a dll, just go to Properties>C/C++>CommandLine and enter :
/D_CORE_BUILD_DLL
and replace CORE with your own designated name.

Why do C++ class definitions on Windows often have a macro token after 'class'?

I am trying to understand an open source project, where I came across the following class declaration:
class STATE_API AttributeSubject : public AttributeGroup, public Subject
{
public:
AttributeSubject(const char *);
virtual ~AttributeSubject();
virtual void SelectAll() = 0;
virtual const std::string TypeName() const;
virtual void Notify();
virtual AttributeSubject *CreateCompatible(const std::string &) const;
virtual AttributeSubject *NewInstance(bool copy) const { return 0; };
virtual bool VarChangeRequiresReset(void) { return false; };
};
What does STATE_API before the class name AttributeSubject signify? Is it some sort of macro?
It's probably a typedef to __declspec(dllimport) or __declspec(dllexport) and is used inside DLLs on windows platform to export classes.
Neil is right, it's a macro.
It usually looks like this:
#ifdef INDSIDE_DLL
#define STATE_API __declspec(dllexport)
#else
#define STATE_API __declsped(dllimport)
#endif
You define INSIDE_DLL only in your dll and export all the classes declared with STATE_API macro.
It's a macro. What it expands to depends on your platform - it is cannot be part of standard C++ (unless it expands to nothing).
Is this the source code of a DLL project ?
If so, then STATE_API must be a preprocessor macro, enabling you to use the header in which this class is declared in both the library project and the application using the library.
in the library project, STATE_API would be defined to __declspec(dllexport)
in the project using the library, STATE_API would be defined to __declspec(dllimport)
This is usually achieved with something like this :
#ifdef USRDLL
#define STATE_API __declspec(dllexport)
#else
#define STATE_API __declspec(dllimport)
#endif
USRDLL being defined in the project options of the DLL.
It is a macro:
As a user of the class it is not that important.
It is some platform specific macro that is being used to help (probably) the compiler perform some operation.
As the designer of the class then you are trying to do somthing platform specific to the class and you have already done the research on what it expands into and what that expansion means.