views:

157

answers:

3

Hello all,

I am currently creating my own framework in C++ (MSVS 2008) which exports a dll with a bunch of functions for a user of my framework to use/call. In the beginning, when my project was still small, all worked fine. I compiled my project. A MyFramework.dll and MyFramework.lib were spit out. I pretended to be a user; put the MyFramework.dll file in my new VS project's Debug folder, put the MyFramework.lib and MyFramework.h file in my project folder, #include-d MyFramework.h in my code and voilá, I could call the (still simple) framework functions from within my new project.

But now I have expanded my framework. It now uses an external dll of its own (let me call it Graphics.dll) and included it in the same way (.dll in Debug folder, .lib/.h in project folder, #include Graphics.h in code).

The problem is that when I nów create MyFramework.dll/MyFramework.lib, include it in my new project and build, the linker complains about not being able to include Graphics.h, which obviously was included in MyFramework.dll somewhere.

So my question. I would like the user of MyFramework.dll to solely have to include the MyFramework.* files in their project and not have the need to copy/paste all external libraries I decide to use in MyFramework. How can I accomplish this? I took a look at this thread. It says something about adding an existing item and pressing the small arrow next to the "Add" button, but...the arrow is nonexistent in my version of MSVS...

Help is very much appreciated.

Kind regards W. Spek

+1  A: 

"The problem is that when I nów create MyFramework.dll/MyFramework.lib, include it in my new project and build, the linker complains about not being able to include Graphics.h, which obviously was included in MyFramework.dll somewhere."

Have you put the path to the header file? The compiler is reporting that the header file is not in the same directory as the cpp file being converted and its not listed in the additional include directories either.

Go to Project->Properties then select C/C++

The first option you'll see is "Additional Include Directories". You need to put the path to your header Graphics.h in there along with any other paths required all semi-colon seperated. The project I have open at the mo has, for example: "../AudioLibrary;../CoreLibrary;"

Edit: From your comments to Mark's post you say you want to embed the Graphics.DLL in your DLL. My answer is as follows:

If you don't have the source code to the Graphics.dll then you have a problem. What you are asking IS possible but VERY complex to do. Basically you can't use LoadLibrary. You will be forced to write your own for of LoadLibaray and GetProcAddress that will look at the embedded DLL and not try and find it on disk ... Its doable but you are going to need to do a lot of reading on the Portable Executable (PE) file structure.

Goz
And that exactly pins down what I do not want to have to do. What can I do in my "MyFramework"-project, to not have to include external files in my new project which uses the MyFramework.dll?
Waldo Spek
Well you need to know what the function prototype looks like. Using GetProcAddress, as suggested by Mark, is all well and good but either you have to create a header file which has a copy of the stuff in Graphics.h or you have to include the original Graphics.h. Otherwise how can the compiler possibly know what parameters are needed?
Goz
I should also point out that if you are going to use GetProcAddress then you will need to create a bunch of correct function pointers with the relevant function prototype embedded in the pointer.
Goz
A: 

If you don't want to require the user to have or include Graphics.h, one way around that is to use LoadLibrary to dynamically load Graphics.dll at runtime.

This will mean that the user will be able to compile against MyFramework without Graphics.dll being available, so it might be wise to do some kind of error reporting if LoadLibrary fails.

Once you have successfully called LoadLibrary on Graphics.dll, you'll need to manually import each function (and its signature) using GetProcAddress -- this will actually give you function pointers. How you store the function pointers is up to you; I generally prefer to have wrap a class around the imported functions but there's nothing stopping you from keeping the function pointers in the global scope.


As mentioned in the comments, if you don't want to distribute Graphics.dll at all, it will need to be a static library (i.e. "built in" to MyFramework.dll). If you do want to distribute Graphics.dll (so the user can use Graphics.dll without MyFramework.dll), then the above approach remains the better option. Really, the above approach assumes you are distributing Graphics.dll with MyFramework.dll, but that the user may not necessarily have Graphics.h available.

Mark Rushakoff
But probably the user will still need a separate copy of Graphics.dll somewhere on his harddisk, right? That too is an unwanted situation. The user need not know about the existence of Grpahics.dll. He should only have to care about the MyFramework.* files...
Waldo Spek
Are you talking about embedding the DLL in the executable? If so .. use a static library not a dynamic library!
Goz
Yes, I am talking about embedding the Graphics.dll in the MyFramework.dll. So the suggestion is a static library? But what do you mean; make the MyFramework library static, or somehow include a static Graphics library in the MyFramework.dll. Please do note that I do not have source code for Graphics.dll, except for the Graphics.h.
Waldo Spek
I think although you include a static copy of Graphics.dll inside MyFramework, you still need to add the .h file in the Client Project. MyFramework.h includes Graphics.h and your Client Project cannot access that file. I'm having this problem right now and i'm not sure how can i solve it. To keep going, I added the Graphics.h folder to Client Project include folders.
HyLian
+2  A: 

What is happening is the user is including one of your library's header files. This file is then including "graphics.h". If you don't want to require your users to have access to this file you must hide it from your libraries interface.

That is your library must have public api header files and private implementation header files. Your user only includes the public api header files, these do not include any 3rd party or private include files. When these files reference private types or 3rd party types, they can only use pointers or references, these are forward declared. This enables the private part of a class to use private library code and 3rd party types.

The chances are using the Pimpl Idiom will fix this for you.

iain
I think you might be right. Right now I am including Graphics.h in the MyFramework.h interface header file. This is wrong. I also spoke to my supervisor who told me the same. This is why the user's compiler is complaining about missing the Graphics.h file. I will have a look at the PIMPL pattern and see if I can fix my problem. Have to do it a bit later though. I will get back on the final solution.
Waldo Spek
I was trying to use an unmanaged library from a managed DLL using C++/CLI. Unfortunately my header was using an OpenCV header which meant it needed mixed-mode building, which wouldnt work. Using the Pimpl idiom was exactly what I needed
Fuzz