I try to reorganize our project from static libs into shared libraries of the subprojects.
Well, using VS Compiler all exporting classes needs a _declspec(dllexport) and importing them needs _declspec(dllimport). Works fine. But I got troubles with all classes derived from boost members (e.g. singleton, or ptr_map).
I get the error
error C2487: 'boost::serialization::singleton::instance' :
member of dll interface class may not be declared with dll interface
Microsofts solution is not very helpful, because changing boosts code would maybe not be a good idea;)
Is it not a good idea to export boost derived classes? Does anybody know where this comes from or maybe knows howto fix?
(samplecode below)
thanks!
Here's a sample (mylib.h as shared library project named: "myLib"):
#ifndef _MY_LIB_H_
#define _MY_LIB_H_
#include <string>
#include <boost/serialization/singleton.hpp>
using boost::serialization::singleton;
#ifdef MYLIB_EXPORTS
#define PORT_DLL __declspec(dllexport)
#else
#define PORT_DLL __declspec(dllimport)
#endif
class PORT_DLL MyLib
: singleton<MyLib>
{
public:
std::string GiveMeOutput() const;
};
#endif //_MY_LIB_H_
it's implementation (myLib.cpp)
#include "myLib.h"
std::string
MyLib::GiveMeOutput() const
{
return "some output";
}
an easy main.cpp (as executable project)
#include <iostream>
#include "../myLib/myLib.h"
int main()
{
MyLib lib;
std::cout << lib.GiveMeOutput();
return 0;
}
some points:
VS2010
x64
boost 1.52
Related
l learned "include" keyword are just copy & paste.
But including cpp file makes different compile result.
(gcc6~8 + boost1.69)
// main.cpp
#include <iostream>
// I'll move next code to why.cpp
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
#include <boost/archive/iterators/remove_whitespace.hpp>
void testFunc()
{
using namespace boost::archive::iterators;
typedef transform_width<binary_from_base64<remove_whitespace<std::string::const_iterator>>, 8, 6> ItBinaryT;
std::string input;
std::string output(ItBinaryT(input.begin()), ItBinaryT(input.end()));
}
// -----------------------------
int main()
{
return 0;
}
Above code compiled without warning.
But, I replace some code with include cpp..
// main.cpp
#include <iostream>
#include "why.cpp" // <----------
int main()
{
return 0;
}
// why.cpp - just copy&paste
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
#include <boost/archive/iterators/remove_whitespace.hpp>
void testFunc()
{
using namespace boost::archive::iterators;
typedef transform_width<binary_from_base64<remove_whitespace<std::string::const_iterator>>, 8, 6> ItBinaryT;
std::string input;
std::string output(ItBinaryT(input.begin()), ItBinaryT(input.end()));
}
It makes warning [-Wsubobject-linkage]
~~ has a field ~~ whose type uses the anonymous namespace
~~ has a base ~~ whose type uses the anonymous namespace
Please look at this link : https://wandbox.org/permlink/bw53IK2ZZP5UWMGk
What makes this difference?
Your compiler treats the main CPP file specially under the assumption that things defined in it are very unlikely to have more than one definition and so some tests for possible violation of the One Definition Rule are not done inside that file. Using #include takes you outside that file.
I would suggest just not using -Wsubobject-linkage since its logic is based on a heuristic that is not applicable to your code.
I noticed that the following code compiles with g++/clang++-3.8 but not with nvcc:
#include <tuple> // not used, just to make sure that we have c++11
#include <stdio.h>
namespace a {
template<class T>
class X {
friend T;
};
}
I get the following compile error:
/usr/local/cuda-8.0/bin/nvcc -std=c++11 minimum_cuda_test.cu
nvcc warning : The 'compute_20', 'sm_20', and 'sm_21' architectures are deprecated, and may be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning).
minimum_cuda_test.cu:7:10: error: âTâ in namespace â::â does not name a type
friend T;
Interestingly, this works with nvcc:
#include <tuple> // not used, just to make sure that we have c++11
#include <stdio.h>
template<class T>
class X {
friend T;
};
Is this a bug in the compiler? I thought nvcc would internally use g++ or clang as a compiler so I am confused why this would work with my local compiler but not with nvcc.
In both cases, the code is being compiled by g++. However, when you pass a .cu file to nvcc, it puts the code through the CUDA C++ front end before passing it to the host compiler. Looking at CUDA 8 with gcc 4.8, I see that the code has been transformed from
namespace a {
template<class T>
class X {
friend T;
};
}
to
namespace a {
template< class T>
class X {
friend ::T;
};
You can see that the front end has replaced the templated friend with an equivalent, but with a prepended anonymous namespace, which is breaking the compilation. I'm not a C++ language lawyer, but this would appear to me to be a bug in the CUDA front end. I would suggest reporting it to NVIDIA.
I am trying to learn C++/CLI, with the plan of writing a DLL which will be consumed by (unmanaged) C code. However, I cannot get the most basic example to build, as is reproducible below:
I am working in Visual Studio Express 2013.
Create new project -> CLR ->class library
LearnCli.h:
extern "C" __declspec(dllexport)
int __stdcall TestFunc();
LearnCli.cpp:
#include "stdafx.h"
#include "LearnCli.h"
int __stdcall TestFunc()
{
return 3;
}
Build with no problems.
Add Project -> Win32 ->Console Application
From the context menu in solution explorer for the new console project:
Add -> reference -> LearnCli
stdafx.h
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
#include "..\LearnCli\LearnCli.h"
ConsoleApplication.cpp
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int z;
z=TestFunc();
cout << "Function returns:" << z << endl;
cin.get();
return 0;
}
intellisense has no problems, but on build:
Error 1 error LNK2019: unresolved external symbol _TestFunc#0 referenced in function _wmain [path]\Projects\LearnCli\ConsoleApplication1\ConsoleApplication1.obj ConsoleApplication1
What am I missing which is not allowing the win32 console app to find the function? Cheers.
Edit
Thanks to the comment and link, I have change the LearnCli.h file to
#ifdef LEARNCLIAPI_EXPORTS
#define LearnCliApi_DECLSPEC __declspec(dllexport)
#else
#define LearnCliApi_DECLSPEC __declspec(dllimport)
#endif
And gone to Project -> Properties -> C/C++ -> Preprocessor ->Definitions
and added LEARNCLIAPI_EXPORTS. unfortuately the error is unchanged
You need to link your application(exe) project with the .lib built from dll project.
You can add that from Project settings >> Linker >> Input files or simply put a line on your source.
i.e.
pragma(comment, "lib:<your_lib.lib>")
I have a (large) C/C++ project that consists of both C and C++ languages. At some point it turned out that there are two C functions with identical names. Those functions are defined in two different *.c files in different locations. In general at the highest level, the project is C++. This problem was questioned and answered here
However still a question "how to organize those files safely" remains. How can I group such project so that there are no name conflicts, and I can be sure that proper function is called. Will writing a wrapper for each of those functions help?
That how it looks at the moment:
A.h //first declaration of function F
A.c //first definition of function F
B.h //second declaration of function F
B.c //second definition of function F
trying to make such thing:
extern "C"{
#include "A.h"
#include "B.h"
}
causes of course name conflict. What can I do to avoid this conflct, and have the robust code? Would such solution help:
A_Wrapper.h: //c++
extern "C"{
#include "A.h"
}
void WrapF_A(int x)
{
F(x);
}
B_Wrapper.h: //C++
extern "C"{
#include "B.h"
}
void WrapF_B(int x)
{
F(x);
}
and then in the program:
#include A_Wrapper.h
#include B_Wrapper.h
Modyfing each file in that project would be rather impossible as it cosists of hundreds of files, and i would probably damage some code rather. Is there a way to make an include file seen only in some part of the program?
EDIT:
So I created a simple project illustrating the problem, and tried to apply the hints given by doctorlove. However still multiple definition of F error occurs. What should I change? Project files:
A.h:
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
int F(int x);
#endif // A_H_INCLUDED
A.c
#include "A.h"
int F(int x)
{
return x*x;
}
AWrapper.h:
#ifndef AWRAPPER_H_INCLUDED
#define AWRAPPER_H_INCLUDED
int AF(int x);
#endif // AWRAPPER_H_INCLUDED
AW.cpp:
#include "AWrapper.h"
extern "C"{
#include "A.h"
}
int AF(int x)
{
return F(x);
}
B.h:
#ifndef B_H_INCLUDED
#define B_H_INCLUDED
int F(int x);
#endif // B_H_INCLUDED
B.c:
#include "B.h"
int F(int x)
{
return -x*x;
}
BWrapper.h:
#ifndef BWRAPPER_H_INCLUDED
#define BWRAPPER_H_INCLUDED
int BF(int x);
#endif // BWRAPPER_H_INCLUDED
BW.cpp:
#include "BWrapper.h"
extern "C"{
#include "B.h"
}
int BF(int x)
{
return F(x);
}
Go with your wrapper idea, but write a facade (see also here) that exposes what you need from A, and what you need from B not all the functions in there.
You will end up with something like
//header Wrap_A.h
#ifndef WRAP_A_INCLUDED
#define WRAP_A_INCLUDED
//for some input Data left as an exercise for the reader...
double solve_with_A(Data data);
#endif
//header Wrap_B.h
#ifndef WRAP_B_INCLUDED
#define WRAP_B_INCLUDED
//for some input Data...
double solve_with_B(Data data);
#endif
Then make two cpp files that include all the conflicting headers files, those from A in A.cpp and those from B in B.cpp, so the conflicts don't happen. The solve_with_A and solve_with_B functions will then call all the things they need without without leaking them to the whole program and causing conflicts.
You might have to give some thought to what Data will actually be. You could define your own types, one for A and one for B. Just avoid exposing the implementation details in your wrapping/facade headers.
If headers are causing you pain, firewall them off in the naughty corner.
EDIT
Given you have two functions, F, if you put all the sources into one project the linker should and will complain it can see both. Instead, you need to make two static libraries, and just expose the wrapped version to your main project.
I encountered a weird problem just now.
The source code is simple and self-evident as follows:
#include <vector>
#include <iostream>
#include <functional>
using namespace std;
using namespace std::tr1;
template<class T_>
void show_size(T_ coll)
{
cout << coll.size();
}
int main()
{
vector<int> coll;
coll.push_back(1);
show_size(ref(coll));
return 0;
}
The VC++ 2010 reports:
error C2039: 'size' : is not a member of 'std::tr1::reference_wrapper<_Ty>'
As we know, reference_wrapper can automatically convert itself to its underlying type, here is vector<int>. Why is such simple code not valid?
No it can't that's the whole point of the reference wrapper, because it doesn't decay from the reference, unless explicitly requested using .get()
Edit: don't mix up the boosts reference wrapper with the standard one, the boost one actually has implicit conversion (but the target functionality is a little bit different)