views:

295

answers:

4

(Re-written for clarity)

I have a multi-project solution that I am looking to convert from using .lib to .DLL files. I have created my declspec macros and applied it to **every class except for those in the project that creates the final .exe. The linker is throwing a fit on just about everything, however. I have set up to ignore errors about exporting templated objects.

One example is this:

error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __thiscall Rail::SetNextRail(class Rail *)" (__imp_?SetNextRail@Rail@@QAEXPAV1@@Z) referenced in function "public: static void __cdecl MyUtilities::CreateBezierRails(int,class MyVector *,class std::vector > &)" (?CreateBezierRails@MyUtilities@@SAXHPAVMyVector@@AAV?$vector@PAVRail@@V?$allocator@PAVRail@@@std@@@std@@@Z) MyUtilities.obj

Unresolved external symbol on my __declspec(dllimport)? That doesn't seem right. It is getting placed by a macro such as:

#ifdef MYAI_EXPORT
#define DECLSPECAI __declspec(dllexport)
#else
#define DECLSPECAI __declspec(dllimport)
#endif

Basically, what gives? Why am I getting these errors and how can I fix them? Thank you to everybody who has tried to help thus far, but I am still stuck with this.

A: 

Well its saying that it found a declaration but no implementation. Are you sure you are compilnig the file with the function implementation in it? Have you remembered to put the MyRenderer:: before the DrawVertices call? Are you sure you are linking both the libraries into the executable?

Edit: When compiling a lib the library leaves a stub, effectively, saying I want this function when you can link it to me.

When you run the linker it runs through all the libraries looking for these stubs and "links" them to the actual implementation. Each cpp file you build compiles to an object file and this object file works in exactly the same way. If it can't link the stub to the actual function then you get a linker error such as you are seeing. Thus, either your renderer library is not being linked into the executable OR the implementation is missing something vital such as the MyRenderer::. Though if it was the latter i'd expect other problems to arise such as the lack of a IDirect3DDevice which, i assume, is a member of the class. Thus, most probably, you are failing to link the .lib in.

Goz
I am compiling the file with the implementation in it, yes. In the implementation, it is being referenced by creating an instance of MyRenderer and then using renderer->DrawVertices. About liking both libraries to the executable, I believe so, but I am new to this. This compiled and ran perfectly as a .lib.
4501
It sounds like it must be the linking then. I am new to C++, so I am not sure how to go about this, unfortunately.
4501
+3  A: 

Are you linking against MyRenderer.lib?

Dolphin
As in is there a project dependency (I am using visual studio, sorry). Yes
4501
So the .lib files are listed in Project Properties > Configuration Properties > Linker > Input > Additional Dependencies? Project dependencies are something else.
Zack Mulgrew
Thanks for the clarification. I added this and now get "cannot open input file 'MyRenderer.lib'. I went and checked, it is in the output/Debug folder for MyRenderer but not in the output/Debug folder for MyAI.
4501
There is a setting in the general linker options for 'Additional Library Directories' which you can put the output dir for MyRenderer.
Dolphin
You could circumvent adding all output dirs by defining intermediate directory `$(SolutionDir)/obj/$(ProjectName)` and output directory `$(SolutionDir)/bin` for all your projects and configurations.
MP24
This link has been added. However, the original error (identical to the one in the question description) has come back.
4501
If the option "Link Library Dependencies" is on, I don't think this is needed, as his project dependencies are set.
Kevin
Kevin, good call. I misunderstood all of the aspects of setting a Project Dependency, thinking it primarily controlled build order and not much else.
Zack Mulgrew
+2  A: 

Do you export your functions and classes using

__declspec(dllexport)

and import them using

__declspec(dllimport)

? If not, you will have to do this. In your header, during compiling the DLL, you will need to have the dllexport clause, and when using the header in other DLLs or EXEs, you will have to use the dllimport clause. You can easily do this by defining a macro like

// set this in preprocessor options for the DLL
#ifdef MYDLL
# define MYDLL_IMPORTEXPORT __declspec(dllexport)
#else
# define MYDLL_IMPORTEXPORT __declspec(dllimport)
#endif
class MYDLL_IMPORTEXPORT MyClass {};
MP24
Yep! I have this. Although a couple of the errors about unresolved external symbols are "unresolved external symbol __declspec(dllimport) public: void _thiscall Rail::SetNextRail" etc
4501
A: 

there are different configurations of DLLs.

  • staticly linked DLL - the implementations are in a DLL, and the definitions are in a .lib. You statically link to the .lib (which is kinda like a header), and the lib tells c++ how to call the function. this is probably what you want. make sure you get your __declspecs right.
  • dynamically linked DLL - everything is in the DLL, the definitions are also in the DLL, you need to manually set up function pointers to all the exported things, which are indexed by a string at runtime.

Google will help and made this CW so someone can make this answer suck less.

i also advise you to get DLLs working in a skeleton app.

Dustin Getz