I am trying to create a templated factory class that exports a create method:
template <typename T>
class ClassFactory
{
_declspec(dllexport) static void* Create()
{
return new T;
}
};
class Foobar : ClassFactory<Foobar>
{
std::string foo;
};
This code compiles just fine, but I don't see anything in the exports table when I look at the output of dumpbin /exports
The following code exports Create() correctly:
class ClassFactoryBase
{
_declspec(dllexport) virtual void* Create() = 0;
};
template <typename T>
class ClassFactory : ClassFactoryBase
{
void* Create()
{
return new T;
}
};
class Foobar : ClassFactory<Foobar>
{
std::string foo;
};
However, I need Create() to be static. Why does sample 2 work, while sample 1 does not? Is there a way to export a static template method?
The compiler sees that the Create() function is never called so it does not generate any code for it. To make it work you need to explicitly instantiate your template like this:
template class ClassFactory<Foobar>;
Just add this line to your source. Now the compiler will generate the code for this function and export it. For more information see this MSDN article - Explicit Instantiation (C++)
To answer your other question why the example 2 works and example 1 does not, let's take a closer look at the derived class Foobar. There is a virtual function in this class so the compiler has to generate a vtable. To fill in the vtable the compiler needs to know the address of Create() and this is when it is implicitly instantiated from the base class template. The code for this function is generated and exported to the DLL, as requested. That is why the example 2 works.
There is no way to export a template method from the DLL, because non-instanced template method is not even compiled. Your examples doesn't do much with the DLL itself, the header file is the one, who makes everything work.
Related
I want to give a static member another name, so it can be linked in a vector table which is elsewhere predefined. The idea is simply to call my static method from the vector table. This works quite well with static methods from non templated class if the declaration and definition is divided.
But I want to have a templated class, so I have no idea how I can write that.
Q1: Why asm("name") did not work for definitions? Any tricks here?
Q2: How can I write a templated definition of a static class method? The problem is that I have no call from my source to it, because it should only be linked in a vector table. Also I have no knowledge at this place with which parameter it will be instantiated.
//non templated variant
class Bla
{
public:
// with attributes it seems to work
void f1() __attribute__((deprecated))
{
}
void f2() __asm__("__newName_f2"); // works
// compiles without error or warning, but no renaming happens!
void f3() __asm__("__newName_f3") __attribute__(( __used__, __externally_visible__)) {}
};
void Bla::f2() {} // definition for renamed function, OK works!
template <typename T>
class Blub
{
void b1() __asm__("__blub_b1") ;
};
// How to write a templated method?
// The instance must be visible without a call,
// because it should be linked in a vector table
template <typename T>
void Blub<T>::b1() {}
int main()
{
Bla bla;
Blub<int> blub;
}
I'm trying to build a wrapper around a managed class so I can call it from native code.
Here is the managed function :
void MyManagedFunction(MyStruct iStruct)
{
// Code according to what are the types of the 2 MyStruct members
}
struct MyStruct
{
public MyStruct(Object iValue1, Object iValue2) : this()
{
Value1 = iValue1; // Often contains DateTime::Now
Value2 = iValue2;
}
public Object Value1;
public Object Value2;
}
In my case, Value1 will almost always be System::DateTime::Now and the Value2 will almost always be a common data type (int, double, float, string, bool). I thought of making two templated function in the wrapper.
In the wrapper's .h I have the following :
#ifdef MYWRAPPER_EXPORTS
# define MYWRAPPER __declspec(dllexport)
#else
# define MYWRAPPER __declspec(dllimport)
#endif
class MYWRAPPER MyWrapper
{
public:
MyWrapper();
~MyWrapper();
template <class T> void MyNativeFunction(T iParam1)
{
MyStruct^ wStruct = gcnew MyStruct(System::DateTime::Now, iParam1);
//The class containing the managed function is a singleton
MyManagedClass::Instance->MyManagedFunction(wStruct);
}
template <class T, class W> void MyNativeFunction(T iParam1, W iParam2)
{
MyStruct^ wStruct = gcnew MyStruct(iParam1, iParam2);
//The class containing the managed function is a singleton
MyManagedClass::Instance->MyManagedFunction(wStruct);
}
};
This wrapper compiled without problem. The problem obviously occurred when I included the .h in the purely native code. Since I can't hide the content of the templated function, I have managed stuff visible on the native side which prevent the native code from compiling.
I was wondering if there was a workaround in order to achieve this. I don't mind if I'm limited into using only primitive types as parameters for the function. The best thing is if I was able to simply hide the content of the templated function in the native code so it only knows about the signature
Here's what I've tried/considered so far :
Converting the parameters to void* and call a function in which would call the managed one. By doing so, I can't cast the void* back to an object since I lose its type and using typeid to get the 'T' or 'W' type doesn't help since it vary from a compiler to another.
Overloading the function for every types I want to use. This is what I'll most likely use if I doesn't find a better solution. The problem is it means alot of overloading (especially for the 2 parameters function considering the number of combination)
If you know all the types your template will take, you can force instantiate it with those variables and thus put the code for the template functions in the source file instead of a header.
You can look at the example provided in Storing C++ template function definitions in a .CPP file
As he says you can do as below (copy-paste alert):
.h file
class foo
{
public:
template <typename T>
void do(const T& t);
};
.cpp file
template <typename T>
void foo::do(const T& t)
{
// Do something with t
}
template void foo::do<int>(const int&);
template void foo::do<std::string>(const std::string&);
Suppose I have such a template class:
template <class T>
class Queue
{
public:
static int Size;
};
template <class T> int Queue<T>::Size = 0;
And I export a function in D.dll use Queue as an parameter:
void ChangeQueueSize(Queue<int>& q)
{
q.Size = 100;
}
And then I use this exported function in an A.exe:
Queue<int> q;
q.Size = 10;
ChangeQueueSize(q);
int updatedSize = q.Size;
Since the Queue class is generated from the class template in 2 projects, there are actually 2 copies of the code, as well as the static data member.
So calling ChangeQueueSize won't really change queue size here, it just update another class's static member, which happens to be have the same class name.
What can we do to solve this problem?
Is weak symbol in gcc capable of address this?
Thanks so much.
You cannot put templates in a library in the way you might think. You can only put actual, instantiated class definitions in a library.
Templates are essentially a code generation tool, and you can only put generated code into the library.
You might want to use explicit template instantiation to make the compiler generate the code, and take the static member definition out of the header:
// Header, shipped to clients
template <class T>
class Queue
{
public:
static int Size;
};
// Library source code:
template <typename T> int Queue<T>::size = 0;
template class Queue<int>;
Now compile the source file into the library; this will contain the instance of the static member variable Queue<int>::size.
Note that your consumers will only be able to use instances of your class with T = int since they don't have access to the static member otherwise (i.e. they'd have to provide their own).
I hav a following piece of code in a module.
Controller is the name of the class.
allocate_route is the member function of it.
While defining the member function it is given as
template<UI num_ip>
void Controller<num_ip>::allocate_route()
{
}
UI is Unsigned Integer. num_ip is not defined any where. He also has not used num_ip anywhere inside the code. What does he tell to the compiler by this statement. Am not able to comprehend the use of templates here. Wat does this code do?
That code implements the function allocate_route defined in the template class Controller.
When creating template classes, you have two way to implement functions:
template <int a>
class A
{
void x() { ... }
};
or
template <int a>
class A
{
void x();
};
template <int a>
void A<a>::x()
{
}
Maybe he is using num_ip somewhere outside this method, but still inside Controller class (maybe another method).
If you define method inside a template you have to add template<...>, even if method doesn't use template parameters. That's why it could be better to do something like this in this case:
class Controller_base
{
void allocate_route(){
}
};
template<UI num_ip>
class Controller: public Controller_base
{
}
void Controller_base::allocate_route()
{
}
So i am trying to export somethings in a project to DLL. Anyways a few of the projects use a singleton class very heavily.
template <typename T>
class DLL_IMP VA_Singleton {
protected:
VA_Singleton () {};
~VA_Singleton () {};
public:
static T *Get(){
return (static_cast<T*> (a_singleton));
}
static void Delete(){
if(a_singleton == NULL) {
delete a_singleton;
}
}
static void Create(){
a_singleton = GetInstance();
if(a_singleton == NULL){
a_singleton = new T;
}
}
private:
static T *a_singleton;
};
template <typename T> T *VA_Singleton<T>::a_singleton = NULL;
I got the export working fine, but when it comes to importing it states this:
template <typename T> T *VA_Singleton<T>::a_singleton = NULL;
Does not work with DLLImport. This is the first time ive ever really worked with DLL's in a work enviroment. Does anyone have any ideas?
Please see Multiple Singleton Instances
You will have to ensure that your template instantiation is done in one compilation unit, and you will have to move the pointer = NULL initialization to the CPP file. In other DLLs, you'll have to use extern templates.
Edit:
If you are stuck with getting templated singletons to work over multiple DLLs, you could also define a short wrapper function that returns your singleton instance so that the template instantiation is done in one compilation unit only.
Example:
template class Singleton<T>;
__declspec(dllexport/dllimport) T& getInstanceForMyType();
// in the cpp file:
T& getInstanceForMyType()
{
return Singleton<MyType>::getInstance();
}