c++ clr with ZeroC Ice 3.5.1 - c++-cli

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.

Related

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

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.

Porting project from ICCAVR to Atmel Studio 7.0 _flash problem

I'm currently porting a large project to Atmel Studio from ICCAVR as I need to use some of the ASF libraries for the project I'm working on.
I'm getting this error with the code example below in regards to trying to convert the following line to Atmel Studio
void debugoutf(__flash char * header, __flash char * msg);
Error pointer targeting address space '__flash' must be const in
function parameter 'header'
I tried using the macro in the documentation so that it can compile in Atmel Studio.
#ifndef FLASHVAR_H_
#define FLASHVAR_H_
#include <avr/pgmspace.h>
#if defined(__ICCAVR__) // IAR C Compiler
#define FLASH_DECLARE(x) __flash x
#endif
#if defined(__GNUC__) // GNU Compiler
#define FLASH_DECLARE(x) x __attribute__((__progmem__))
#endif
IAR to AVR Conversion
void debugout(FLASH_DECLARE (char * header), char * msg);
My question is have I done the conversion correctly, as I don't think I've done it correctly as nothing is getting printed out in my UART debugging.
The problem with using __attribute__((__progmem__)) on a variable is that whenever you want to read data from such a variable, you can't just access it in the usual way that you would access a variable from RAM. Instead, you have to use special functions provided by the avr/pgmspace.h header in avr-libc, like pgm_read_byte.
That's pretty annoying, but you don't have to do it that way because why they added named address spaces like __flash to recent versions of GCC (assuming you are using C, not C++). I recommend you stop using __attribute__((__progmem__)) and use __flash instead, if your version of GCC supports it. If the compiler gives you an error or warning because it expects items stored in flash to be marked as const, you can simply add const to the declaration/definition (in the right position). If you have trouble doing that, please post a new question or edit this question so it contains a MCVE.
For the example code you gave, you should try writing:
void debugoutf(const __flash char * header, const __flash char * msg);

Using system symbol table from VxWorks RTP

I have an existing project, originally implemented as a Vxworks 5.5 style kernel module.
This project creates many tasks that act as a "host" to run external code. We do something like this:
void loadAndRun(char* file, char* function)
{
//load the module
int fd = open (file, O_RDONLY,0644);
loadModule(fdx, LOAD_ALL_SYMBOLS);
SYM_TYPE type;
FUNCPTR func;
symFindByName(sysSymTbl, &function , (char**) &func, &type);
while (true)
{
func();
}
}
This all works a dream, however, the functions that get called are non-reentrant, with global data all over the place etc. We have a new requirement to be able to run multiple instances of these external modules, and my obvious first thought is to use vxworks RTP to provide memory isolation.
However, no matter what I try, I cannot persuade my new RTP project to compile and link.
error: 'sysSymTbl' undeclared (first use in this function)
If I add the correct include:
#include <sysSymTbl.h>
I get:
error: sysSymTbl.h: No such file or directory
and if i just define it extern:
extern SYMTAB_ID sysSymTbl;
i get:
error: undefined reference to `sysSymTbl'
I havent even begun to start trying to stitch in the actual module load code, at the moment I just want to get the symbol lookup working.
So, is the system symbol table accessible from VxWorks RTP applications? Can moduleLoad be used?
EDIT
It appears that what I am trying to do is covered by the Application Programmers Guide in the section on Plugins (section 4.9 for V6.8) (thanks #nos), which is to use dlopen() etc. Like this:
void * hdl= dlopen("pathname",RTLD_NOW);
FUNCPTR func = dlsym(hdl,"FunctionName");
func();
However, i still end up in linker-hell, even when i specify -Xbind-lazy -non-static to the compiler.
undefined reference to `_rtld_dlopen'
undefined reference to `_rtld_dlsym'
The problem here was that the documentation says to specify -Xbind-lazy and -non-static as compiler options. However, these should actually be added to the linker options.
libc.so.1 for the appropriate build target is then required on the target to satisfy the run-time link requirements.

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).

Placing function in .dll causes debug assertion failed error

Hallo fellow members,
I run into a very strange problem today and I am not exactly sure as to what is causing it. Here is a function which I use to get the current working directory :
#ifdef _WIN32
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#error "There is currently no support for non windows based systems!"
#endif
const std::string getCurrentPath()
{
char CurrentPath{_MAX_PATH];
GetCurrentDir(CurrentPath, _MAX_PATH);
CurrentPath[_MAX_PATH - 1] = '/0';
return std::string(CurrentPath);
}
This function works well as a stand alone function. However if I declare it as a static function inside a class :
static __declspec(dllexport) const std::string getCurrentPath(void);
and a .dll I get "debug assertion failed error" when I try to do
std::cout<<CUtilities::getCurrentPath()<<std::endl;
If I instead write :
std::string dir = CUtilities::getCurrentPath();
std::cout<<"Dir is : "<<dir<<std::endl;
it works fine. I am totally confused as to what I am doing wrong. Any ideas?
I finally found out what the problem was. The project was compiled with /MT options , therefore the .dll had a different heap than the original file. So when the string size was bigger than it's initial size (15) then heap was allocated from the .dll's side. However the string had it's destructor called from the main program side and then the destructor was trying to deallocate memory from the .dll's heap thus resulting in "heap corruption error"
The solution was to simply compile with /MD options.