I have seen:
Convert BSTR to CHAR* and CHAR* to BSTR in C
Problems converting BSTR to char *
Convert BSTR to char*
using these question I am attempting to convert a BSTR to a char* via
#include "comutil.h"
STDMETHODIMP CServer::Initialise(BSTR strCmdFilePath,
VARIANT_BOOL bDiagErr, VARIANT_BOOL bProcErr, BSTR* RESULT)
{
char *p = _com_util::ConvertBSTRToString(strCmdFilePath);
...
}
but I am getting:
Error 1 error LNK2019: unresolved external symbol "char * __stdcall _com_util::ConvertBSTRToString(wchar_t *)" (?ConvertBSTRToString#_com_util##YGPADPA_W#Z) referenced in function "public: virtual long __stdcall CServer::Initialise(wchar_t *,short,short,wchar_t * *)" (?Initialise#CServer##UAGJPA_WFFPAPA_W#Z)
Why am I getting this error?
Your project is not linking the required library. Which is comsuppw.lib for the Release build, comsuppwd.lib for the Debug build. Do note that you can always see the required library in the MSDN article. It is annotated at the bottom of the article. "Header" tells you what you need to #include, "Lib" tells you what you need to link.
There's an easier way for this library, the best way to get the linker instruction embedded so it is automatic is by #including the .h file that contains the #pragma comment. Fix:
#include <comdef.h> // Added
#include <comutil.h>
Related
I normally work in c# and am out of my wits for this one . I used Walkthrough: Creating and Using a Dynamic Link Library (C++) to create a Dynamic Link Library.
I have defined two methods as shown below
DeveloperConsoleManager.h
#pragma once
#include "atlstr.h"
#ifdef DEVCONSOLEMANAGER_EXPORTS
#define DEVCONSOLEMANAGER_API __declspec(dllexport)
#else
#define DEVCONSOLEMANAGER_API __declspec(dllimport)
#endif
namespace DeveloperConsoleManager
{
class DeveloperConsoleLogic
{
public:
// Returns a + b
static DEVCONSOLEMANAGER_API double Add(double a, double b);
static DEVCONSOLEMANAGER_API bool CheckforValidFile(CString fileName);
};
}
DeveloperConsoleManager.cpp
// DeveloperConsoleManager.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "DeveloperConsoleManager.h"
namespace DeveloperConsoleManager
{
double DeveloperConsoleLogic::Add(double a, double b)
{
return a + b;
}
bool DeveloperConsoleLogic :: CheckforValidFile(CString fileName)
{
return false;
}
}
I use these methods in a .cpp file in a different project (type: Application (.exe)). When I Build the solution, there are following linker errors
Warning 1 warning C4273: 'DeveloperConsoleManager::DeveloperConsoleLogic::Add' : inconsistent dll linkage e:\md_69\developerconsolemanager\developerconsolemanager.cpp 10
Warning 2 warning C4273: 'DeveloperConsoleManager::DeveloperConsoleLogic::CheckforValidFile' : inconsistent dll linkage e:\md_69\developerconsolemanager\developerconsolemanager.cpp 16
Error 3 error LNK2028: unresolved token (0A0004F1) "public: static bool __cdecl DeveloperConsoleManager::DeveloperConsoleLogic::CheckforValidFile(class ATL::CStringT > >)" (?CheckforValidFile#DeveloperConsoleLogic#DeveloperConsoleManager##$$FSA_NV?$CStringT#_WV?$StrTraitMFC_DLL#_WV?$ChTraitsCRT#_W#ATL#####ATL###Z) referenced in function "public: void __thiscall CSaSsiConsoleUi::UploadSsiCheck(void)" (?UploadSsiCheck#CSaSsiConsoleUi##$$FQAEXXZ) E:\MD_69\DeveloperConsoleUI\SaSsiConsoleUI.obj
Error 4 error LNK2019: unresolved external symbol "public: static bool __cdecl DeveloperConsoleManager::DeveloperConsoleLogic::CheckforValidFile(class ATL::CStringT > >)" (?CheckforValidFile#DeveloperConsoleLogic#DeveloperConsoleManager##$$FSA_NV?$CStringT#_WV?$StrTraitMFC_DLL#_WV?$ChTraitsCRT#_W#ATL#####ATL###Z) referenced in function "public: void __thiscall CSaSsiConsoleUi::UploadSsiCheck(void)" (?UploadSsiCheck#CSaSsiConsoleUi##$$FQAEXXZ) E:\MD_69\DeveloperConsoleUI\SaSsiConsoleUI.obj
Error 5 error LNK1120: 2 unresolved externals E:\MD_69\Debug\DeveloperConsoleUi.exe
There is no linker error for the "Add" method.
I have already included "DeveloperConsoleManager.lib" in Linker -> Input -> Additional Dependencies. Please help me find out what exactly am I doing wrong.
I would be glad to add any additional information needed.
Thanks to #Igor Tandetnik and the awesome thing that is internet, I figured it out. I am adding it as an answer so that some one else might benefit.
The problem was with CString. The project in which the function was defined was a dynamic link library (dll) and the call was being made from an MFC application. Now, the issue was that, MFC uses for CString while the non-MFC dll uses .
CString in is defined as:
typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;
while in is defined as:
typedef CStringT< TCHAR, StrTraitATL< TCHAR > > CString;
This, as you can clearly see is different. The workaround I used was using CAtlString instead of CString . However, please feel free to suggest any better way if you come across.
I have the code presented later using Xerces-c, which can be built as a static or dynamic library. Failing to include of course results in a compiler error, however when I add #include <xercesc/util/PlatformUtils.hpp> visual studio 2012 gives me a linker errors saying:
1>main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: static void __cdecl xercesc_3_1::XMLPlatformUtils::Initialize(char const * const,char const * const,class xercesc_3_1::PanicHandler * const,class xercesc_3_1::MemoryManager * const)" (__imp_?Initialize#XMLPlatformUtils#xercesc_3_1##SAXQBD0QAVPanicHandler#2#QAVMemoryManager#2##Z) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: static void __cdecl xercesc_3_1::XMLPlatformUtils::Terminate(void)" (__imp_?Terminate#XMLPlatformUtils#xercesc_3_1##SAXXZ) referenced in function __catch$_main$0
1>main.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: static char const * const xercesc_3_1::XMLUni::fgXercescDefaultLocale" (__imp_?fgXercescDefaultLocale#XMLUni#xercesc_3_1##2QBDB)
Based on the dllimport part of the error it seems that it's failing to find a dll. This is confirmed by that when I build Xerces-c as a dynamic library and link to it the error goes away. However if I build Xerces-c as a static library and link to it the same error remains. So my question is why am I getting an error asking for a dll when I'm including and linking to a static library?
using namespace xercesc;
int main(int argc, char* argv[])
{
std::ifstream inputFile(argv[1]);
char c = inputFile.get();
while (inputFile.good()) {
std::cout << c;
c = inputFile.get();
}
try {
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch) {
// Do your failure processing here
return 1;
}
// Do your actual work with Xerces-C++ here.
//XercesDOMParser parser;
//parser.useScanner(XMLUni::fgDGXMLScanner);
XMLPlatformUtils::Terminate();
// Other terminations and cleanup.
return 0;
}
You need to compile your application with XERCES_STATIC_LIBRARY preprocessor macro to disable DLL import/export for Xerces library.
Also check that you link against static version of .lib files.
Following error is coming when I am compiling the project "proj1" code which is using xyz.lib (it is a different project that got compiled successfully).
Error 3 error LNK2019: unresolved external symbol "int __cdecl Vsnprintf16(unsigned short *,unsigned int,unsigned short const *,char *)" (?Vsnprintf16##YAHPAGIPBGPAD#Z) referenced in function "int __cdecl eastl::Vsnprintf(wchar_t *,unsigned int,wchar_t const *,char *)" (?Vsnprintf#eastl##YAHPA_WIPB_WPAD#Z) File : xyz.lib(abc.obj)
abc.cpp has calls to function sprintf .
When I am moving all the code of abc.h and abc.cpp to some other lets say def.h and def.cpp file which is already present in xyz project then all works fine, no linking error. I don't know why.
I have used all the includes that were used in file def.cpp in abc.cpp but same error.
When I am removing the sprintf() calls from abc.cpp then also all works fine.
Please if anyone can suggest why this is happening. Thanks
I have searched msdn and also VS2015 and VS2005 source code folders and found no definition or declaration of Vsnprintf16.
I have not used eastl but it looks like you should define this function by yourself, you can find examples in following links:
https://github.com/BSVino/Digitanks/blob/master/common/eastl.cpp
https://github.com/electronicarts/EASTL/blob/master/test/source/main.cpp
for reference I include it here:
// EASTL also wants us to define this (see string.h line 197)
int Vsnprintf8(char* pDestination, size_t n, const char* pFormat, va_list arguments)
{
#ifdef _MSC_VER
return _vsnprintf(pDestination, n, pFormat, arguments);
#else
return vsnprintf(pDestination, n, pFormat, arguments);
#endif
}
int Vsnprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, va_list arguments)
{
#ifdef _MSC_VER
return _vsnwprintf((wchar_t*)pDestination, n, (wchar_t*)pFormat, arguments);
#else
char* d = new char[n+1];
int r = vsnprintf(d, n, convertstring<char16_t, char>(pFormat).c_str(), arguments);
memcpy(pDestination, convertstring<char, char16_t>(d).c_str(), (n+1)*sizeof(char16_t));
delete[] d;
return r;
#endif
}
I am trying to create a rather simple project in native c++ that calls a a managed dll.
this how my native c++ code looks:
// MyCppStud.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "MyStudWrapper\MyStudentWrapperWrapper.h"
int _tmain(int argc, _TCHAR* argv[])
{
char * path = "C:/Users/rami.schreiber/documents/visual studio 2013/Projects/TestProj/test.xml";
MyStudentWrapperWrapper* student = new MyStudentWrapperWrapper();
// student->GetStudent(path);
return 0;
}
and here are the .h and .cpp files for the managed dll (compiled with /clr)
//MyStudentWrapperWrapper.h
#pragma once
//#ifdef THISDLL_EXPORTS
#define THISDLL_API __declspec(dllexport)
/*#else
#define THISDLL_API __declspec(dllimport)
#endif*/
class MyStudentWrapper;
class THISDLL_API MyStudentWrapperWrapper
{
private:
MyStudentWrapper* _Impl;
public:
MyStudentWrapperWrapper();
MyStudentWrapperWrapper(MyStudentWrapper* student);
~MyStudentWrapperWrapper();
MyStudentWrapperWrapper* GetStudent(const char* path);
void SaveStudent(MyStudentWrapperWrapper* student, const char* path);
};
// MyStudentWrapperWrapper.cpp
#pragma once
#include "stdafx.h"
#include "MyStudWrapper.h"
#include "MyStudentWrapperWrapper.h"
MyStudentWrapperWrapper::MyStudentWrapperWrapper()
{
_Impl = new MyStudentWrapper;
}
when i build the solution i get a link error
1>MyCppStud.obj : error LNK2019: unresolved external symbol "public: __thiscall MyStudentWrapperWrapper::MyStudentWrapperWrapper(void)" (??0MyStudentWrapperWrapper##QAE#XZ) referenced in function _main
1>c:\users\...\documents\visual studio 2013\Projects\MyStudentProj\Debug\MyCppStud.exe : fatal error LNK1120: 1 unresolved externals
From what I understand I am not referencing the the .lib file correctly and therefor the linker does not recognize the c'tor for my wrapper class.
can someone please explain how to correctly reference the dll to my c++ project.
thank you very much!
I'm trying to build a console application without using the CRT, or any other imports than kernel32.lib in any case. I get my code to compile, but can't wrap the linker around a few problems:
unresolved external symbol #__security_check_cookie#4
unresolved external symbol "int __cdecl FreeLibrary(void *)" (?FreeLibrary##YAHPAX#Z)
unresolved external symbol "void * __cdecl LoadLibraryW(wchar_t *)" (?LoadLibraryW##YAPAXPA_W#Z)
unresolved external symbol "int (__cdecl*__cdecl GetProcAddress(void *,char *))(void)" (?GetProcAddress##YAP6AHXZPAXPAD#Z)
unresolved external symbol _wmainCRTStartup
FreeLibrary, LoadLibraryW and GetProcAddress I've brought in to program explicitly, not using windows.h:
#pragma comment(lib, "kernel32.lib")
typedef int(*FARPROC)();
void* LoadLibraryW( wchar_t* lpLibFileName );
FARPROC GetProcAddress( void* hModule, char* lpProcName );
int FreeLibrary( void* hLibModule );
I suppose something is wrong with my prototypes.
However, the bigger problem are __security_check_cookie and _wmainCRTStartup, which obviously have something to do with the CRT.
So I'm wondering how I'd go about overriding the default int wmain(int argc, wchar_t* argv[]) for entrypoint, and how to get rid of whatever the security cookie is.
_wmainCRTStartup is the function that calls wmain()
IIRC it should be available in some .o file that you can link with, look in your lib directory.
Maybe this is useful reading too: Reduce EXE and DLL Size with LIBCTINY.LIB (and Matt Pietrek rocks :-)
Well, answering myself here to sum up, in case someone else finds this page looking for info.
As MSalters advised, the security cookie code can be stolen from the CRT source, but doing that I found that the /GS- compiler flag can be used to avoid the security stuff altogether.
As SoapBox said, the API functions need to be __stdcall, as well as the entry point does.
I fixed the entry point issue with linker command line flag /entry:wmain.
And finally, as Tomek pointed out, the API functions gotta be in extern C!
So:
#pragma comment(lib, "kernel32.lib")
typedef int(*FARPROC)();
extern "C" {
void* __stdcall LoadLibraryW( wchar_t* lpLibFileName );
FARPROC __stdcall GetProcAddress( void* hModule, char* lpProcName );
int __stdcall FreeLibrary( void* hLibModule );
typedef int (__stdcall *f_MessageBoxW_t)( unsigned long hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned long uType);
f_MessageBoxW_t fnMsg;
void* hUser;
};
int __stdcall wmain(int argc, wchar_t* argv[])
{
hUser = LoadLibraryW( L"user32.dll" );
fnMsg = (f_MessageBoxW_t)GetProcAddress( hUser, "MessageBoxW" );
fnMsg( 0, L"foo", L"bar", 0 );
FreeLibrary( hUser );
return 0;
}
More correct entry point declaration will be:
int __stdcall wmain(PVOID ThreadParam)
Without CRT entry point called directly by BaseThreadInitThunk. Its passes pointer to something, but not argc+argv.
You can look in Windows.h to see the prototypes you need for your kernel32 imports. In general, windows functions are defined WINAPI which is actually __stdcall and not __cdecl. That will fix that problem at least.
As for your other problem, you need to explore the linker commandline arguments and see if there is a way to get it to not look for things from CRT. I don't know if there is a way to do that or not. But you're going to have to find a way or define those functions your self (which you probably don't want to do).
I'd recommend just using a different compiler/linker.
You need to declare windows.h functions as extern "C".
The proper entry point is main(), not wmain() (since you're compiling a console app).
The security cookie code can be nicked from the CRT source code; no need to link it in.