unresolved external symbol "void __cdecl boost::tss_cleanup_implemented(void)" - c++

I was very surprised when I tried to search this error as I got only 4 results, two of which seem to be in Chinese. I am getting this error when compiling my project and boost sources alltogether. I searched the boost library and found this:
namespace boost
{
/*
This file is a "null" implementation of tss cleanup; it's
purpose is to to eliminate link errors in cases
where it is known that tss cleanup is not needed.
*/
void tss_cleanup_implemented(void)
{
/*
This function's sole purpose is to cause a link error in cases where
automatic tss cleanup is not implemented by Boost.Threads as a
reminder that user code is responsible for calling the necessary
functions at the appropriate times (and for implementing an a
tss_cleanup_implemented() function to eliminate the linker's
missing symbol error).
If Boost.Threads later implements automatic tss cleanup in cases
where it currently doesn't (which is the plan), the duplicate
symbol error will warn the user that their custom solution is no
longer needed and can be removed.
*/
}
}
My question is what's tss cleanup, why is it needed and how do I implement it.

I don't know about TSS, but to fix this linker error, you need to define
BOOST_THREAD_WIN32
and
BOOST_THREAD_BUILD_LIB
so boost/thread/src/win32/tss_pe.cpp implements the missing function (empty).
I assume there are few results on the Internet for this question, because the build scenario is rare. Most people do not build boost within their own project, but build boost with b2.

Related

Link error when using a _com_ptr_t (auto-created by #import) only in a template

After #importing a .tlb file, I tried to use one of the generated _com_ptr_t objects in a function template. This works fine if the functions I use are also used outside of a function template. However if it's only used in a function template, I get a link error.
Can anyone explain why this happens? I'm guessing it's to do with template instantiation but I'm not sure how the #import mechanism works.
Is it the expected behaviour?
Here's a minimal example which includes all combinations according to the value of COMPILE_OPTION.
Define only the regular function that uses the object (causing it to be instantiated)
Define only the function template (which doesn't cause the used function to be instantiated) - This is the problem case
Define both, this shows that if the object is used in a regular function the template option works as expected (and not as in case #2)
Code:
#import <mshtml.tlb>
#if COMPILE_OPTION & 1
int foo(MSHTML::IHTMLElementPtr elem) {
return elem->tagName.length();
}
#endif
#if COMPILE_OPTION & 2
template <class T>
int bar(T elem) {
return elem->tagName.length();
}
#endif
int main() {
#if COMPILE_OPTION & 2
bar(MSHTML::IHTMLElementPtr());
#else
foo(MSHTML::IHTMLElementPtr());
#endif
}
Now the following compile successfully:
cl Source.cpp /DCOMPILE_OPTION=1
cl Source.cpp /DCOMPILE_OPTION=3
But this one:
cl Source.cpp /DCOMPILE_OPTION=2
Produces the following (relevant error in bold):
Source.obj : error LNK2019: unresolved external symbol "public: class _bstr_t __thiscall MSHTML::IHTMLElement::GettagName(void)" (?GettagName#IHTMLElement#MSHTML##QAE?AV_bstr_t##XZ) referenced in function "int __cdecl bar<class _com_ptr_t<class _com_IIID<struct MSHTML::IHTMLElement,&struct __s_GUID const _GUID_3050f1ff_98b5_11cf_bb82_00aa00bdce0b> > >(class _com_ptr_t<class _com_IIID<struct MSHTML::IHTMLElement,&struct __s_GUID const _GUID_3050f1ff_98b5_11cf_bb82_00aa00bdce0b> >)" (??$bar#V?$_com_ptr_t#V?$_com_IIID#UIHTMLElement#MSHTML##$1?_GUID_3050f1ff_98b5_11cf_bb82_00aa00bdce0b##3U__s_GUID##B######YAHV?$_com_ptr_t#V?$_com_IIID#UIHTMLElement#MSHTML##$1?_GUID_3050f1ff_98b5_11cf_bb82_00aa00bdce0b##3U__s_GUID##B#####Z)
Source.exe : fatal error LNK1120: 1 unresolved externals
Notes:
A workaround is to use the raw COM methods
This is obviously a simplified version, the reason I'm using a template is that I'm using a library that has several types with common functionality that don't share a common base interface.
As per the comments, I unearthed this archived
KB Article which talks about the #pragma implementation_key compiler directive, which is used to improve performance when a type library has a lot of methods (over 1000 it seems), which mshtml.tlb does. This directive appears in the generated mshtml.tlh and .tli files. The article also talks about 'side-effects' which is perhaps what is happening here.
If you add the (undocumented!) 'no_function_mapping' modifier to the #import:
#import <mshtml.tlb> no_function_mapping
these #pragmas are removed and the code compiles and links.
[EDIT] A bit more explanation / guesswork. It seems MS have introduced the implementation_key pragma to try to improve the performance (somehow) of importing/imported type libraries: in cases where the caller might only use 2 functions out of 10,000's.
This is the section of the generated mshtml.tlh header that defines all the individual methods of the type library, all 51,468 of them, surrounded by the start_map_region and stop_map_region pragmas. The failing method GettagName() is number 190.
#pragma start_map_region("your_project_path\Debug\mshtml.tli")
__declspec(implementation_key(1)) void IHTMLStyle::PutfontFamily ( _bstr_t p );
__declspec(implementation_key(2)) _bstr_t IHTMLStyle::GetfontFamily ( );
//And on and on, down to the OP's failing method:
__declspec(implementation_key(190)) _bstr_t IHTMLElement::GettagName ( );
//and on and on, down to:
__declspec(implementation_key(51466)) ISVGElementInstancePtr ISVGUseElement::GetanimatedInstanceRoot ( );
__declspec(implementation_key(51467)) long ISVGElementInstanceList::Getlength ( );
__declspec(implementation_key(51468)) ISVGElementInstancePtr ISVGElementInstanceList::item ( long index );
#pragma stop_map_region
And here is the corresponding part in the mshtml.tli file which is #include'd by the mshtml.tlh header:
#pragma implementation_key(190)
inline _bstr_t MSHTML::IHTMLElement::GettagName ( ) {
BSTR _result = 0;
HRESULT _hr = get_tagName(&_result);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _bstr_t(_result, false);
}
The KB article refers to side effects of this mapping process. My guess is that when working with this pragmas, the MS compiler can detect explicit calls, eg:
MSHTML::IHTMLElementPtr elem();
elem->tagName.length();
but doesn't recognize the indirect use in the OP's template function.
The no_function_mapping qualifier to the #import statement tells the code generator not to add in the start_map_region, stop_map_region, and implementation_key pragmas, and you get 'regular' code, which recognizes the template substitution.
If the OP had chosen a smaller type library for their test, then this 'feature' may not have been apparent, as the implementation_key pragma might not have been used.
My minimal tests do not show any size change in the compiled executable, with the no_function_mapping modifier.
What the performance improvement might be is unclear. It might be a smaller memory footprint at run-time, as the dual interface doesn't have to keep a track of the dispId's that won't be called. My understanding is a bit vague, but using IDispatch::Invoke() requires determining which dispId will be invoked for a given function name, using some kind of map created after calling IDispatch::GetIdsOfNames(). This map would get pretty large for 50k+ methods, so perhaps the implementation_key approach is a way to reduce the size of the map (and hence the lookup time) to contain only those methods that will actually be used?

Linking to external functions in dynamic libraries with LLVM

In my project, I am emitting LLVM IR which makes calls to external functions in dynamic libraries.
I declare my external functions like:
declare %"my_type"* #"my_function"()
In the external library, functions are declared like:
extern "C" {
my_type* my_function();
}
When I compile the IR and run it, the process immediately crashes. The same behavior happens if I declare and call a nonsense function that I know doesn't exist, so I assume what's happening is that the external function is not being found/linked. (I don't think that the function itself is crashing).
I am using Python's llvmlite library for this task, and within the same process where I JIT and invoke my LLVM IR, I have another python library imported which requires the external dynamic library; so I assume that library is loaded and in-memory.
The procedure I'm using to compile and execute my LLVM code is basically the same as what's in this document, except that the IR declares and invokes an external function. I have tried invoking cos(), as in the Kaleidoscope tutorial, and this succeeds, so I am not sure what is different about my own library functions.
I have tried adding an underscore to the beginning of the function name, but I get the same result. (Do I need to add the underscore in the LLVM function declaration?)
How do I verify my assumption that the process is crashing because the named function isn't found?
How do I diagnose why the function isn't being found?
What do I need to do in order to make use of external functions in a dynamic library, from LLVM code?
Edit: It seems there is indeed trouble getting the function pointers to my external function. If I try to merely print the function address by replacing my calls with %"foo" = ptrtoint %"my_type"* ()* #"my_function" to i64 and return/print the result, it still segfaults. Merely trying to obtain the pointer is enough to cause a crash! Why is this, and how do I fix it?
Edit: Also forgot to mention— this is on Ubuntu (in a Docker container, on OSX).
I figured it out— I was missing that I need to call llvmlite.binding.load_library_permanently(filename) in order for the external symbols to become available. Even though the library is already in memory, the function still needs to be invoked. (This corresponds to the LLVM native function llvm::sys::DynamicLibrary::LoadLibraryPermanently()).
From this answer, it appears calling the above function with nullptr will import all the symbols available to the process.
Oddly, on OSX, I found that the external symbols were available even though load_library_permanently() had not been explicitly called— I'm not sure why this is (perhaps the OSX build of llvmlite itself happened to call the function with nullptr, as above?).

LNK2019, LPCTSTR, and C++ syntax in general

Allow me to preface this question with 2 comments:
1) I'm a C# developer, so I don't have much practice dealing with linker errors in C++ and some standard C++ syntax is a bit unfamiliar to me. I suspect this will be an easy question to the C++ gurus out there.
2) I'm not sure how to ask this question in a way that will be relevant to the masses but I'm open to suggestions/corrections from the community. The problem with lnk2019 errors is that it seems pretty individualized as to what the problem actually is. MSDN has an article that deals with the error generally and Stack Overflow already has a slew of questions with that tag and yet I still can't seem to solve my problem.
On to the details...
I was given an old (VS2005) C++ solution with 42 projects and was asked to try and get it to build. After doing quite a bit of twiddling, I've gotten it down to just 3 projects that won't build. I'd like to focus on just one of them because I think if we can figure that one out, I can do the same things to the other 2 projects to fix them.
Let's start with the error. As you can see, the project in question is named "HttpWire".
Deleting intermediate and output files for project 'Http Wire',
configuration 'Release|x64' Compiling... HttpWire.cpp
Compiling resources... Linking... Creating library
Release\AMD64\HttpWire.lib and object Release\AMD64\HttpWire.exp
HttpWire.obj : error LNK2019: unresolved external symbol "public:
__cdecl THttpWire::THttpWire(char const *)" (??0THttpWire##QEAA#PEBD#Z) referenced in function
CreateConnectionWire Release\AMD64\HttpWire.dll : fatal error LNK1120:
1 unresolved externals
Looks like the linker is upset because the function "CreateConnectionWire" is calling "THttpWire" but for some reason the linker is unable to find it. There is only 1 .cpp file in the project (HttpWire.cpp) and here it is:
#include "THttpWire.h"
BOOL WINAPI DllMain(HINSTANCE hDllInst, DWORD reason, LPVOID reserved)
{
return TRUE;
}
__declspec(dllexport) TConnectionWire *CreateConnectionWire(LPCTSTR connectionString)
{
return new THttpWire(connectionString);
}
__declspec(dllexport) void DeleteConnectionWire(TConnectionWire *connectionWire)
{
delete connectionWire;
}
The #include file, "THttpWire.h" lives in another project called "AirTime Core". It includes several other things and then has the following:
class THttpWire : public TConnectionWire
{
public:
THttpWire(LPCTSTR connectionString);
virtual ~THttpWire();
... (lots of other stuff) ...
}
And then, finally, we have THttpWire.cpp:
#include "THttpWire.h"
...
THttpWire::THttpWire(LPCTSTR connectionString) :
TConnectionWire(connectionString),
hWinHttp(NULL), hSession(NULL), hRequest(NULL),
opTimedOut(FALSE), asyncError(0),
headers(NULL), headersOffset(0), headersLength(0),
availData(0)
{
requestSent = new TSyncEvent(TRUE);
updateToString();
}
This syntax is a bit weird to me... what are we doing here? I mean, I realize this is a constructor, and since THttpWIre appears to inherit from TConnectionWire (according to the .h), then the ":TConnectionWire(connectionString)" makes sense (I'm assuming this is like C# appending ": base()" to constructors of objects that inherit from other objects), but then what is all the other stuff between that and the opening brace (note that TConnectionWire does not appear to inherit from anything else)?
SO...
After doing some searching on MSDN and SO, I've learned the following (please correct me if I'm wrong)
CreateConnectionWire is prefaced by __declspec(dllexport) which simply makes it available to other projects consuming this .dll (as discussed here)
LPCTSTR is a const char* (see MSDN). Note that my projects are set with "Treat wchar_t as Built-in Type: No (/Zc:wchar_t-)" in the property pages. (see the bottom of this article and also this article)
Right now, my primary suspicion is with LPCTSTR. Perhaps it is not defined the same in both projects, which would yield different method signatures... but I don't know how to check for this or fix it if that is the case. Or, perhaps the "/Zc:wchar_t-" thing is affecting it adversely?My next suspicion is that there is something in the string of methods listed in the constructor (with the syntax that I don't understand) that is causing some sort of problem and making the "THttpWire" constructor not available, generally.What do you think? I'd be happy to share any other bits that you think would be useful.
Other information that may or may not be helpful (I'll let you decide)
When I first started with this project, there were several .lib and .h files missing and I've had to go around trying to find them (examples were opends60.lib, mssoap30.lib, WinLUA.h, etc.). It is quite possible I don't have the same version the solution was originally built against.
The projects were all built with "_WIN32_WINNT=0x0400" defined, which appears to mean it was meant to be built against the Windows 2000 SDK (see MSDN). I found something that I thought was the Win 2000 SDK (the oldest one on here, but when I link to that, I get many more errors. Instead, I'm linking to the SDK version 6.1. HOWEVER, this causes WinHttp not to compile because "SOCKADDR_STORAGE" isn't defined for anything "_WIN32_WINNT<0x0501" (windows XP). THUS, I've redefined "_WIN32_WINNT=0x0501" for all of the projects that appear to be related to HttpWire. It is possible I missed one or two.
There is only 1 .cpp file in the project (HttpWire.cpp)
Well, that's a problem because clearly you need more than 1. You also need THttpWire.cpp since it contains the constructor code. The one that the linker cannot find.
Keep the C++ build model in mind, it is very different from C#. Source code files are separately compiled. And then the linker glues all the bits of code together to make the program. Those bits may come from an .obj file created from a .cpp file. Or they could come from a .lib file, a "container" of bits of code.
Which is the likely explanation since you mentioned an "AirTime Core" project. Project + Properties, Linker, Input, Additional Dependencies setting. You need to add the output of the "AirTime Core" project, whatever it is named.

operator new already defined in custom memory manager with library

Sorry for the poor title, but hopefully the description makes it clearer.
At the momemnt I have one main application which is built together with other libraries (like libpng, libvorbis,etc.). I'm trying to add libtheoraplayer to the main application, but I keep running into problems:
1) Linking to a pre-built library of llibtheoraplayer and including the appropriate header files gives me an error saying that pushMemoryManager cannot be found (part of our custom memory manager)
2) Building the library together with the main application results in a linker error "error LNK2005: "void * __cdecl operator new(unsigned int,void *)" (??2#YAPAXIPAX#Z) already defined in win32Mem.obj"
I'm not quite sure where to start debugging this. The main application does not support STL, and I started by changing references to STL in the libtheoraplayer to our own STL replacements, but I'm still getting error 2 as above after finding the offending files and changing them.
Any wild ideas?
Silence the linker error (convert to warning) with /FORCE and pray that there are no cross-library allocations ending up using different allocators.
It's rather difficult to replace allocation functions on Windows (NT or CE), because:
Dynamic symbols are loaded from specific libraries, so you will replace which allocator is used in your code, but not which is used in libraries you link dynamically. If you don't link dynamically and silence the linker error with /FORCE, it will do the right thing and override the allocators from standard library just fine.
With dynamic linking if code living in one library allocates and code living in another library frees, there will be mismatch in allocators used and thus probably crash. Unfortunately it may easily happen even if both functions are defined by the same library, but one of them is a template (so the instance lives in the library refering to it) and the other is not (so it lives in the library defining it).
They have some non-standard entry points to the allocator and sometimes use them from other code. We used to use duma library and actually managed to override both C (malloc/realloc/free) and C++ (operator new and operator delete) allocators, but hit a wall when we started using iostreams, where they allocate with the standard function, but free with something like __debug_free or the other way 'round.
On a side-note, the same is absolutely trivial on Linux, because in GNU libc malloc, realloc and free call the real allocator through pointers that you can easily override (operator new and operator delete just call malloc and free respectively basically everywhere).

Calling a Visual Basic DLL in C++

I have acquired a DLL that was created in Visual Basic from a third party vendor(Sensor DLL.dll). This DLL contains functions for talking to a sensor, and I need to call these functions from a Visual C++ program I am writing. The vendor will not provide a header file, and I do not know Visual Basic. If I had a header file this would be a 15 minute project... instead I am still struggling with it a week later. Please Help!
I am told one function (Get_Data) in the DLL is of the form:
Public Function Get_Data(ByVal Handle As String) As String
I have tried several methods for calling this Get_Data function with no success:
Method 1) the DllImport attribute
#using <mscorlib.dll>
using namespace System::Runtime::InteropServices;
namespace Sensor
{
[DllImport("Sensor DLL.dll", EntryPoint = "Get_Data", CharSet = System::Runtime::InteropServices::CharSet::Unicode)]
BSTR Get_Data(BSTR Handle);
}
//then I call the function
Sensor::Get_Data(Handle);
This method seems to be the closest I have gotten to a sloution. It compiles, but gives the following error when it runs:
An unhandled exception of type 'System.EntryPointNotFoundException' occurred
Additional information: Unable to find an entry point named 'Get_Data' in DLL 'Sensor DLL.dll'.
I have tried various datatype combinations/permutations besides BSTR including BSTR*, wchar_t, int, etc. It is possible that I missed one, but each datatype returns the same error.
Method 2) dllimport storage-class attribute
__declspec(dllimport) BSTR Get_Data(BSTR Handle);
//then I call the function
Get_Data(Handle);
This method is confusing to me because I don't specify the DLL I want to import from. I have copied the DLL to the project folder and I have added it to the project manually, so hopefully that means it can be found. When I compile the linker returns the following errors:
error LNK2028: unresolved token (0A00034F) "wchar_t * __cdecl Get_Data(wchar_t *)" (?Get_Data##$$FYAPA_WPA_W#Z) referenced in function "int __cdecl main(void)" (?main##$$HYAHXZ)
error LNK2019: unresolved external symbol "wchar_t * __cdecl Get_Data(wchar_t *)" (?Get_Data##$$FYAPA_WPA_W#Z) referenced in function "int __cdecl main(void)" (?main##$$HYAHXZ)
I suspected maybe this meant I should be using wchar_t or wchar_t* instead of BSTR, but changing to either datatype results in the same error.
Method 3) GetProcAddress
typedef BSTR (*Get_Data_Ptr)(BSTR Handle);
HINSTANCE LoadMe;
LoadMe = LoadLibraryA("Sensor DLL.dll");
if (!LoadMe)
std::cout << "\nDLL failed to load!\n";
Get_Data_Ptr LibMainGet_Data;
LibMainGet_Data = (Get_Data_Ptr)GetProcAddress(LoadMe,"Get_Data");
//then I call the function
LibMainGet_Data(Handle);
This will compile, but gives the following error when run:
An unhandled exception of type 'System.AccessViolationException' occurred
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
When I mouse over the various parts of this code in debug mode it seems that, like the first method, it was also unable to find the 'Get_Data' entry point in the DLL.
Has anyone called functions from a VB DLL using C++ when you haven't made the DLL yourself and you don't have .idl files, etc? Does anyone have a working example like this you could share?
Thanks!
A VB6 DLL is normally a COM server. You do in fact have the equivalent of a .h file, it has a type library embedded in it. Start this off with Project + Properties, Common Properties, Framework and References. Add New Reference button, Browse tab, select the DLL.
Next, View + Object Browser. You should see the generated Interop library in the list. Open the node to see what is there. You write normal managed code, like gcnew, to create the COM object and call the interface methods. You do need some minimum documentation on the available methods to have a guess at how they should be called.
I believe the missing piece is the calling convention. C++ has its own function calling convention different than VB6 (I assume VB6 since you haven't stated VB.NET explicitly). VB6 uses STDCALL convention whereas C++, depending on the vendor, uses a different calling convention termed __cdecl, which is why you see the __cdecl in the compiler error line for method #2. It assumes your external function is using that calling convention by default. Calling convention is a set of rules describing how functions call one another; specifically about how registers are used, what order parameters are delivered in, how by-value / by-reference is determined, etc.
I would suggest sticking with method #3 since method #1 is for Managed C++ which is not standard C++, and method #2 is unfamiliar to me and looks a bit ambiguous. What you want to try is declaring the function pointer typedef to use STDCALL.
typedef BSTR (__stdcall *Get_Data_Ptr)(BSTR Handle);
In the OLE/COM viewer, in order to view the COM type library in a dll/exe/... you have to open it by using "File->View TypeLib" instead of "File->Bind to File"
It sounds like the DLL isn't actually exporting a function named Get_Data. Open up a command prompt and use dumpbin to get the list of exports of the DLL, e.g.:
dumpbin /exports "Sensor DLL.dll"
(dumpbin.exe is located in VC\bin within your Visual Studio install folder, which istypically something like C:\Program Files\Microsoft Visual Studio 10.0).
Then, replace Get_Data with the actual entry point and see if you have any better luck.
A Visual basic program normally needs a runtime to execute.
If you have a COM object (implemented in VB) use the COM API to communicate with it from C++. You will have to register the COM first. Here is a thread that explains hot to do that: http://forums.devx.com/archive/index.php/t-87059.html
If you use a .NET language, use the method of Hans Passant with a reference that will create an interop dll for you. This is far much easier.
Method 1: Do not do that, if you have a COM object that you want to use from a .NET environment, reference it.
Method 2: You get errors because you lack the the .lib file to properly link to the DLL (statically dynamically linking)
Method 3: Would be a pure dynamic solution but you have to know the exact names of the methods in the DLL. These may vary according to the parameters and calling convention used. This is very similar (actually identical, I would say) to the issue you face with your Method 1 solution. The name of the method is for yure not "Get_Data" but something else. With a tool like the dependency viewer you can have a look at the exported names.
Even Method 3 with the right names is likely to fail because if it is a COM object you will need some environment called Appartment to use the COM objects. You "enter" this appartment by calling CoInitialize. This creates some magical stuff in the TLS (Thread Local Storage) to perform the COM magic. I hope this explains why your tries will be pointless if the DLL you have is happening to be a COM component, what is quite likely according to the ATL like naming we can see.
EDIT:
I forgot to say that you can also easily see what is inside the dll if it is a COM with the OLE/COM Viewer (normally if you have a compiler you will have such a tool around).