Can not use CString parameter (which was built in VC6.0) at VC2019 - dll

I have an old DLL which was built in VC6.0.
And I want to use this DLL at VC2019 project.
This DLL file is a MFC DLL, and contains a lot of classes and functions.
There is no problem for using classes and functions except these three functions (which contains CString parameter).
The exported DLL functions (class functions) are like below:
class CColorListCtrl : public CListCtrl
{
...
public:
int AddColumn(CString szHeaderStr, int nColWidth);
int AddItem(CString szItem);
bool SetItemTip(int nRow, int nCol, CString szTip);
...
}
And the link errors are like below:
error LNK2001: unresolved external symbol "public: int __thiscall CColorListCtrl::AddColumn(class ATL::CStringT<char,class StrTraitMFC<char,class ATL::ChTraitsCRT<char> > >,int,int)" (?AddColumn#CColorListCtrl##QAEHV?$CStringT#DV?$StrTraitMFC#DV?$ChTraitsCRT#D#ATL#####ATL##HH#Z)
error LNK2001: unresolved external symbol "public: int __thiscall CColorListCtrl::AddItem(class ATL::CStringT<char,class StrTraitMFC<char,class ATL::ChTraitsCRT<char> > >)" (?AddItem#CColorListCtrl##QAEHV?$CStringT#DV?$StrTraitMFC#DV?$ChTraitsCRT#D#ATL#####ATL###Z)
error LNK2001: unresolved external symbol "public: bool __thiscall CColorListCtrl::SetItemTip(int,int,class ATL::CStringT<char,class StrTraitMFC<char,class ATL::ChTraitsCRT<char> > >)" (?SetItemTip#CColorListCtrl##QAE_NHHV?$CStringT#DV?$StrTraitMFC#DV?$ChTraitsCRT#D#ATL#####ATL###Z)
The DLL exported functions are like below:
?AddColumn#CColorListCtrl##QAEHVCString##HH#Z
?AddItem#CColorListCtrl##QAEHVCString###Z
?SetItemTip#CColorListCtrl##QAE_NHHVCString###Z
For fix this problem, I changed Project Character Set (Project Setting -> General -> Character Set) as "Use Multi-Byte Character Set", but the problem is not solved.
I noticed that CString class was changed, so the CString classes at VC6 and VC2019 are different.
I have no idea to resolve this prblem. Also I can not change DLL, because I removed the project for this DLL.
Please help me.
Thank you.

CString in VC++ 6 and VC++ 2019 are not compatible with each other because there is a difference.
That is, if you use CString as a parameter for the export function in VC6 dll, you cannot directly call VC6 dll in VS2019.
I suggest one solution:
First, create a dll that acts as a repeater in vc6. The export function of this dll uses, for example, LPCTSTR as a parameter. Let this dll be A.dll and the original dll be B.dll.
Inside the A.dll, the export function of the B.dll is called and the result is converted to LPCTSTR and returned.
VS2019 calls the export function of A.dll. LPCTSTR is compatible between VS2019 and VS6, so you can solve your problem in this way.

There is some notes in this article (CStringT Class) where it states:
If your code contains the workaround for linker errors that is
described in Exporting String Classes Using CStringT, you
should remove that code. It is no longer needed.
I notice that the subsequent article that it refers to does state:
In the past, MFC developers have derived from CString to specialize
their own string classes. In Microsoft Visual C++.NET (MFC 8.0), the
CString class was superseded by a template class called CStringT.
It provides an explanation of what you can do to resolve linker issues.

Related

How to load a dll into VS c++, which acts like a wrapper to another CAPL code?

I am trying to reference functions in a 3rd party dll file through CAPL Script. Since, I cannot directly call them, I am trying to create a wrapper which exports the functions in the dll.
int MA_Init(char *TbName, int Option); is the function in the dll file.
The wrapper code for this is
int CAPLEXPORT far CAPLPASCAL CMA_Init(char *TbName, int Option)
{
return MA_Init(*TbName, Option);
}
I am trying to use
HINSTANCE DllHandel = loadlibrary("C:\\Turbo.dll"); to load the library and
typedef int(*TESTFnptr)(char, int);
TESTFnptr fn= (TESTFnptr)getprocaddress(DllHandle, "MA_Init"); to resolve the function address.
However the compiler says the function "MA_Init()" is not defined. I am not sure if I am using the correct procedure to load the dll into my visual C++ project. Has anyone tried doing this or knows how it's done? Thank you very much.
The standard procedure would be to include the corresponding .lib file to VS project. Go to "Project - Properties - Configuration Properties - Linker - Additional Dependencies" and add turbo.lib on a new line. Then you'll need to include the corresponding turbo.h header file which contains the definition for MA_Init function.
In this case, you'll be able to call MA_Init directly, as you do now. The compiler will happily find the definition of MA_Init in the header file, and the linker will find the reference to MA_Init in the .lib file.
If you don't have turbo.h file, you can create one yourself provided you know the prototypes of all functions you want to use. Just put definitions like
int MA_Init(char *TbName, int Option);
there and include it.
If you don't have turbo.lib file, you'll have to proceed with LoadLibrary and GetProcAddress. Obviously, you cannot call MA_Init by name in this case, since it is undefined. You'll have to call the pointer returned by GetProcAddress instead:
TESTFnptr fn = (TESTFnptr)GetProcAddress(DllHandle, "MA_Init");
int CAPLEXPORT far CAPLPASCAL CMA_Init(char *TbName, int Option)
{
return fn(TbName, Option);
}
PS. Notice I removed the start in front of TbName?
PPS. Don't forget to include your wrapper function, CMA_Init, to CAPL_DLL_INFO_LIST, otherwise it will not be accessible in CANoe/CANalyzer.

c++ clr with ZeroC Ice 3.5.1

I have a need to compile an existing message library generated using ZeroC's ICE with c++ clr.
I've been at this for a while and I'm having no luck.
I have a very simple .ice message file defined.
Upon generating the cpp and h files for this, I try to compile them into a .dll.
My slice2cpp command line args are
C:\Program Files (x86)\ZeroC\Ice-3.5.1\bin\slice2cpp.exe --depend --dll-export=ENABLE_DLL -I"C:\Program Files (x86)\ZeroC\Ice-3.5.1\slice" -I".\.." --underscore "E:\test\platform\platform\testMessage.ice"
This generates me a testMessage.cpp and testMessage.h files.
Upon attempting to compile these, I get the error:
Error 7 error LNK2028: unresolved token (0A00098D) "class IceUtil::Shared * __cdecl IceInternal::upCast(class IceInternal::ObjectFactoryManager *)" (?upCast#IceInternal##$$FYAPEAVShared#IceUtil##PEAVObjectFactoryManager#1##Z) referenced in function "public: __cdecl IceInternal::Handle<class IceInternal::ObjectFactoryManager>::Handle<class IceInternal::ObjectFactoryManager>(class IceInternal::Handle<class IceInternal::ObjectFactoryManager> const &)" (??0?$Handle#VObjectFactoryManager#IceInternal###IceInternal##$$FQEAA#AEBV01##Z) E:\test\platform\platform\testMessage.obj platform
As per usual with Ice, I have to link the Iced.lib and IceUtild.lib files.
I compile with no pre compiled headers and /clr option on (not pure clr or safe)
using VS2013. The body of the testMessage.ice file is very simple.
#ifndef _MESSAGE_ICE_
#define _MESSAGE_ICE_
module messaging {
class Message
{
string clientId;
string origin;
string destination;
string messageType;
string suffix;
};
sequence<Message> MessageSeq;
class NonQueuedMsg extends messaging::Message {};
};
#endif
Compiling without the CLR option on results in success.
I imagine this is all caused by my lack of familiarity with c++ clr.
Any help would be appreciated.
I had the same problem after the migration of my projects to vs 2013.
The project c++ with ice compile fine
but the project c++/cli with ice don't links.
I fixed linking problem in ObjectFactoryManagerF.h :
#ifdef __cplusplus_cli
IceUtil::Shared* upCast(ObjectFactoryManager* p) { return (IceUtil::Shared*) p; };
#else
IceUtil::Shared* upCast(ObjectFactoryManager* );
#endif
I stopped trying to make C++/CLI and ICE-generated code work together after I read on their forum here that they didn't support it.
What I've done.. I've made native static library on the client's side where I had C++/CLI. Static library fully encapsulated all communication stuff and was referenced from C++/CLI part. As a result I've got a Mixed (C++/CLR) Recommended Rules assembly. It works fine plus I've got easier portable application.

unresolved external symbol while using a library

i have a header file named NetworkInterfaceInfoProvider.h.
in this header file i declare a class as follow:
#ifndef INETWORK_INTERFACE_INFO_PROVIDER_H
#define INETWORK_INTERFACE_INFO_PROVIDER_H
#pragma once
/*#include "stdafx.h"*/
#include "IConfig.h"
#include "NetworkAddapterAddresses.h"
#include "InstaledAddapters.h"
namespace IRNetwork
{
class CLASS_DECLSPEC INet;
struct CLASS_DECLSPEC GenericIPAddress;
/*
* provide information about all network interface related adapters such as installed interfaces , addresses , best routes and ...
* TO DO: implement Other OS's
*/
class CLASS_DECLSPEC INetworkInterfaceInfoProvider
{
public:
INetworkInterfaceInfoProvider(void);
~INetworkInterfaceInfoProvider(void);
int32_t GetBestRouteTo(char* destIp,uint16_t port,ip_t *ip);
int32_t GetBestRouteTo(GenericIPAddress* ip);
private:
INet* snet;
};
}
#endif
when i want to use it in my console application i got following linker error
*note: the library of above code has been linked to my console application.
CLASS_DECLSPEC is dll import/export definition*
error LNK2019: unresolved external symbol "__declspec(dllimport)
public: int __thiscall
IRNetwork::INetworkInterfaceInfoProvider::GetBestRouteTo(char
,unsigned short,char ()[65])" (_imp?GetBestRouteTo#INetworkInterfaceInfoProvider#IRNetwork##QAEHPADGPAY0EB#D#Z)
referenced in function "void __cdecl test_adapters(void)"
(?test_adapters##YAXXZ) testDhcpv4.obj testDhcpv4
what is wrong here?
Hmm. From the error I would say importing looks good. So maybe there was an error while exporting. Assuming you are using Visual Studio, you can use dumpbin to check if your dll is exporting correctly:
Open the Visual Studio Command Prompt (available from the windows start menu) and type
dumpbin /EXPORTS yourlib.dll
Then you should see our export, something like (dump from one of my dlls):
...
170 A9 00108120 ??1AbstractParam#param#core#megamol##UAE#XZ = ??1BoolParam#param#core#megamol##UAE#XZ (public: virtual __thiscall megamol::core::param::BoolParam::~BoolParam(void))
...
If the function your are calling is not listed, you should doublecheck if your dllexport is set correctly while building your dll.
If the function is listed, but looks different, you should check for the calling conventions to be the same for your application and your dll.
If the function is listed and the name looks identical to what the error message says, doublecheck if you are linking the import library of the dll correctly.
Also check if the runtime-configuration is the same for your application and your dll (e.g. Multi-Threaded-Dll or Multi-Threaded-Debug-Dll).

How to convert from C# ref type to CLI\C++ ^% type

I am writing an application in Managed C++ (CLI\C++). In which I am using a library (.dll file) which is written in C#.
In a file I am encountering a problem.
I am implementing functions of an interface which is written in the library.
The declaration of a function in the library is as given below:
COMWORKSPACELib.IWorkspaceEvents.WorkspaceMessage(int, string, COMWORKSPACELib.EnumNotificationCode, COMWORKSPACELib.EnumNotificationType, string, ref COMWORKSPACELib.EnumNotificationReply);
When I write the same code in CLI\C++ the declaration is like:
WorkspaceMessage(int workspaceToken, String ^description, EnumNotificationCode ^code, EnumNotificationType ^type, String ^source, EnumNotificationReply ^%action);
Here, the compiler is giving me error that the “class must provide an implementation for the interface method”. Because the parameters passed in both function declarations are syntactically different.
Is there any alternative way to match the library declaration?
If I remove the “^’ & ‘%’ to match the library declaration then it gives further errors in the code.
Are EnumNotifcationCode, EnumNotificationType, and EnumNotficationReply all enums? That is, are they value types? If so, then it should be declared as follows:
WorkspaceMessage(int workspaceToken,
String^ description,
EnumNotificationCode code,
EnumNotificationType type,
String^ source,
EnumNotificationReply% action);

Unresolved external symbol error

I am getting the following error in my VC++ COM project. What is the problem in linking the lib files here?
Error 4 error LNK2019: unresolved external symbol _BVUOpen#8 referenced in function "unsigned int __stdcall AFunc(void *)" (?AFunc##YGIPAX#Z) CBillAcceptor.obj BillAcceptorCOM
Here are the explanation of the LNK2019 error : MSDN.
Look for a problem of definition about BVUOPen symbol ! The problem si inside the method AFunc Maybe, you haven't declare it correctly or haven't link the library or haven't export the symbol...
Probably, you need to link against some external library that contains the object code for the BVUOpen function. The name of that library is not obvious from your error message, but it should be possible to work out from the documentation you are coding from.