Exporting class from executable to dll - c++

I need in a DLL to use a class, defined in an executable (DLL and executable are compiled by the same compiler). But I don't want the source code of this class definition to be available to DLL, only declaration.
One possible way to do it is to make all the necessary class methods to be virtual (so that DLL linker will not need these methods' definitions). The disadvantages of this approach:
I cannot create objects of exported classes
in DLL code using new (a have to
create additional functions in
executable's code).
I have to make all these methods virtual,
even if otherwise they don't need to
be virtual.
There is a way to export a class from a DLL to an executable using Microsoft's __declspec(dllexport) storage-class extended attribute.
Is there a way to export a class from executable to DLL using the same technique?
My old Borland C 6 compiler does not allow me to create import library during the build of executable project. (So, when compiling the DLL, linker gives me unresolved external error messages for all imported non-virtual class methods.) Is it a limitation of this very compiler, or maybe I'm missing something important?

So far as I know, it is ok to use MS VS's dllexport to export a class or function from a exe and use it in a DLL. and it runs cool if your DLL and Exe execute in one process.

You could put the class in a second DLL if you really didn't want it in the first one.
I'm having a hard time understanding your reasoning for not just putting the class in the DLL though.
ETA: Did some more digging and found this link that explains how to generate an import library from an EXE project in Visual Studio 2008. As for how to export them, it looks like you just use the regular __declspec(dllexport).

OK, new answer in light of new information here. If you can't generate an export library for your EXE with your compiler, and you really really have to do it this way, here's a creative, hacky and generally not recommended solution:
Step 1: Create a C wrapper API for your class, kinda like this (probably wont compile, but you get the idea):
// Yes, need some 32 bit/64 bit checks here
#define MYHANDLE unsigned int
__declspec(dllexport) MYHANDLE MyClassNewInstance() {
MyClass* ptr = new MyClass();
return (MYHANDLE)ptr;
}
__delspec(dllexport) MyClassDoSomething( MYHANDLE handle, int parm ) {
MyClass* ptr = (MyClass*)handle;
ptr->DoSomething(parm);
}
etc..
Step 2: To actually get the C functions from the EXE for use in the DLL, use the Win32 API functions GetModuleHandle() and GetProcAddress().
Step 3: Create a proxy class in your DLL. The methods in the proxy class do nothing but call their counterpart C functions from the EXE.
This would keep the "real" implementation of your class out of the DLL. It's a hack, but it would probably work.

Related

utilizing a static library to create an import library

I am interested in using my static lib to create a dll (implicitly linking). which means I need to (in vs2008)
create a dll project that should generate the following:
header file (which have export function declarations. These are simple wrappers to actual functions in the static lib using __declspec(dllexport) which are in the .cpp )
import lib which will be made as a result of creating the dll
the actual dll which is created.
I have made a test program that will utilize the above dll(including the import lib/header files) to test it.
in this I have included all the three items. now the exe compiles/links without issue.
however in the main.cpp when i call the exported functions (with the associated __declspec(dllimport) call it never seems to execute. I am uncertain why this is?
Its almost like the even though the exe can see the exported function in in the dll...the dll cannot call on the code that is in the static lib?
i just cannot answer why my exe can't see the code in the static lib? do i need an archiver/librarian for vs2008 to include all those obj files as part of the import lib?
I am at a loss and am not sure how to test this?
other than just making my static lib directly into a dll. I wanted to try this method. I know i am missing something...i have read all over the place and i am just stuck. There were some threads here that had some people posting something similar but i can't seem to get it. please be as detailed as possible as I am new to this. thanks again.
update 1:
ok so currently i added the extern line to the function prototype and now it sees the exported function from the dll. however, now the only issue left is that:
i can't invoke the function that this exported function (aka wrapper) is trying to call. which happens to be in the static library. how should my exe get visibility to that static library function. I know it can be done because I think there was one other person on this board who was able to make this work.
update 2: my setup is exactly like this questioner...
How to force inclusion of an object file in a static library when linking into executable?
but i am not using explicit linking. i am using implicit linking. my real issue is how to call a static lib function in my dll wrapper which is exported to the exe?
If the app and DLLs are MFC app/dlls, then make sure that the application and all dlls are either "Debug" versions or "release" versions and not a mix.

C++ wrapper DLLs to static LIBs

I have some statically compiled libraries (.lib) that I use in my project, which is written in C++ and built on both Windows and Linux. At my project's entry-point to these libraries, I use just one or two functions from the 'main' library in the static library suite, really (but I'm sure that these functions call many others in the other libraries in the suite).
I would ideally like to instead have a suite of dynamically linked libraries (DLLs) that wraps around each of the libs in the static lib suite; I've read/heard that the way to do this on Windows (e.g., Visual Studio 2005/2008/2010) is to "create a wrapper DLL" with some exposed functions calling the underlying static library functions. I would very much appreciate if someone can give me some detailed step-by-step including possibly some snippets, of how to go about doing this in MS Visual Studio 2005/2008/2010. I am sure some of you may already be doing this on a day-to-day basis; your experience is very much appreciated.
Edit:
For the benefit of others like myself, I am posting the first 'useful' link I found:
http://tom-shelton.net/index.php/2008/12/11/creating-a-managed-wrapper-for-a-lib-file/
"Convert a library to another library type" seems easy, but it is not. There is no straight-forward step-by-step way to do this because C++ and DLLs do not play well together at all, and your code will need to be adapted to support a DLL interface.
A concise way to describe the problem is this:
A .lib's interface is C++
A .dll's interface is C
Thus, a DLL's interface simply doesn't support C++ and you need to be clever to make it work - this is why the ambiguous existing answers.
One standard way is via COM, which means building an entire COM wrapper for the library, complete with class factory, interfaces, objects, and using BSTR instead of std::string. I would guess is not practical.
Another solution is to create a C interface for your C++ library which is DLL-safe. That means basically creating a winapi-style interface, which again is probably not practical or defeats the purpose of using your library at all. This is what #David Heffernan suggests. But what he doesn't address is how you must change your code to be DLL-compatible.
An important but subtle problem is you cannot pass ANY templated C++ objects across DLL boundaries. This means passing std::string in or out of a DLL function is considered unsafe. Each binary gets its own copy of the std::string code, and there's no guarantee that they will happen to play nicely with each other. Each binary (potentially) also gets its own copy of the CRT and you will mess up internal state of one module by manipulating objects from another.
Edit: You can export C++ objects in MSVC using __declspec(dllexport) and importing them using __declspec(dllimport). But there are a lot of restrictions on this and subtleties that cause problems. Basically this is a shortcut for getting the compiler to create a cheap C-style interface for your exported class or function. The problem is it doesn't warn you about how much unsafe stuff is happening. To reiterate:
If there are ANY templated symbols crossing DLL bounds, it is not safe (std::* for example).
Any objects with CRT-managed state should not cross DLL bounds (FILE* for example).
If you do not care about interface adaptation at all, you can export symbols from a static .lib to a .dll fairly easily. The trick is, you do not use Visual Studio GUI or projects at all, but just the linker (link.exe).
With this method, C symbols will remain C symbols and C++ symbols will remain C++ symbols. If you need to change that, you need to write wrapper code (e.g. extern C interfaces). This method simply presents existing symbols from the .objs in the .lib as official exports from the DLL.
Assume we have a .lib compiled from a source TestLib.c
#include <stdio.h>
void print(char* str)
{
printf("%s\n", str);
}
int add(int a, int b)
{
return a + b;
}
We compiled this into a static lib TestLib.lib. Now we wish to convert TestLib.lib to TestLibDll.dll (the base name should not be the same or you will get issues with the link output since the linker also creates DLL link .lib). To do this, we use link.exe outside Visual Studio GUI. Launch the "x64 Native Tools Command Prompt for Visual Studio xx" to get a cmd with the toolchain in path. (If you need 32 bit version, use x86 Native Tools instead). Change to the folder with TestLib.lib (e.g x64\Release). Then run:
link /DLL /EXPORT:add /EXPORT:print /OUT:TestLibDll.dll TestLib.lib
This should produce TestLibDll.dll. (The linker may complain a bit about there being no .obj, but you can ignore this.) The exports are:
dumpbin /exports TestLibDll.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30040.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file TestLibDll.dll
File Type: DLL
Section contains the following exports for TestLibDll.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
2 number of functions
2 number of names
ordinal hint RVA name
1 0 00001080 add
2 1 00001070 print
We have successfully exported the functions.
In the case there are many functions, using /EXPORT is tedious. Instead make a .def file. For our example, here is TestLibDll.def:
LIBRARY TestLibDll
EXPORTS
print #1
add #2
The linker is then run as
link /DLL /DEF:TestLibDll.def /OUT:TestLibDll.dll TestLib.lib
This example uses x64 C symbols, which makes it straightforward. If you have C++ symbols, you need to provide the mangled version of the symbol in the /EXPORT argument or in the def file. For more complex situations than a single static lib, you may need to provide more link libraries on the command line and/or /LIBPATH args to point to link library folders.
Again, this method is only for exporting symbols verbatim from a static library. I personally used it to create a DLL to be loaded in Python with ctypes for a closed source static library. The advantage is you don't need to write any wrapper code or create any additional VS projects at all.
Note: the accepted answer provides a good discussion of pitfalls regarding C++ DLL interface and why C wrappers are a good idea. I did not focus on that here, only on the mechanics of getting the symbols to be exported to the DLL. Using a C interface to DLL if possible remains good advice.
This was a little big to add as a comment to tenfour's response...
If you want to still maintain a C++ API when using the DLL wrapper, you can put C++ to C conversion functions in the header file. This ensures that only C compatible data types ever cross the DLL boundary.
As an example
//MyDLL.h
class MyDLL {
public:
...
int Add2ToValues(std::vector<int>& someValues) {
int* cValues = new int[someValues.size()];
memcpy(cValues, &someValues[0], someValues.size() * sizeof(int));
int retVal = Add2ToValues_Internal(cValues, someValues.size());
someValues.assign(std::begin(cValues), std::end(cValues));
delete [] cValues;
return retVal;
}
private:
int Add2ToValues_Internal(int* valuesOut, const int numValues);
};
//MyDLL.cpp
int MyDLL::Add2ToValues_Internal(int* values, const int numValues)
{
for(int i = 0; i < numValues; ++i) {
values[i] += 2;
}
return 0;
}
One catch I ran into when doing these wrappers is that you must allocate and deallocate any memory within the header file. Since the header file will be compiled by the application that is using your library, it will use the CRT for whatever compiler you are using to build your application. All interaction with the DLL uses C, so you won't run into any runtime mismatches and all memory is allocated and freed either entirely within the DLL or entirely within the application so you don't have any cross DLL memory management issues either. In the example, I both allocated and deallocated in the header. If you need to allocate data in the _Internal function, you'll need to also add a function that allows you to free that memory within the DLL. Once inside of the _Internal functions, you are free to use as much C++ as you want.

Not all symbols of an DLL-exported class is exported (VS9)

I'm building a DLL from a group of static libraries and I'm having a problem where only parts of classes are exported.
What I'm doing is declaring all symbols I want to export with a preprocessor definition like:
#if defined(MYPROJ_BUILD_DLL)
//Build as a DLL
# define MY_API __declspec(dllexport)
#elif defined(MYPROJ_USE_DLL)
//Use as a DLL
# define MY_API __declspec(dllimport)
#else
//Build or use as a static lib
# define MY_API
#endif
For example:
class MY_API Foo{
...
}
I then build static library with MYPROJ_BUILD_DLL & MYPROJ_USE_DLL undefined causing a static library to be built.
In another build I create a DLL from these static libraries. So I define MYPROJ_BUILD_DLL causing all symbols I want to export to be attributed with __declspec(dllexport) (this is done by including all static library headers in the DLL-project source file).
Edit:
Note on unrefenced symbols: Linker options Keep Unreferenced Data (/OPT:NOREF) and Do Not Remove Redundant COMDATs (/OPT:NOICF) is set so that no unreferenced symbols will be removed.
Ok, so now to the problem. When I use this new DLL I get unresolved externals because not all symbols of a class is exported. For example in a class like this:
class MY_API Foo{
public:
Foo(char const* );
int bar();
private:
Foo( char const*, char const* );
};
Only Foo::Foo( char const*, char const*); and int Foo::bar(); is exported. How can that be? I can understand if the entire class was missing, due to e.g. I forgot to include the header in the DLL-build. But it's only partial missing.
Also, say if Foo::Foo( char const*) was not implemented; then the DLL build would have unresolved external errors. But the build is fine (I also double checked for declarations without implementation).
Note: The combined size of the static libraries I'm combining is in the region of 30MB, and the resulting DLL is 1.2MB.
I'm using Visual Studio 9.0 (2008) to build everything. And Depends to check for exported symbols.
Edit:
For the ones who wonder why I don't just build a DLL from each of the static libraries: I can't because they cross-reference each other (that's why I need to group them together in one a single DLL). I know, it's horrible I can't really understand the logic behind it.
Remember that when you link against a static LIB, by default the linker is only pulling in the functions, classes, and data that the client (which in this case is your DLL) actually references.
So what happens is this:
You build your static LIB, and that's fine. This LIB is 100% valid.
You now build your static DLL around the original binary LIB. It pulls in only the stuff that it actually references. It doesn't pull in the entire class definition which is what it needs to do. This DLL, though it builds, is invalid.
A client then uses the DLL, and expects to see a complete binary definition for the exported class, because that's what the client sees in the accompanying header file.
However the class has only been partially imported, and this is why you're getting those link errors.
To fix:
If you're able to, don't build your DLL off your static LIB. Build your DLL off the original source code. And build your static LIB off the original source code.
Otherwise you can possibly fiddle with linker settings but I strongly recommend option 1 above. Note that OPT:NOREF won't work here as OPT:NOREF has no effect on static LIBs.
What wont't fix it:
High-level linker tweaks like OPT:NOREF, anything involving COMDATs, etc. If you want those functions present, you have to make sure they're referenced, either by referencing them, or by telling the linker explicitly, "hey, this Symbol X is referenced".
As a side note:
Anytime I build a DLL or LIB, I build both a DLL and a LIB, using exactly the technique you're using. Having a single code base that can generate either a DLL or a LIB by toggling a setting is ideal. But building a DLL off of a (binary) static LIB when you own the source code for both... I'm having a hard time imagining when such a scenario would be necessary.
The problem is surely that you use the already-built static .lib in your DLL project. That cannot work, you have to rebuild the .lib so that the functions get the __declspec(dllexport) declarator and will be exported by the linker.
At that point, it just isn't all that useful anymore to create the DLL compatible version of the .lib in the first place. Just create two projects, one that creates the static .lib, another that creates the DLL. Technically it is possible to still use the static .lib in your DLL project but you'll have to export the functions with a .def file. That can be high maintenance if the library has a lot of exports.
This is probably years too late, but OP's complaint was that a private method (the destructor) was not exported from a dllexport'd class. Isn't that normal? No external user is allowed to call a private method.

Why to use __declspec(dllexport)? Seems to be working without it

Been a while since I have programmed in C++, so the whole export/import idea slipped off my mind.
Can you explain me why to use __declspec(dllexport) & import thingy if it looks like I can use classes from other libraries without those.
I have created a solution in VC++ 2005, added the console applicaiton project and two dll libraries projects. Then create ClassA in a LibA, ClassB in LibB project.
Once I have included ClassA.h & ClassB.h into my console app source code, and has linked it with a LibA.lib and LibB.lib I was able to create and use instances of ClassA and ClassB in a console applicaiton. So basically I was able to use classes without exporting/importing them using __declspec.
Can you explain me - what I am missing here.
Once I have included ClassA.h & ClassB.h into my console app source code, and has linked it with a LibA.lib and LibB.lib I was able to create and use instances of ClassA and ClassB in a console applicaiton.
This sounds like you have used static linking. This works without the __declspec(dllexport) in the same way as linking with the object files of your classes directly.
If you want to use dynamic (run-time) linking with a DLL, you have to use either the mentioned declaration or a DEF-file specifying the exported functions. DLLs contain an exports table listing the functions exposed to other executables. All other functions remain internal to your DLL.
Perhaps you are confused coming from the Linux world, where the situation is the other way round: All symbols are visible externally by default.
You would use __declspec(dllexport) if you wanted to provide symbols in your dll for other dlls/exes to access.
You would use __declspec(dllimport) if you wanted to access symbols in your dll/exe provided by another dll.
Not necessary if you are linking against a static .lib.
If you are including .h files and linking to .lib files then you can drop the DLL declarations. Why do you need a dynamic link library if you only need static linking?
The export declaration marks the function as available for exporting. The declaration you are using may be a macro for "extern" and "pascal" It's been years since I've done this but I think DLLs function calls have a different ordering of pushing params on the stack and the allocation of the return result is done differently (the pascal flag). The extern declaration helps the linker make the function available when you link the library.
You may have missed the step of linking the DLL - the linker will take classA.lib and turn it into classA.dll ( you may need to setup a setupA.def file to define the DLL library). Same applies to ClassB

Trouble compiling dll that accesses another dll

So, I have an interesting issue. I am working with a proprietary set of dlls that I ,obviously, don't have the source for. The goal is to write an intermediate dll that groups together a large series of funnction calls from the proprietary dlls. The problem I am having, when compiling with g++, is that I get errors for the original dlls along the lines of:
cannot export libname_NULL_THUNK_DATA. Symbol not found.
If I add a main and just compile to an executable everything works as expected. I'm using mingw for compilation. Thanks for any help.
In response to the first reply: Either I'm confused about what you're saying or I didn't word my question very well. I'm not explicitly trying to export anything from my wrapper I am just calling functions from their dlls. The problem is that I get errors that it can't export these specific symbols from the dll to my wrapper. The issue is that I'm not even entirely sure what these _NULL_THUNK_DATA symbols are for. I did a search and read somewhere that they shouldn't be exported because they're internal symbols that windows uses. I have tried using the --exclude-symbols directive to the linker but it didn't seem to do anything. I apologize if I'm completely misunderstanding what you're trying to say.
So, I think my issue was related to this. When just compiling a standard executable that uses a dll I was able to include the headers and directly call the functions for example:
#include :3rdparty.h
int main(){
dostuff(); // a function in the 3rdparty.dll
}
this would compile and run fine. I just needed to link the libraries in the g++ command.
When linking with the -shared flag I would get these errors (with main removed of course). I think it has something to do with the fact that by default g++ attempts to import all symbols from the dll. What I didn't understand is why this happens in the dll vs in an executable. I will try doing it using GetProcAddress(). Thank you!
it should be as easy as you think it should be.
eg:
your dll code needs:
void doStuff()
{
3rdparty.login();
3rdparty.dostuff();
3rdparty.logoff();
};
so far - so good, you've included the right headers .... (if you have them, if you don't then you need to import the library using LoadLibrary(), then create a function pointer to each exported dll entrypoint using GetProcAddress() and then call that function pointer)
You then link with the 3rd party lib and that's it. Occasionally you will have to wrap the definitions with 'extern "C"' in order to get the linkage name mangling correct.
As you say you're using g++, you can't be getting confused with __declspec(dllimport) which is a MS VC extension.
"Compiling" tells me that you're approaching this from the wrong end. Your DLL should not export its own wrapper functions, but directly refer to exports from other DLLs.
E.g. in a Windows Kernel32.DEF file, the following forward exists:
EXPORTS
...
HeapAlloc = NTDLL.RtlAllocHeap
There's no code for the HeapAlloc function.