Exporting DLL C++ Class , question about .def file - c++

I want to use implicit linking in my project , and nmake really wants a .def file . The problem is , that this is a class , and I don't know what to write in the exports section .
Could anyone point me in the right direction ?
The error message is the following :
NMAKE : U1073: don't know how to make 'DLLCLASS.def'
P.S: I'm trying to build using Windows CE Platform Builder .

If I recall correctly, you can use __declspec(dllexport) on the class, and VC++ will automatically create exports for all the symbols related to the class (constructors/destructor, methods, vtable, typeinfo, etc).
Microsoft has more information on this here.

You can always find the decorated name for the member function by using dumpbin /symbols myclass.obj
in my case
class A {
public:
A( int ){}
};
the dumpbin dump showed the symbol ??0A##QAE#H#Z (public: __thiscall A::A(int))
Putting this symbol in the .def file causes the linker to create the A::A(int) symbol in the export symbols.
BUT! as #paercebal states in his comment: the manual entry of decorated (mangled) names is a chore - error prone, and sadly enough, not guarenteed to be portable across compiler versions.

I've found the best route to be an abstract factory.
Start by defining a purely virtual base class. This is a class with no implementation, a purely virtual interface class.
You can export this virtual base "abstract interface" class, but there's no real reason to do so. When the caller uses it, they will be using it through a pointer (PImpl, or Pointer to Implementation) so all the caller knows about is a simple memory address. A Def file, while a teensy bit more work to keep up with, provides benefits beyond what __declspec(dllexport) can attain. What benefits, you ask? We'll get to that, you just wait.
Have your real class publicly inherit from the virtual base. Now create a factory method to construct your object and a "release"ish callable destructor to perform cleanup. Name these methods something like "ConstructMyClass" and "ReleaseMyClass". Please, please replace "MyClass" :-)
Those factory / release methods should take only POD types if they need any paramaters (plain-old-data: integer, char, etc.). The return type should be your virtual abstract interface base class -- or rather, a pointer to it.
IMyClass* CreateAnObjectOfTypeIMyClass();
Perhaps it's now obvious why we need the virtual base class? Since the virtual interface class has no implementation, it's essentially all POD types (sort-of) so the "datatype" of the class can be understood by most callers like Visual Basic, C or vastly different C++ compilers.
If you're sufficiently fancy, you can get around the need for a "manual release" method (sorry, had to do it). How? Manage your own resources in the class through smart-pointers and a pImpl type of architecture so when the object dies, it will clean up after itself. Doing so means your class is, in the immortal words of our saint and saviour Scott Meyers, "easy to use correctly and hard to use incorrectly" by letting the caller disregard the need to clean up. Let those among us who have never forgotten to call ".close" cast the first stone.
Maybe this architecture sounds familiar? It should, it's basically a micromachine version of COM. Well, sort-of, at least the concept for interface, factory construction and release.
In the end you've exported the interface for your class, made (and exported) Create and Destroy methods, and now callers can invoke your PleaseConstructMyClass factory function to have your DLL return a fully constructed, fully implemented and fully baked object under the guise of its interface. They can call down to all the public methods of your class (at least the ones in your abstract virtual interface) and do all the fun stuff.
When they are finished with the object which was returned by the factory function, then they can call a "ReleaseMyClass" function to ask your DLL to clean up the object's resources, or you can help them along by making your class clean up itself, making the "ReleaseMyClass" method redundant and useless.
If anyone's interested in the specific gains & tradeoffs for using the Def file and the interface (besides my blind say-so), please pipe up and we can dig deeper.
Don't you just love this stuff?

The solution is the following :
since a class is exported,you also need to add the exported methods in the .def file
I didn't find out how to export a constructor , so I went with using a factory method ( static ) , which will return new instances of an object
the other functions will be exported by adding normal exporting declaration in the .def file
Hope someone will benefit from this information .

Related

Double Dreadful Diamond Inheritance issue (alternative solutions allowed)

I ended up in a situation lined out below.
I have one library that is pure CPP without external libraries, and another project that is an SDK to interface with an external library.
"I" in front of the name indicates an abstract class. Arrows indicate inheritance.
I have IDevice which contains HandleInput(data) as a callback, and StartDevice().
Then I have a more specific type of device: ISmartwatch (containing StartTimer), and from that inherits a more specific version SmartwatchV1, which implements HandleInput(data) according to its needs.
That all seemed great until I came to the external SDK part, where the library expects me to use inheritance to interface with it to override some functions. So, I have to inherit from the external library, and from my own CPP library, to override the functions I need. Most of these library overrides suit any device (IExternalLibDevice), but a few are specific to the exact Stopwatch version (ExternallSmartWatchV1).
Then for polymorphism in my SDK, I would like to call and override functions both provided by the library and my own device example: libDevice.StartDevice() and use library calls within this optionally overriden StartDevice. Or stopWatch.StartTimer(), stopwatchV1.libraryOverride().
The object which I need to create is the green one, however, the white SmartWatchV1 is also an object to instantiate in applications without the library. (And obviously I keep in mind any future alternative devices or stopwatch versions.)
I think if I drop any inheritance arrow, I would either lose out on polymorphism (so SDK code will only work for a very specific smartwatch version), or I cannot override functions I need anymore. Composition would be nice, but won't work for overriding functions, or is there an option I don't know about?
And so, I ended up here. I am encountering quite some annoying errors implementing this, since double diamond is usually solved with virtual inheritance (nice page about double diamond: https://isocpp.org/wiki/faq/multiple-inheritance#mi-diamond). However, when applied here (see the v's that indicate "virtual" in the image), I have one inheritance that should both be virtual and not be virtual. Additionally, virtual inheritance makes constructors really annoying in my generic CPP library. Even without virtual (which as far as I'm aware would cause some duplication of classes in memory and a lot of ambiguity to solve), I have some constructor errors ("no suitable default constructor" for a class that must not have a default constructor, etc) issues.
I have been battling to solve this for a long time, and I hope someone more experienced can make a suggestion that provides a better solution for my code structure or issue.
In the end, I solved it by using composition:
Add an IDevice pointer to IExternalLibDevice that is set in the constructor.
In IExternalLibSmartwatch: add an ISmartwatch pointer to the constructor and pass it to its parent constructor. Also, add a function that retrieves the IDevice pointer as an ISmartwatch.
In ExternalSmartwatchV1: also add a SmartwatchV1 to the constructor and pass it to its parent constructor, and create a function that retrieves the IDevice pointer as a SmartwatchV1.
The IDevice pointer holds the reference to the cppLibDevice, and can now be cast to any of the subclasses it belongs to. Downside: I cannot override the cpp lib classes, but it was not a hard requirement for my code, since I created alternative functions in the ExternalLib classes that can optionally call the cppLibDevice functions, or completely replace them.

C++ Class References

Coming from Delphi, I'm used to using class references (metaclasses) like this:
type
TClass = class of TForm;
var
x: TClass;
f: TForm;
begin
x := TForm;
f := x.Create();
f.ShowModal();
f.Free;
end;
Actually, every class X derived from TObject have a method called ClassType that returns a TClass that can be used to create instances of X.
Is there anything like that in C++?
Metaclasses do not exist in C++. Part of why is because metaclasses require virtual constructors and most-derived-to-base creation order, which are two things C++ does not have, but Delphi does.
However, in C++Builder specifically, there is limited support for Delphi metaclasses. The C++ compiler has a __classid() and __typeinfo() extension for retrieving a Delphi-compatible TMetaClass* pointer for any class derived from TObject. That pointer can be passed as-is to Delphi code (you can use Delphi .pas files in a C++Builder project).
The TApplication::CreateForm() method is implemented in Delphi and has a TMetaClass* parameter in C++ (despite its name, it can actually instantiate any class that derives from TComponent, if you do not mind the TApplication object being assigned as the Owner), for example:
TForm *f;
Application->CreateForm(__classid(TForm), &f);
f->ShowModal();
delete f;
Or you can write your own custom Delphi code if you need more control over the constructor call:
unit CreateAFormUnit;
interface
uses
Classes, Forms;
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
implementation
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
begin
Result := AClass.Create(AOwner);
end;
end.
#include "CreateAFormUnit.hpp"
TForm *f = CreateAForm(__classid(TForm), SomeOwner);
f->ShowModal();
delete f;
Apparently modern Delphi supports metaclasses in much the same way as original Smalltalk.
There is nothing like that in C++.
One main problem with emulating that feature in C++, having run-time dynamic assignment of values that represent type, and being able to create instances from such values, is that in C++ it's necessary to statically know the constructors of a type in order to instantiate.
Probably you can achieve much of the same high-level goal by using C++ static polymorphism, which includes function overloading and the template mechanism, instead of extreme runtime polymorphism with metaclasses.
However, one way to emulate the effect with C++, is to use cloneable exemplar-objects, and/or almost the same idea, polymorphic object factory objects. The former is quite unusual, the latter can be encountered now and then (mostly the difference is where the parameterization occurs: with the examplar-object it's that object's state, while with the object factory it's arguments to the creation function). Personally I would stay away from that, because C++ is designed for static typing, and this idea is about cajoling C++ into emulating a language with very different characteristics and programming style etc.
Type information does not exist at runtime with C++. (Except when enabling RTTI but it is still different than what you need)
A common idiom is to create a virtual clone() method that obviously clones the object which is usually in some prototypical state. It is similar to a constructor, but the concrete type is resolved at runtime.
class Object
{
public:
virtual Object* clone() const = 0;
};
If you don't mind spending some time examining foreign sources, you can take a look at how a project does it: https://github.com/rheit/zdoom/blob/master/src/dobjtype.h (note: this is a quite big and evolving source port of Doom, so be advised even just reading will take quite some time). Look at PClass and related types. I don't know what is done here exactly, but from my limited knowledge they construct a structure with necessary metatable for each class and use some preprocessor magic in form of defines for readability (or something else). Their approach allows seamlessly create usual C++ classes, but adds support for PClass::FindClass("SomeClass") to get the class reference and use that as needed, for example to create an instance of the class. It also can check inheritance, create new classes on the fly and replace classes by others, i. e. you can replace CDoesntWorksUnderWinXP by CWorksEverywhere (as an example, they use it differently of course). I had a quick research back then, their approach isn't exceptional, it was explained on some sites but since I had only so much interest I don't remember details.

Is it safe to use strings as private data members in a class used across a DLL boundry?

My understanding is that exposing functions that take or return stl containers (such as std::string) across DLL boundaries can cause problems due to differences in STL implementations of those containers in the 2 binaries. But is it safe to export a class like:
class Customer
{
public:
wchar_t * getName() const;
private:
wstring mName;
};
Without some sort of hack, mName is not going to be usable by the executable, so it won't be able to execute methods on mName, nor construct/destruct this object.
My gut feeling is "don't do this, it's unsafe", but I can't figure out a good reason.
It is not a problem. Because it is trumped by the bigger problem, you cannot create an object of that class in code that lives in a module other than the one that contains the code for the class. Code in another module cannot accurately know the required object size, their implementation of the std::string class may well be different. Which, as declared, also affects the size of the Customer object. Even the same compiler cannot guarantee this, mixing optimized and debugging builds of these modules for example. Albeit that this is usually pretty easy to avoid.
So you must create a class factory for Customer objects, a factory that lives in that same module. Which then automatically implies that any code that touches the "mName" member also lives in the same module. And is therefore safe.
Next step then is to not expose Customer at all but expose an pure abstract base class (aka interface). Now you can prevent the client code from creating an instance of Customer and shoot their leg off. And you'll trivially hide the std::string as well. Interface-based programming techniques are common in module interop scenarios. Also the approach taken by COM.
As long as the allocator of instances of the class and deallocator are of the same settings, you should be ok, but you are right to avoid this.
Differences between the .exe and .dll as far as debug/release, code generation (Multi-threaded DLL vs. Single threaded) could cause problems in some scenarios.
I would recommend using abstract classes in the DLL interface with creation and deletion done solely inside the DLL.
Interfaces like:
class A {
protected:
virtual ~A() {}
public:
virtual void func() = 0;
};
//exported create/delete functions
A* create_A();
void destroy_A(A*);
DLL Implementation like:
class A_Impl : public A{
public:
~A_Impl() {}
void func() { do_something(); }
}
A* create_A() { return new A_Impl; }
void destroy_A(A* a) {
A_Impl* ai=static_cast<A_Impl*>(a);
delete ai;
}
Should be ok.
Even if your class has no data members, you cannot expect it to be usable from code compiled with a different compiler. There is no common ABI for C++ classes. You can expect differences in name mangling just for starters.
If you are prepared to constrain clients to use the same compiler as you, or provide source to allow clients to compile your code with their compiler, then you can do pretty much anything across your interface. Otherwise you should stick to C style interfaces.
If you want to provide an object oriented interface in a DLL that is truly safe, I would suggest building it on top of the COM object model. That's what it was designed for.
Any other attempt to share classes between code that is compiled by different compilers has the potential to fail. You may be able to get something that seems to work most of the time, but it can't be guaraneteed to work.
The chances are that at some point you're going to be relying on undefined behaviour in terms of calling conventions or class structure or memory allocation.
The C++ standard does not say anything about the ABI provided by implementations. Even on a single platform changing the compiler options may change binary layout or function interfaces.
Thus to ensure that standard types can be used across DLL boundaries it is your responsibility to ensure that either:
Resource Acquisition/Release for standard types is done by the same DLL. (Note: you can have multiple crt's in a process but a resource acquired by crt1.DLL must be released by crt1.DLL.)
This is not specific to C++. In C for example malloc/free, fopen/fclose call pairs must each go to a single C runtime.
This can be done by either of the below:
By explicitly exporting acquisition/release functions ( Photon's answer ). In this case you are forced to use a factory pattern and abstract types.Basically COM or a COM-clone
Forcing a group of DLL's to link against the same dynamic CRT. In this case you can safely export any kind of functions/classes.
There are also two "potential bug" (among others) you must take care, since they are related to what is "under" the language.
The first is that std::strng is a template, and hence it is instantiated in every translation unit. If they are all linked to a same module (exe or dll) the linker will resolve same functions as same code, and eventually inconsistent code (same function with different body) is treated as error.
But if they are linked to different module (and exe and a dll) there is nothing (compiler and linker) in common. So -depending on how the module where compiled- you may have different implementation of a same class with different member and memory layout (for example one may have some debugging or profiling added features the other has not). Accessing an object created on one side with methods compiled on the other side, if you have no other way to grant implementation consistency, may end in tears.
The second problem (more subtle) relates to allocation/deallocaion of memory: because of the way windows works, every module can have a distinct heap. But the standard C++ does not specify how new and delete take care about which heap an object comes from. And if the string buffer is allocated on one module, than moved to a string instance on another module, you risk (upon destruction) to give the memory back to the wrong heap (it depends on how new/delete and malloc/free are implemented respect to HeapAlloc/HeapFree: this merely relates to the level of "awarness" the STL implementation have respect to the underlying OS. The operation is not itself destructive -the operation just fails- but it leaks the origin's heap).
All that said, it is not impossible to pass a container. It is just up to you to grant a consistent implementation between the sides, since the compiler and linker have no way to cross check.

C++ DLL plugin interface

I'm planning on doing a C++ plugin interface ala How to create some class from dll(constructor in dll)?(с++)
but concerns have been raised that if the interface is used to create DLLs via MinGW or Borland and the DLL loader is compiled with MSVC++, there might be problems. Since the only exported function is declared extern "C" I fail to see why it would not work ?
Ideas ?
If you want to be compatible across compilers (and Release / Debug) and use C++, you need a little more effort.
Basically - you are allowed to pass basic datatypes, and pointer to pure virtual classes. These classes must not contain any data member, their destructor must not be public and they should not have overloaded functions.
Memory must not be allocated in one dll and released in another. This means no exceptions and you need some kind of reference counting or returning mechanism.
All methods inside pure virtual class (aka "Interface") must be marked with a call convention (I'd prefer stdcall).
Dynamic casts are not possible as well, so you might need some functionality in all your interfaces to do the trick (like QueryInterface in COM).
This works because most compiler on win32 try to be COM compatible and solve the same problems in a COM compatible way. For getting the first interface, you need a plain C function that is exported from the dll.
If you just use C functions and C data types, everything will work as well. But then you are limited to C without classes & inheritance.
I hope that helps.
Name mangling is not a problem:
1st: if you use C functions with C data types, everything is defined, there's no name mangling (exception: in VS with STDCALL, you need to remap the name to the "normal" C name via Linker directive)
2nd: Methods inside classes are not exported and thus not mangled. You call methods via pointer to pure virtual classes (aka "Interfaces"). This uses an offset and no name. You still can't use the destructor, as the position of the destructor inside the vtbl is not fixed as far as I know.
If you pass structs to functions / methods, be sure to fix the alignment. It is not defined across different compilers.
An idea could be using standard extern C function to create a ClassFactory. Have some convenction about a fixed ( or more ) entry point the dll must expose to be a valid plugin.

Using C++ DLLs with different compiler versions

This question is related to "How to make consistent dll binaries across VS versions ?"
We have applications and DLLs built
with VC6 and a new application built
with VC9. The VC9-app has to use
DLLs compiled with VC6, most of
which are written in C and one in
C++.
The C++ lib is problematic due to
name decoration/mangling issues.
Compiling everything with VC9 is
currently not an option as there
appear to be some side effects.
Resolving these would be quite time
consuming.
I can modify the C++ library, however it must be compiled with VC6.
The C++ lib is essentially an OO-wrapper for another C library. The VC9-app uses some static functions as well as some non-static.
While the static functions can be handled with something like
// Header file
class DLL_API Foo
{
int init();
}
extern "C"
{
int DLL_API Foo_init();
}
// Implementation file
int Foo_init()
{
return Foo::init();
}
it's not that easy with the non-static methods.
As I understand it, Chris Becke's suggestion of using a COM-like interface won't help me because the interface member names will still be decorated and thus inaccessible from a binary created with a different compiler. Am I right there?
Would the only solution be to write a C-style DLL interface using handlers to the objects or am I missing something?
In that case, I guess, I would probably have less effort with directly using the wrapped C-library.
The biggest problem to consider when using a DLL compiled with a different C++ compiler than the calling EXE is memory allocation and object lifetime.
I'm assuming that you can get past the name mangling (and calling convention), which isn't difficult if you use a compiler with compatible mangling (I think VC6 is broadly compatible with VS2008), or if you use extern "C".
Where you'll run into problems is when you allocate something using new (or malloc) from the DLL, and then you return this to the caller. The caller's delete (or free) will attempt to free the object from a different heap. This will go horribly wrong.
You can either do a COM-style IFoo::Release thing, or a MyDllFree() thing. Both of these, because they call back into the DLL, will use the correct implementation of delete (or free()), so they'll delete the correct object.
Or, you can make sure that you use LocalAlloc (for example), so that the EXE and the DLL are using the same heap.
Interface member names will not be decorated -- they're just offsets in a vtable. You can define an interface (using a C struct, rather than a COM "interface") in a header file, thusly:
struct IFoo {
int Init() = 0;
};
Then, you can export a function from the DLL, with no mangling:
class CFoo : public IFoo { /* ... */ };
extern "C" IFoo * __stdcall GetFoo() { return new CFoo(); }
This will work fine, provided that you're using a compiler that generates compatible vtables. Microsoft C++ has generated the same format vtable since (at least, I think) MSVC6.1 for DOS, where the vtable is a simple list of pointers to functions (with thunking in the multiple-inheritance case). GNU C++ (if I recall correctly) generates vtables with function pointers and relative offsets. These are not compatible with each other.
Well, I think Chris Becke's suggestion is just fine. I would not use Roger's first solution, which uses an interface in name only and, as he mentions, can run into problems of incompatible compiler-handling of abstract classes and virtual methods. Roger points to the attractive COM-consistent case in his follow-on.
The pain point: You need to learn to make COM interface requests and deal properly with IUnknown, relying on at least IUnknown:AddRef and IUnknown:Release. If the implementations of interfaces can support more than one interface or if methods can also return interfaces, you may also need to become comfortable with IUnknown:QueryInterface.
Here's the key idea. All of the programs that use the implementation of the interface (but don't implement it) use a common #include "*.h" file that defines the interface as a struct (C) or a C/C++ class (VC++) or struct (non VC++ but C++). The *.h file automatically adapts appropriately depending on whether you are compiling a C Language program or a C++ language program. You don't have to know about that part simply to use the *.h file. What the *.h file does is define the Interface struct or type, lets say, IFoo, with its virtual member functions (and only functions, no direct visibility to data members in this approach).
The header file is constructed to honor the COM binary standard in a way that works for C and that works for C++ regardless of the C++ compiler that is used. (The Java JNI folk figured this one out.) This means that it works between separately-compiled modules of any origin so long as a struct consisting entirely of function-entry pointers (a vtable) is mapped to memory the same by all of them (so they have to be all x86 32-bit, or all x64, for example).
In the DLL that implements the the COM interface via a wrapper class of some sort, you only need a factory entry point. Something like an
extern "C" HRESULT MkIFooImplementation(void **ppv);
which returns an HRESULT (you'll need to learn about those too) and will also return a *pv in a location you provide for receiving the IFoo interface pointer. (I am skimming and there are more careful details that you'll need here. Don't trust my syntax) The actual function stereotype that you use for this is also declared in the *.h file.
The point is that the factory entry, which is always an undecorated extern "C" does all of the necessary wrapper class creation and then delivers an Ifoo interface pointer to the location that you specify. This means that all memory management for creation of the class, and all memory management for finalizing it, etc., will happen in the DLL where you build the wrapper. This is the only place where you have to deal with those details.
When you get an OK result from the factory function, you have been issued an interface pointer and it has already been reserved for you (there is an implicit IFoo:Addref operation already performed on behalf of the interface pointer you were delivered).
When you are done with the interface, you release it with a call on the IFoo:Release method of the interface. It is the final release implementation (in case you made more AddRef'd copies) that will tear down the class and its interface support in the factory DLL. This is what gets you correct reliance on a consistent dynamic stoorage allocation and release behind the interface, whether or not the DLL containing the factory function uses the same libraries as the calling code.
You should probably implement IUnknown:QueryInterface (as method IFoo:QueryInterface) too, even if it always fails. If you want to be more sophisticated with using the COM binary interface model as you have more experience, you can learn to provide full QueryInterface implementations.
This is probably too much information, but I wanted to point out that a lot of the problems you are facing about heterogeneous implementations of DLLs are resolved in the definition of the COM binary interface and even if you don't need all of it, the fact that it provides worked solutions is valuable. In my experience, once you get the hang of this, you will never forget how powerful this can be in C++ and C++ interop situations.
I haven't sketched the resources you might need to consult for examples and what you have to learn in order to make *.h files and to actually implement factory-function wrappers of the libraries you want to share. If you want to dig deeper, holler.
There are other things you need to consider too, such as which run-times are being used by the various libraries. If no objects are being shared that's fine, but that seems quite unlikely at first glance.
Chris Becker's suggestions are pretty accurate - using an actual COM interface may help you get the binary compatibility you need. Your mileage may vary :)
not fun, man. you are in for a lot of frustration, you should probably give this:
Would the only solution be to write a
C-style DLL interface using handlers
to the objects or am I missing
something? In that case, I guess, I
would probably have less effort with
directly using the wrapped C-library.
a really close look. good luck.