I am using Visual Studio and am working on some C++ code that works like this in class A:
class A
{
public:
//......
static void foo();
};
class B is exported:
class __declspec(dllexport) B
{
public:
//...
void bar()
{
A::foo();
}
};
A and B are compiled to AB.dll (and AB.lib).
Now the main program:
int main()
{
B b;
b.bar();
return 0;
}
When compiling the main program and linking it to AB.lib,
it complains about the A::foo() as unresolved external symbol
(in this case A::foo is a static function).
Do I need to somehow export A::foo() or could it be that
I introduce errors somewhere? Any help is appreciated.
Modified:
1) Sorry for the type, it should be dllexport, not dllimport
2) in my actual project, the implementation is in .cpp files. They are not inline functions.
Thanks.
I assume code showed is in your .h header file, then when you header file says:
class __declspec(dllimport) B
{
public:
//...
void bar()
{
A::foo();
}
};
First: you say B class is IMPORTED, it works for your main app, but not works for your dll.
Second: B::bar() IS NOT IMPORTED FROM dll, instead IS DIRECTLY IMPLEMENTED IN YOUR MAIN APP (compiler is readding directly in your header file, and it is not trying to import from dll)
Recomendations:
FIRST: redefine your header file like this:
class __declspec(dllimport) B
{
public:
//...
void bar();
};
And implement method B::bar in a cpp file in dll project
SECOND: remove class A from your header file (if you can)
Related
I encountered a strange behavior for an msvc c++ build while compiling two shared libraries and an executable. The complete setup can be found on GitHub
Information:
platform toolset is v143
4 projects: 1 header only, 2 DLL`s, 1 executable
The 4 projects are:
HeaderOnlyInterface (header only)
Implementation (DLL)
Factory (DLL)
SharedLibsTest (EXE)
Projects 2 - 4 can include all header files from HeaderOnlyInterface.
HeaderOnlyInterface consists of two header files:
DLLExport.h
#pragma once
#ifdef MAKEDLL
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __declspec(dllimport)
#endif
IFoo.h
#pragma once
#include "DLLExport.h"
class EXPORT IFoo
{
public:
virtual ~IFoo() = 0 {}
virtual void Bar() = 0;
};
The next project is Implementation which implements the defined abstract class. This class has MAKEDLL defined as PREPROCESSOR macro. I only show the header because the source is unnecessary:
Foo.h
#pragma once
#include <IFoo.h>
class EXPORT Foo : public IFoo
{
public:
void Bar() override;
};
Going on to Factory, which also defines MAKEDLL and links against Implementation.lib, I have these two files:
FooFactory.h
#pragma once
#include <IFoo.h>
class EXPORT FooFactory
{
public:
static IFoo* Create();
};
FooFactory.cpp
#include "FooFactory.h"
#include <Foo.h>
IFoo* FooFactory::Create()
{
return new Foo();
}
And at the last, I have a main method in an Executable, which links against Factory.lib:
#include <FooFactory.h>
int main()
{
auto* foo = FooFactory::Create();
foo->Bar();
delete foo;
}
For me, the strange thing is, that everything compiles and works fine until now. I have no compile or linker warnings.
The strange thing for me is the compilation and linkage of Factory.lib (and NOT against Implementation.lib).
This library imports a class and exports it also and I do not know why it works. I try to explain my thinking by providing in (pseudo-) code what happens if FooFactory.cpp is pre-processed:
class __declspec(dllexport) IFoo
{
public:
virtual ~IFoo() = 0 {}
virtual void Bar() = 0;
};
class __declspec(dllexport) FooFactory
{
public:
static IFoo* Create();
};
class __declspec(dllexport) Foo : public IFoo
{
public:
void Bar() override;
};
IFoo* FooFactory::Create()
{
return new Foo();
}
The macro is the same for all compiled libs meaning that Factory.lib is exporting all classes. But it does not compile the implementation of Foo::Bar(). Also, it is somehow able to import the implementation because the code works fine. I am not sure why it works, and what really happens under the hood.
If someone could lighten me up on this behavior and also maybe could explain why I should do it not like this or maybe why this is a good idea to do it like this, that would be really helpful.
Thanks!
I got a weird C++ question and have no idea how to resolve it.
I have a public header:
// a.h
#ifdef A_EXPORTS
#define A_API __declspec(dllexport)
#else
#define A_API __declspec(dllimport)
#endif
struct A_API IWorker
{
virtual bool foo() { return false; }
};
I built a.DLL with -DA_EXPORTS.
But my test.exe just needs a mocked IWorker.
// test.cpp
#include "a.h"
class CMockWorker : public IWorker
{
public:
bool foo() override { return true; }
};
I built test.exe, and found it depends on a.DLL because of external symbol public: __cdecl IWorker::IWorker(void) __ptr64
I know that IWorker has a compiler-generated constructor because of the vtbl, but could it be inline so we can get rid of a.DLL?
Thanks!
As #hans-passant mentioned, yes, once I removed the definition of virtual methods, problem resolved.
// a.h
struct IWorker
{
virtual bool foo() = 0;
};
But in existing project, some so-called interface class has similar dummy body and hard to refactor them.
So I really want to find the ideal solution to force-inline the c'tor, if has. Maybe not today, hope it could be impl-ed in the future.
If I'm creating a static library with a header file such as this:
// Myfile.h
#include "SomeHeaderFile.h" // External library
Class MyClass
{
// My code
};
Within my own project I can tell the compiler (in my case, Visual Studio) where to look for SomeHeaderFile.h. However, I don't want my users to be concerned with this - they should be able to include my header without having to inform their compiler about the location of SomeHeaderFile.h.
How is this type of situation normally handled?
This is a classic "compilation firewall" scenario. There are two simple solutions to do:
Forward-declare any classes or functions that you need from the external library. And then include the external library's header file only within your cpp file (when you actually need to use the classes or functions that you forward-declared in your header).
Use the PImpl idiom (or Cheshire Cat) where you forward-declare an "implementation" class that you declare and define only privately (in the cpp file). You use that private class to put all the external-library-dependent code to avoid having any traces of it in your public class (the one declared in your header file).
Here is an example using the first option:
#ifndef MY_LIB_MY_HEADER_H
#define MY_LIB_MY_HEADER_H
class some_external_class; // forward-declare external dependency.
class my_class {
public:
// ...
void someFunction(some_external_class& aRef); // declare members using the forward-declared incomplete type.
};
#endif
// in the cpp file:
#include "my_header.h"
#include "some_external_header.h"
void my_class::someFunction(some_external_class& aRef) {
// here, you can use all that you want from some_external_class.
};
Here is an example of option 2:
#ifndef MY_LIB_MY_HEADER_H
#define MY_LIB_MY_HEADER_H
class my_class_impl; // forward-declare private "implementation" class.
class my_class {
private:
std::unique_ptr<my_class_impl> pimpl; // a vanishing facade...
public:
// ...
};
#endif
// in the cpp file:
#include "my_header.h"
#include "some_external_header.h"
class my_class_impl {
private:
some_external_class obj;
// ...
public:
// some functions ...
};
my_class::my_class() : pimpl(new my_class_impl()) { };
Say the external header file contains the following:
external.h
class foo
{
public:
foo();
};
And in your library you use foo:
myheader.h:
#include "external.h"
class bar
{
...
private:
foo* _x;
};
To get your code to compile, all you have to do is to forward declare the foo class (after that you can remove the include):
class foo;
class bar
{
...
private:
foo* _x;
};
You would then have to include external.h in your source file.
I have a base interface class:
class A
{
public:
ITask(){}
virtual bool Start()=0;
virtual void Update()=0;
virtual void Stop()=0;
};
I now have 2 other classes, that inherit from this
#include "A.h"
#include "C.h"
class B: public A
{
public:
bool Start(){}
void Update()
{
c.Start();
}
void Stop(){}
static bool m_run;
static void SetRun(bool run)
{
m_run = run;
}
private:
C c;
};
lastly I have a 3rd class:
#include "A.h"
#include "B.h"
class C : public A
{
public:
bool Start()
{
B::SetRun(false); // cant do this
B::m_run = false; // or this
}
void Update()
{
}
void Stop()
{
}
}
I have shaved down some of the code, for simplicity.
I dont understand why I cant access the static var in B. Do I need to make it a pointer or a ref?
I get 2 errors:
error C2653: 'B' : is not a class or namespace name
error C3861: 'm_run': identifier not found
Although you don't show it, I'm assuming that B.h includes C.h; otherwise the line C c; won't compile. This causes a circular dependency in the header files: B.h must be included before C.h, which must be included before B.h, which is impossible.
The easiest solution is to move the body of C::Start out of the definition of C, so that C.h does not need to include B.h. The function definition can go into a source file, or a separate header if you want to keep it inline.
Alternatively, you could modify B to contain a std::unique_ptr<C> rather than an instance of C, and implement a constructor (in a source file, or a separate header) that initialises it with new C. Then B.h only needs to forward declare class C; rather than including C.h.
A better solution, if possible, would be to rethink the relationships between the classes so that there isn't a circular dependency.
(UPDATE: while I was writing this answer, the question changed to show that B.h does indeed include C.h as I guessed.)
There is nothing wrong with your example code (after the edits), the problem must be somewhere else, like a failed include.
Is there a way in C++ to create an anonymous namespace, and only export a single function out of it?
I want something like:
namespace {
void Bar() {}
void Foo() { Bar(); }
}
Now, I want to somehow access to Foo() yet make sure there's no way to touch Bar()
Thanks!
If you want to export the function, you'll have to put it outside the anonymous namespace.
namespace {
void Bar() {};
};
void Foo() { Bar(); };
Since you want Foo() to have external linkage, you should declare it in a header file:
#ifndef FOO_H
#define FOO_H
void Foo();
#endif
Now everyone can see and call Foo()
But in Foo.cpp:
#include "Foo.h"
namespace {
void Bar(){ }
}
void Foo(){ Bar(); }
Now, as long as you control the source file Foo.cpp, no one can change access to Bar()
You could place them in different header files and make sure clients only get the header file that declares Foo(). However, you cannot implement Foo() inline with that solution.
why not
namespace {
void Bar() {};
};
void Foo() { Bar(); };
?
an anonymous namespace is accessible from the file you created it in
Define Bar as a global static function in the CPP file that contains the function body for Foo.
Edit: Its worth noting that this will only cause a link time error.
Edit2: And I ran a quick test and it seems you can't extern to an anonymous namespace.
Edit3:
Something like this would seem sensible (and lose the namespace)
static void Bar()
{
}
void Foo()
{
Bar();
}
You can now "extern void Foo();" but if you try the same with Bar then the linker will fail as Bar no longer has external linkage.