I have a circular dependency between two functions. I would like each of these functions to reside in its own dll. Is it possible to build this with visual studio?
foo(int i)
{
if (i > 0)
bar(i -i);
}
-> should compile into foo.dll
bar(int i)
{
if (i > 0)
foo(i - i);
}
-> should compile into bar.dll
I have created two projects in visual studio, one for foo and one for bar. By playing with the 'References' and compiling a few times, I managed to get the dll's that I want. I would like to know however whether visual studio offers a way to do this in a clean way.
If foo changes, bar does not need to be recompiled, because I only depend on the signature of bar, not on the implementation of bar. If both dll's have the lib present, I can recompile new functionality into either of the two and the whole system still works.
The reason I am trying this is that I have a legacy system with circular dependencies, which is currently statically linked. We want to move towards dll's for various reasons. We don't want to wait until we clean up all the circular dependencies. I was thinking about solutions and tried out some things with gcc on linux and there it is possible to do what I suggest. So you can have two shared libraries that depend on each other and can be built independent of each other.
I know that circular dependencies are not a good thing to have, but that is not the discussion I want to have.
The reason it works on Unix-like systems is because they perform actual linking resolution at load time. A shared library does not know where its function definition will come from until it's loaded into a process. The downside of this is that you don't know either. A library can find and call functions in any other library (or even the main binary that launched the process in the first place). Also by default everything in a shared library is exported.
Windows doesn't work like that at all. Only explicitly exported things are exported, and all imports must be resolved at library link-time, by which point the identity of the DLL that will supply each imported function has been determined. This requires an import library to link against.
However, you can (with some extra work) get around this. Use LoadLibrary to open any DLL you like, and then use GetProcAddress to locate the functions you want to call. This way, there are no restrictions. But the restrictions in the normal method are there for a reason.
As you want to transition from static libraries to DLLs, it sounds like you're assuming that you should make each static library into a DLL. That's not your only option. Why not start moving code into DLLs only when you identify it as a self-contained module that fits into a layered design with no circularity? That way you can begin the process now but still attack it a piece at a time.
I deeply sympathise with your situation (as clarified by your edit), but as a firm believer in doing the correct thing, not the thing which works for now, if there's any possibility at all I think you need to refactor these projects.
Fix the problem not the symptom.
It's possible to use the LIB utility with .EXP files to "bootstrap" (build without prior .LIB files) a set of DLLs with a circular reference such as this one. See MSDN article for details.
I agree with other people above that this kind of situation should be avoided by revising the design.
This question was first in my search for 'dll cyclic dependency', and even if it is 10 years old, it is a shame that most answers points to 'refactoring' which is a very very very stupid advice for large project and was not a question anyway.
So I need to point out that cyclic dependency are not so dangerous. They are totally ok in unix/linux. They are mentioned in many msdn articles as possible situations with ways to go arround them. They happens in JAVA (compiler solving it by muilti-pass compiling). Saying that refactoring is the only way is like forbidding 'friends' in classes.
this pragraph in some begginers guide to linkers (David Drysdale) explains it well for VS-linkers.
So the trick is to use two-pass compiling: first one that will create just 'import-libs', and the second one that will generate dll's itself.
For visual studio and any graphic-ide compiling, it is probably still something strange. But if you make your own Makefiles, and have better controll of linker process and flags, than it is not so hard to do.
Using OP exampe files and mingw-gcc syntax as a concept to show (because i tested it and know for sure that it works ok on windows), one must:
- compile/link a.lib and b.lib without specifing cyclic libraries:
g++ -shared -Wl,--out-implib=a.lib -o a.dll a.obj //without specifying b.lib
g++ -shared -Wl,--out-implib=b.lib -o b.dll b.obj //without specifying a.lib
... will show 'undefined refernce errors' and fail to provide dll-s, but it will create a.lib and b.lib, which we want foor second-pass linking:
g++ -shared -Wl,--out-implib=a.lib -o a.dll a.obj b.lib
g++ -shared -Wl,--out-implib=b.lib -o b.dll b.obj a.lib
and the result is a.dll and b.dll with pretty clean method. Using Microsoft compilers should be simmilar, with their advice to switch link.exe to lib.exe (did not tested it, seems even cleaner, but probably harder to make something productive from it comparing to mingw + make tools).
How about this:
Project A
Public Class A
Implements C.IA
Public Function foo(ByVal value As C.IB) As Integer Implements C.IA.foo
Return value.bar(Me)
End Function
End Class
Project B
Public Class B
Implements C.IB
Public Function bar(ByVal value As C.IA) As Integer Implements C.IB.bar
Return value.foo(Me)
End Function
End Class
Project C
Public Interface IA
Function foo(ByVal value As IB) As Integer
End Interface
Public Interface IB
Function bar(ByVal value As IA) As Integer
End Interface
Project D
Sub Main()
Dim a As New A.A
Dim b As New B.B
a.foo(b)
End Sub
The only way you'll get around this "cleanly" (and I use the term loosely) will be to eliminate one of the static/link-time dependencies and change it to a run-time dependency.
Maybe something like this:
// foo.h
#if defined(COMPILING_BAR_DLL)
inline void foo(int x)
{
HMODULE hm = LoadLibrary(_T("foo.dll");
typedef void (*PFOO)(int);
PFOO pfoo = (PFOO)GetProcAddress(hm, "foo");
pfoo(x); // call the function!
FreeLibrary(hm);
}
#else
extern "C" {
__declspec(dllexport) void foo(int);
}
#endif
Foo.dll will export the function. Bar.dll no longer tries to import the function; instead, it resolves the function address at runtime.
Roll your own error handling and performance improvements.
As I came across this very problem recently I wanted to share a solution using CMake.
The idea is that we have two dlls a and b that have a circular dependency and one main object that calls a.dll. To make the linking work we create an additional library b_init that is compiled with the /FORCE:UNRESOLVED flag in order to allow building with incomplete symbols as it is not linking against a. Additionally, b_inits output name is b, so it will create b.lib.
In the next step we link a to the newly created b.lib. Note, the PRIVATE keyword to avoid transitive adding of b.lib to the b library below.
Here's the CMakeLists.txt:
project(circ_dll CXX)
cmake_minimum_required(VERSION 3.15)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
add_library(b_init SHARED b_dll.cpp)
set_target_properties(b_init PROPERTIES LINK_FLAGS "/FORCE:UNRESOLVED")
set_target_properties(b_init PROPERTIES OUTPUT_NAME "b")
add_library(a SHARED a_dll.cpp)
target_link_libraries(a PRIVATE b_init)
add_library(b SHARED b_dll.cpp)
target_link_libraries(b a)
add_executable(main main.cpp)
target_link_libraries(main a b)
It is not possible to do cleanly. Because they both depend on each other, if A changes, then B must be recompiled. Because B was recompiled, it has changed and A needs to be recompiled and so on.
That is part of the reason circular dependencies are bad and whether you want to or not, you cannot leave that out of the discussion.
Visual Studio will enforce the dependencies, generally speaking, since function addresses may change within the newly-compiled DLL. Even though the signature may be the same, the exposed address may change.
However, if you notice that Visual Studio typically manages to keep the same function addresses between builds, then you can use one of the "Project Only" build settings (ignores dependencies). If you do that and get an error about not being able to load the dependency DLL, then just rebuild both.
You need to decouple the two DLLs, placing the interfaces and implementation in two different DLLs, and then using late binding to instantiate the class.
// IFoo.cs: (build IFoo.dll)
interface IFoo {
void foo(int i);
}
public class FooFactory {
public static IFoo CreateInstance()
{
return (IFoo)Activator.CreateInstance("Foo", "foo").Unwrap();
}
}
// IBar.cs: (build IBar.dll)
interface IBar {
void bar(int i);
}
public class BarFactory {
public static IBar CreateInstance()
{
return (IBar)Activator.CreateInstance("Bar", "bar").Unwrap();
}
}
// foo.cs: (build Foo.dll, references IFoo.dll and IBar.dll)
public class Foo : IFoo {
void foo(int i) {
IBar objBar = BarFactory.CreateInstance();
if (i > 0) objBar.bar(i -i);
}
}
// bar.cs: (build Bar.dll, references IBar.dll and IFoo.dll)
public class Bar : IBar {
void bar(int i) {
IFoo objFoo = FooFactory.CreateInstance();
if (i > 0) objFoo.foo(i -i);
}
}
The "Factory" classes are technically not necessary, but it's much nicer to say:
IFoo objFoo = FooFactory.CreateInstance();
in application code than:
IFoo objFoo = (IFoo)Activator.CreateInstance("Foo", "foo").Unwrap();
because of the following reasons:
You can avoid a "cast" in application code, which is a good thing
If the DLL that hosts the class changes, you don't have to change all the clients, just the factory.
Code-completion still wroks.
Depending on your needs, you have to call culture-aware or key-signed DLLs, in which case you can add more parameters to the CreateInstance call in the factory in one place.
--
Kenneth Kasajian
Related
I am new to CMake and a bit confused with the PUBLIC, PRIVATE and INTERFACE keywords related to target_link_libraries(). Documentation mentions that they can be used to specify both the link dependencies and the link interface in one command.
What does link dependencies and link interface actually mean?
If you are creating a shared library and your source cpp files #include the headers of another library (Say, QtNetwork for example), but your header files don't include QtNetwork headers, then QtNetwork is a PRIVATE dependency.
If your source files and your headers include the headers of another library, then it is a PUBLIC dependency.
If your header files other than your source files include the headers of another library, then it is an INTERFACE dependency.
Other build properties of PUBLIC and INTERFACE dependencies are propagated to consuming libraries. http://www.cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#transitive-usage-requirements
#steveire accepted answer is great. I just wanted to add a table to quickly see the difference:
.-----------.------------------.----------------.
| | Linked by target | Link interface |
:-----------+------------------+----------------:
| PUBLIC | X | X |
:-----------+------------------+----------------:
| PRIVATE | X | |
:-----------+------------------+----------------:
| INTERFACE | | X |
'-----------'------------------'----------------'
Linked by target: libraries included in target sources (not a dependency for projects linking the library).
Link interface: libraries included in target public headers (dependencies for projects linking the library).
Not my brainchild but this extremely useful explanation helped me understand the situation. The most important part is quoted below for reference:
When A links B as PRIVATE, it is saying that A uses B in its implementation, but B is not used in any part of A's public API. Any
code that makes calls into A would not need to refer directly to
anything from B. An example of this could be a networking library A
which can be built to use one of a number of different SSL
libraries internally (which B represents). A presents a unified
interface for client code which does not reference any of the
internal SSL data structures or functions. Client code would have
no idea what SSL implementation (B) is being used by A, nor does
that client code need to care.
When A links B as INTERFACE, it is saying that A does not use B in its implementation, but B is used in A's public API. Code
that calls into A may need to refer to things from B in order to
make such calls. One example of this is an interface library which
simply forwards calls along to another library but doesn't actually
reference the objects on the way through other than by a pointer or
reference. Another example is where A is defined in CMake as an
interface library, meaning it has no actual implementation itself,
it is effectively just a collection of other libraries (I'm
probably over-simplifying here, but you get the picture).
When A links B as PUBLIC, it is essentially a combination of PRIVATE and INTERFACE. It says that A uses B in its implementation and
B is also used in A's public API.
Consider first what this means for include search paths. If something
links against A, it will also need any include search paths from B if
B is in A's public API. Thus, if A links B either as PUBLIC or
INTERFACE, then any header search paths defined for target B will also
apply to anything that links to A. Any PRIVATE header search path for
B will NOT be carried through to anything that links only to A. The
target_include_directories() command handles this. The situation with
compile flags is analogously handled with target_compile_definitions()
and target_compile_options().
Now consider the situation for the actual libraries involved. If A is
a shared library, then A will have encoded into it a dependency on B.
This information can be inspected with tools like ldd on Linux, otool
on Mac and something like Dependency Walker (a.k.a. depends.exe) on
Windows. If other code links directly to A, then it also will have
encoded into it a dependency on A. It will not, however, have a
dependency on B unless A links B either as PUBLIC or INTERFACE. So far, so
good. If, however, A is a static library, the situation changes.
Static libraries do not carry information about other libraries they
depend on. For this reason, when A links B as PRIVATE and another
target C links A, CMake will still add B to the list of libraries
to be linked for C because parts of B are needed by A, but A itself
doesn't have that dependency encoded into it. So even though B is an
internal implementation detail of A, C still needs B added to the
linker command, which CMake conveniently handles for you.
If you were paying careful attention, you would have noticed that when
A links B as PRIVATE, the include directories of B never propagate
to something linking to A, but if A is a static library, then the
linking of B behaves as though the relationship was PUBLIC. This PRIVATE-becomes-PUBLIC behaviour for static libraries only applies to
the
linking, not to the other dependencies (compiler options/flags and include search paths). The upshot of all this is that if you select
PRIVATE, PUBLIC or INTERFACE based on the explanations in the dot
points above, then CMake will ensure dependencies propagate through to
where they are required, regardless of whether libraries are static or
shared. This does, of course, rely on you the developer not missing
any dependencies or specifying the wrong PRIVATE/PUBLIC/INTERFACE
relationship.
Some answers only said when to use PRIVATE/PUBLIC/INTERFACE, but the affects are ignored. Refer:CMake-Public-Private-Interface
PUBLIC
All the objects following PUBLIC will be used for linking to the current target and providing the interface to the other targets that have dependencies on the current target.
PRIVATE
All the objects following PRIVATE will only be used for linking to the current target.
INTERFACE
All the objects following INTERFACE will only be used for providing the interface to the other targets that have dependencies on the current target.
Other posts already answered what the meaning of PUBLIC/PRIVATE/INTERFACE keywords. I want to add one more to clarify the terms "link dependencies" and "link interface."
Link dependencies :
the list of libraries to be linked by the target.
The target property LINK_LIBRARIES holds this information.
Link interface : the list of libraries to be linked by the target's dependents. The target property INTERFACE_LINK_LIBRARIES holds this information.
Probably the term "link interface" came from the old CMake wording used around LINK_INTERFACE_LIBRARIES properties, which is deprecated in favor of INTERFACE_LINK_LIBRARIES.
See the description of CMP0022, which also uses the term "link interface."
https://cmake.org/cmake/help/latest/policy/CMP0022.html
INTERFACE_LINK_LIBRARIES defines the link interface.
I'm in DLL hell. I have 2 DLLs let's say A.dll and B.dll which have a name collision - the same C++ class name is used in each, etc. Both DLLs are available as static libs.
Can I create a 'wrappe' DLL, say Aprime.dll which exports a similar class, methods, etc. as in A.dll, and delegates the functionality to the class in A.lib, but statically linked into the Aprime.dll? Wouldn't that avoid the name collision?
I've been trying this, but not sure I have the MSVS project set up correctly. Aprime.dll is being produced, but according to Dependency Walker Aprime.dll is still loading A.dll.
I've been searching, but most stuff I find applies only to statically linking in the CRT or MFC, which have their own switches.
I added A.lib under Linker -> Input -> Additional Dependencies.
Am I missing some magic linker command line switch or something?
Yes that method should work. The key though is to ensure that you do not include any of the original A.dll header files in the Aprime.dll header file. Otherwise if someone includes Aprime.h/pp then it will include A.h/pp and you will then have a clash again.
So you want something like:
A.h
// Library A includes
class test
{
};
B.h
// Library B includes
class test
{
}
Aprime.h
// Proxy class
class myTest
{
}
Aprime.cpp
#include "A.h"
#include "Aprime.h"
...
main.cpp
#include "Aprime.h"
#include "B.h"
...
Note that main never includes both A and B. In only includes Aprime and B. B is still static lib and Aprime is a DLL.
Yes, you can, and it's supported at a very low level by Windows. Aprime.DLL is effectively empty except for a bunch of references to A.DLL.
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.
I currently have a c++ setup like the following
class FlowController
{
public:
//...
private:
cntrl::OneWayValve _intake;
}
As you can see i'm using a cntrl::OneWayValve instance within my class. The Valve class resides in another library which i link with at compile time. The cntrl::OneWayValve has a cntrl::Value within its implementation like so.
class OneWayValve
{
public:
//...
private:
cntrl::Valve _valve;
}
And as before the cntrl::Valve resides in a different library for reasons you'll have to ask the previous developer about.
Now when i compile my FlowController class i'm required to link with the OneWayValve library and the cntrl::Valve library as well.
My question:
Is it possible to only link with the cntrl::OneWayValve library at compile time?
Forward declaration?
Static libraries (really don't want to do this tho)?
Another alternative?
Basically i don't want to know that its using a cntrl::Valve internally, its none of my business.
Note: apologies the OS is Unix.
Cheers,
Ben
What you could do is make your Valve library part of your OneWayValve library using a tool called a librarian. I don't know what OS/compiler you are using so I'm going to describe how do it using Visual Studio since that's the only system I've actually done this with (unless you want to count CP/M + LIB-80 :-)
If you bring up the Tools|Options dialog for you OneWayValve project and select Configuration Properties|Librarian|Additional Dependencies, you can put a reference to your Valve library in the Additional Dependencies setting. This will cause OneWayValve.lib to contain any objects that it references from Valve.lib.
Unfortunately for you, the OneWayValve isn't very well designed. Not only you need to link to both libraries, but you will also have to recompile both the OneWayValve library and your code if the Valve class changes.
You can do it by defining all methods of OneWayValve and Valve in their headers as inline. Then you don't need to link to the library.
But if it was designed that way, then what problems are linking to this library causing? Nothing wrong with dynamically linking a library.
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.