I have a VS 2005 solution that has numerous projects (most are DLL, 1 EXE which is a CppUnit project) and I am trying to add a fixed back-end DLL for the Pantheios logger so that I can use a single logger instance throughout the solution. Following the directions from the below URLs:
Use Pantheios logging framework from a dll
https://sourceforge.net/projects/pantheios/forums/forum/647484/topic/1639420/index/page/1
I seem to have a fixed back-end DLL that supports basic Pantheios logging statements e.g. log_DEBUG, log_ERROR etc. and even the Tracing API (http://www.pantheios.org/doc/html/group__group____tracing.html) e.g. PANTHEIOS_TRACE_NOTICE.
But I am stuck going forward because Pantheios requires "inserters" (an API to convert fundamental types to string) (http://www.pantheios.org/doc/html/group__group____application__layer__interface____inserters.html) to handle for example int, double, float, pointer etc.
I don't know how implement these "inserters" in the fixed back-end DLL that I created. If I simply call them from my other DLLs then I get an error such as this:
DLLApp.obj : error LNK2019: unresolved external symbol "public: __thiscall pantheios::integer::integer(int,int)" (??0integer#pantheios##QAE#HH#Z) referenced in function "public: void __thiscall DLLApp::DLLAppSetup(void)" (?DLLAppSetup#DLLApp##QAEXXZ)
I am not sure if I can (and need to) export the "integer" (and other inserter) class using the .DEF as mentioned in the sourceforge.net article OR if there is something else I am missing.
Any help would be most appreciated. Thanks in advance.
In project properties page, change character set as "Use Multi-Byte Character Set"
Related
First, a little background:
At work, I've inherited a large C++ program (a language I haven't used extensively in 12 years). To help myself better understand the application and how it fits together, I thought, "I love TDD, why not write some unit tests!". I've since spent two days getting a simple unit test to compile. I'm at the point where it gets to the linker, but I get the following error:
CIniReader* reader = new CIniReader("");
Error 3 error LNK2019: unresolved external symbol "public: __thiscall CIniReader::CIniReader(char *)" (??0CIniReader##$$FQAE#PAD#Z) referenced in function "public: void __clrcall ApogeeTests::UnitTest1::TestMethod1(void)" (?TestMethod1#UnitTest1#ApogeeTests##$$FQ$AAMXXZ) C:\Users\champad\Documents\Applications\Leading Hedge\src\Apogee.Tests\UnitTest1.obj Apogee.Tests
Now, I can resolve this buy setting the project that this lives in to a static library, rather than a DLL project (Properties -> Configuration Properties -> General -> Configuration Type).
My question is this: MUST I do this? It seems there has to be a way for the linker to identify the functions it needs at compile time without having to constantly switch all 24 projects to lib when I want to unit test, and back when I need to deploy it.
Any thoughts?
While not exactly what I was looking for, this is what I'm doing unless anyone has a better suggestion!
I added a new project configuration and called it UnitTesting. Under that configuration, all the C++ projects are static libraries that the unit test project can reference. I figure I change the configuration before deploying, so this would be easy for me to remember.
While not ideal, this is working. But if there is a better way, please let me know!
Visual Studio creates a static library for each DLL you create, specifically for linking with client code.
If your project has the following modules:
core-functionality.dll
unit-tests.exe
Then your unit-tests.exe will either load APIs from core-functionality.dll using LoadLibrary and family and casting the resulting function pointers to the correct types (this is ugly, error prone and difficult to maintain), or it can link statically, against core-functionality.lib (this should be generated during the build of core-functionality.dll).
I think you are looking for the second option.
I am attempting to build a project in Visual Studio 2012 that uses GnuTLS. I downloaded the latest official Windows build from the website, and created a link library by running lib /def:libgnutls-28.def in the bin directory form a Visual Studio command prompt.
After adding a typedef long ssize_t, the code compiles fine, but linking fails with the following error:
source_file.obj : error LNK2001: unresolved external symbol _gnutls_free
C:\Path\to\executable.exe : fatal error LNK1120: 1 unresolved externals
I am calling gnutls_free to free some memory allocated and returned by the library. If I remove the call to gnutls_free, the project links successfully. Given that gnutls_free is just a global variable (containing a function pointer) exported by the library, I'm not sure why accessing it results in an unresolved reference to a different symbol. I have verified that gnutls_free is not #defineed to anything.
As a test, I tried doing gnutls_free_function test = gnutls_free; which also resulting in the link error. Running grep -w -r _gnutls_free . on the GnuTLS source code returns nothing, so I am at a loss.
Any ideas for getting this working would be greatly appreciated.
EDIT:
Adding __declspec(dllimport) to the declaration of gnutls_free in gnutls.h allows the link to succeed. Is there any way to accomplish this without maintaining a custom version of the header file?
There doesn't seem to be a way to have the linker or import library automatically dereference the IAT's pointer to the data item the same way that is done for functions (via a small trampoline function that is statically linked into the module importing the function). The __declspec(dllimport) attribute tells that compiler that this dereferencing needs to be done so it can insert code to perform the dereferencing of the IAT pointer implicitly. This allows exported data to be accessed and for functions allows the compiler to call the imported function via an indirect call through the IAT pointer rather than by calling the trampoline function.
See a couple of Raymond Chen's articles about dllimport for a good explanation of what goes on for function calls (he didn't discuss importing data, unfortunately):
Calling an imported function, the naive way
How a less naive compiler calls an imported function
The MS linker or import library doesn't have a mechanism to help the compiler get imported data in a 'naive' way - the compiler needs the the __delcspec(dllimport) hint that an extra dereference through the IAT is needed. Anyway, the point of all this is that it seems there's no way to import data except by using the __declspec(dllimport) attribute.
If you want to avoid modifying the gnutls distribution (which I can understand), here's one rather imperfect workaround:
You can create a small object file that contains nothing but a simple wrapper for gnutls_free(); since gnutls_free() has an interface with no real dependencies, you can have the necessary declarations 'hardcoded' instead of including gnutls.h:
typedef void (*gnutls_free_function) (void *);
__declspec(dllimport) extern gnutls_free_function gnutls_free;
void xgnutls_free(void* p)
{
gnutls_free(p);
}
Have your code call xgnutls_free() instead of gnutls_free().
Not a great solution - it requires your code to call a wrapper (so it's particularly not great if you'll be incorporating 3rd party code that might depend on gnutls_free()), but it might be good enough.
Hello industry veterans,
I am a junior in college embarking on my first summer programming internship, and I am in way over my head. The company I'm working for has purchased a colossal application from another company that has slowly been expanding and modifying it since the early 90's. The solution contains over 200,000 lines of code which are spread across more than 300 files. The entire solution has purportedly been written to ANSI-C++ standards. The code is almost entirely undocumented, and most of it looks like hieroglyphs to me. Ultimately, my job is to port this code to embedded Linux. At the moment, my job is simply to get it compiling using Visual Studio 2008 on Windows XP.
Today, I'm running into linker errors such as this one:
libcmtd.lib(sprintf.obj) : error LNK2005: _sprintf already defined in msvcrtd.lib(MSVCR90D.dll)
My understanding is that this often happens when different projects within a solution are compiled using different runtime libraries. There are 6 projects in my solution. 4 of them were set to compile using the multi-threaded debug DLL runtime library (/MDd), one of them was set to compile using the multi-threaded debug library (/MTd), and one of them was set to compile using the multi-threaded dll runtime library (/MD). The first thing I tried after receiving this error message was to change the /MTd and /MD switches to /MDd so that everything would have compiled with the same runtime libraries. Unfortunately, this led to the following error in afx.h:
fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]
After some digging around, I discovered that it had already told me what I needed to do. I went ahead and changed the "Use of MFC" option under Project Properties->Configuration Properties->General to "Use MFC in a Shared DLL". At this point I started receiving dozens of unresolved external errors such as these:
dataPropertySheet.obj : error LNK2019: unresolved external symbol "public: __thiscall CResizableSheet::CResizableSheet(unsigned short const *,class CWnd *,unsigned int)" (??0CResizableSheet##QAE#PBGPAVCWnd##I#Z) referenced in function "public: __thiscall CdataPropertySheet::CdataPropertySheet(unsigned short const *,class CWnd *,unsigned int)" (??0CdataPropertySheet##QAE#PBGPAVCWnd##I#Z)
ResizableLib.lib(ResizablePage.obj) : error LNK2001: unresolved external symbol "public: virtual int __thiscall CWnd::Create(char const *,char const *,unsigned long,struct tagRECT const &,class CWnd *,unsigned int,struct CCreateContext *)" (?Create#CWnd##UAEHPBD0KABUtagRECT##PAV1#IPAUCCreateContext###Z)
After reading through the MSDN pages on LNK2001 and LNK2019, I've realized I have no idea what's going on. These are not the sort of issues they've taught us how to deal with in school. I know my data structures, and that's about it. How I ended up where I am now is beyond me!
From my limited knowledge, it seems that the various debug and release versions of these modules are all tangled up in a web of preprocessor directives and #includes. There are a number of nested #ifdef checks and #define statements done in nearly every header and source file throughout the solution for environment variables, file names, macros, and possibly more. By making even small changes to my compiler settings, I seem to be redirecting large parts of the program to different libraries which have very different function definitions. This is my vague conceptual understanding of what's going on.
I feel as though I'm going to need a better understanding of how this code works before I stand any chance of troubleshooting these compiler errors. To that end, I've been trying to step through many of the files line by line to see where they lead, what objects and variables are in scope, and so on. Unfortunately, this doesn't get me very far, because every call to an external function is ambiguous, and I have no way of seeing through the preprocessor mess to know which version of any given function is supposed to be called.
I was looking around for magic solutions to map out the program and try to make sense of it. I tried one called Doxygen, but either I don't know how to use it properly or it's getting just as confused by the preprocessor stuff as I am.
My question is this:
What are my remaining options?
At this point it's a toss up between:
a.) Switch majors
b.) Jump off a bridge
Neither of these choices are going to help me better understand this code base and get it compiling. Does anybody have any better ideas? Similar experiences? Sage wisdom to share?
Thanks a ton,
-Alex
It appears you're using the CResizableSheet and CResizeablePage from CodeProject. If you're using the compiled static lib from that page, you could try downloading the source and compiling that with the matching /MDd setting and using the .lib it outputs in the linker input section of your project. I'd also suggest doing a clean all (go to build->batch build->select all then click clean) and then try building again to make sure everything is up to date.
I hear nursing is a great program ...
At the risk of being pedantic, what you are fighting with are linker errors, not compiler errors. My basic approach to this would be to create a new solution, and start adding projects one at a time, getting each one to build in turn.
I would also seriously consider trying to standardize the settings of each project as much as possible. The easiest way to do this is to create empty projects in your new solution, and copy the existing code into them.
To start with you should assume the following settings (related to MFC):
Debug: Use MFC in a shared DLL, /MDd
Release: Use MFC in a shared DLL, /MD
MDd and MD are the same mode, but one links against debug libraries with extra information for debugging.
Then all you can do is work on one project at a time. Note that if you create a new solution as suggested, you'll need to rebuild the dependency tree between projects. (Right click on a project and choose 'Dependencies', you'll see what I mean.)
When you run into problems doing this, you should make friends with a senior developer at your workplace =).
Compile everything with the same runtime libraries. End of story.
I'm working on a fairly convoluted project in which I'm accessing classes written in plain-old-C++ from a project using C++/CLI. It's a Windows Forms GUI project that uses a lot of the same functions as its (non-CLI) C++ sister project.
In one of my classes that I'm trying to adjustment to work in both environments, I'm polling keypresses with this function:
inline bool IsKeyDown(unsigned char ch) const {
return (GetAsyncKeyState(ch) & (1u << 15)) != 0;
}
I'm getting both Unresolved Token and Unresolved External Symbol errors on
"extern "C" short __stdcall GetAsyncKeyState(int)" (?GetAsyncKeyState##$$J14YGFH#Z) referenced in function "public: bool __clrcall Engine::InputManager::IsKeyDown(unsigned char)const " (?IsKeyDown#InputManager#Engine##$$FQBM_NE#Z)
Obviously, the issue is related to GetAsyncKeyState() but I'm not sure what needs to be different for a CLI-friendly implementation. Can anyone direct me how to fix this? The function works properly in my non-CLI environment (and has for months). I'm very new to this CLI stuff so any help would be wonderful and no help could be too-specific.
If it helps, I'm using Visual Studio 2010 and compiling with the /clr parameter (not :pure or :safe).
The MSDN library provides the details of which header files and libraries need to be included for any particular function.
In this case, you need windows.h (which you must already have) and user32.lib (which is probably missing). So add
#pragma comment(lib, "user32.lib")
at the top of your code and all should be well. Alternatively, you could add user32.lib to the list of libraries in the project properties pages, remembering to do this for each configuration, e.g., debug as well as release.
Just got the same issue. The solution is to link against a .lib which has a respective symbol, which in this case is user32.lib.
I fixed a problem in Visual Studio by making a project use inherited values. Check this checkbox in your project properties and it should fix it:
i am trying to launch Printdlg() in my wince device but it is showing me linking error while building . this is the way i am doing it..
/// using pagesetupdlg....
PAGESETUPDLG info;
memset(&info,0,sizeof(info));
info.lStructSize=sizeof(info);
PageSetupDlg(&info);
or
////using printdlg...
PRINTDLG info;
memset(&info,0,sizeof(info));
info.lStructSize=sizeof(info);
PrintDlg(&info);
in both case it is showing me ---
error LNK2019: unresolved external
symbol PageSetupDlgW referenced in
function "public: void __cdecl
CAboutDlg::OnBnClickedButton1(void)"
(?OnBnClickedButton1#CAboutDlg##QAAXXZ)
PrinterTest.obj
plesae suggest me the solution...
regards,
mukesh
PageSetupDlg is definitely supported in the OS so that leaves two questions:
Are you linking to commdlg.lib?
Is the function included in your OS image/device SDK?
If #1 is true, then it's likely that #2 is false - at least it's not in the SDK. First, go look at the OS design. If you don't have access to that, you could try manually pulling it in - I'd try declaring it as an extern first and if that fails, try GetProcAddress.