HashMap : Dealing with Managed objects C++ - c++-cli

I guess it's kind of a stupid question but here is my problem :
I want to have a hash_map<int, Object^> as an attribute of my object BigObject, which is written in managed C++.
So I have to declare a pointer, hash_map<int, Object^>* hash because I cannot declare explicitely native object in managed code.
How can I insert an object ? the hash_map[] won't work with a pointer, and I cannot make insert work (I cannot use a std::pair<int, Object^> because Object is managed...
Thanks a lot

You should declare your hashmap as hash_map<int, gcroot<Object^> >. You will need to #include <vcclr.h>
See also msdn
edit: added code sample
#include <iostream>
#include <vcclr.h>
#include <hash_map>
using namespace std;
using namespace stdext;
using namespace System;
int main()
{
hash_map<int, gcroot<Object^> > hash;
hash.insert( make_pair<int, gcroot<Object^> >( 5,
gcnew String("hello world") ) );
return 0;
}

If you're working in .NET, why not use one of the .NET collections? They are directly usable in C++/CLI, and can also be shared with other .NET languages, which a std::hash_map cannot. And they play nicely with the garbage collector.
.NET provides several hashtable implementations, including 'System.Collections.HashTable' and System.Collections.Generic.Dictionary.
In your case, a Dictionary<int, Object^>^ would be appropriate.

hash_map <double,gcroot<siteNEVObjectdic^>> d;
d.insert(make_pair<double,gcroot<siteNEVObjectdic^>>(PN2,gcnew siteNEVObjectdic(Lat1,Long1,Lat2,Long2,Lat3,Long3)));
this worked as a charm.

Related

Attempting to print SerialPort inputs to the console

First my code:
#include <iostream>
#include <thread>
#using <System.dll>
using namespace System;
using namespace System::IO::Ports;
using namespace System::Threading;
int main()
{
SerialPort^ mySerialPort = gcnew SerialPort("COM5");
mySerialPort->BaudRate = 9600;
mySerialPort->Parity = Parity::None;
mySerialPort->StopBits = StopBits::One;
mySerialPort->DataBits = 8;
mySerialPort->Handshake = Handshake::None;
mySerialPort->RtsEnable = true;
while (1)
{
Console::WriteLine(Console::ReadLine());
}
}
The idea was to read from the SerialPort and write to the console. Source
Originally I was going to use:
std::cout << Console::ReadLine() << '\n';
However, that had an error (ReadLine outputs String^ not String, I don't know the difference) and I was hoping for something to compile.
With the above code I received the error:
two-phase name lookup is not supported for C++/CLI ... use /Zc:twoPhase-
The error recommends I use /Zc:twoPhase- which is a compiler option. So I enabled it and got the error:
Element has an invalid value of "Yes(/permissive-) /Zc:twoPhase-"
I'm not quite sure how to proceed from here.
Apologies I'm a beginner and I dove way over my head. Any help would be appreciated!
Note: I included thread, I know this code doesn't use it, but I plan on using it later.
Judging by the "Element has an invalid value of "Yes(/permissive-) /Zc:twoPhase-"" you've put this compiler option where it does not belong. Make sure you know where it should go. E.g. Why do I have warning "C4199 two-phase name lookup is not supported for C++/CLI, C++/CX, or openmp"?
There is no solution. I got an "cannot open file 'MSCOREE.lib'" error. It appears that file no longer exists in Windows and I didn't know how to get ahold of it. So I used the Visual Studio Windows Form App.
Edit: eXCore's comment about the .NET framework solved it.

Insert int variable into the class using LLVM PASS or Clang

I want to insert integer variable into all classes using LLVM PASS or Clang.
How to do this ?
For example..
class foo {
int a;
}
I want to insert new value as below.
class foo {
int a;
unsigned int b; // I want to insert this.
}
How can I do this using LLVM PASS or Clang ?
- I much prefer LLVM PASS.
Thank you very much :)
My recommendation would be to use Clang for this, as LLVM operates on bitcode (IR) and the operation you want is very much C++ related, so why not exploit Clang's knowledge about the AST?
With LibTooling you can write stand-alone tool to do exactly what you want. More specifically, use an AST Matcher to find all C++ class declarations (cxxRecordDecl). You can then insert a new FieldDecl in your callback.
More info: LibTooling and LibASTMatchers Tutorial

Casting System::IO::FileStream^ to FILE*

I am working on refactoring a large amount of code from an unmanaged C++ assembly into a C# assembly. There is currently a mixed-mode assembly going between the two with, of course, a mix of managed and unmanaged code. There is a function I am trying to call in the unmanaged C++ which relies on FILE*s (as defined in stdio.h). This function ties into a much larger process which cannot be refactored into the C# code yet, but which now needs to be called from the managed code.
I have searched but cannot find a definitive answer to what kind of underlying system pointer the System::IO::FileStream class uses. Is this just applied on top of a FILE*? Or is there some other way to convert a FileStream^ to a FILE*? I found FileStream::SafeFileHandle, on which I can call DangerousGetHandle().ToPointer() to get a native void*, but I'm just trying to be certain that if I cast this to FILE* that I'm doing the right thing...?
void Write(FILE *out)
{
Data->Write(out); // huge bulk of code, writing the data
}
virtual void __clrcall Write(System::IO::FileStream ^out)
{
// is this right??
FILE *pout = (FILE*)out->SafeFileHandle->DangerousGetHandle().ToPointer();
Write(pout);
}
You'll need _open_osfhandle followed by _fdopen.
Casting is not magic. Just because the input and types output are right for your situation doesn't mean the values are.

Managed array in VC++

I want to pass a managed array from VB.NET to a function in a VC++ project. How would I declare my C++ function and how would I use the array when I'm inside it? Specifically, I want to make VB compatible functions like the one below, which is written in plain old C.
void Vcopy(double *A, double *B)
{
int n;
for(n=0;n<3;n++)
{
B[n]=A[n];
}
}
Maybe some kind soul could convert this to something that would play nicer with VB. Thanks!
Can the C++ method be managed, e.g., C++/CLI ?
If so, then:
void Vcopy(array<double> ^A, array<double> ^B)
By the way, the rest of the method should be identical, provided that the size is 3 - otherwise use A->Length and B->Length.

How to create a global handle in C++-CLI

I am trying to use a C# class in a C++-CLI project, but Visual Studio will only let me declare a handle (^) to a C# object in a local scope, just inside a function. The only way I got it working was declaring a global pointer to a handle:
SUTAdapter::Form1^ *ptForm1;
But if then I create an object inside a function and give its address to the global pointer:
SUTAdapter::Form1^ form1;
form1 = gcnew SUTAdapter::Form1();
ptForm1 = &form1;
(*ptForm1)->incCounter(0);
When the function exits and I try to use the incCounter function inside some other C++-CLI function, the object seems gone (debugger says this == null). Is there a way to have a global handle of a C# code in C++-CLI? I guess global handles are forbidden for some reason I don't understand but I am out of ideas and I need this done. Thank you.
edit:
*ptForm1 = gcnew SUTAdapter::Form1();
Gives a null reference exception. Why?
This restriction seems consistent with the other CLR-based languages. C# has no concept of a static, function-scoped variable for example. The lack of such functionality in C++/CLI suggests that is the way the CLR works - static objects must be defined at the class scope.
The CLR is object based, so this is just a case of that object-oriented nature influencing the design of languages that run on top of it.
From an OO view point, I like the C# way better anyway.
Ok thanks for your answers but I finally solved it, I found it googling:
http://bytes.com/groups/net-vc/473036-how-define-global-com-object-vc-8-a
It seems that VS doesn't let global handles or static handles inside functions. I am puzzled about this because sometimes it is necessary to access managed objects globally.
The solution is to declare a "GlobalObjects" class with static handles inside it:
ref class GlobalObjects
{
public:
static SUTAdapter::Form1^ hndForm1;
};
This way I can access the C# form/class globally. The error code of the previoous error is C3145, I am still wondering why does not VS allow the declaration of global handles.
Will Visual Studio let you declare a static handle to a C# object in a local scope?
SUTAdapter::Form1^ theForm() {
static SUTAdapter::Form1^ form1 = gcnew SUTAdapter::Form1();
return form1;
}
*ptForm1 = gcnew SUTAdapter::Form1();
Gives a null reference exception because you are dereferncing a null pointer - it is just like a pointer to any other type in that regard.
I think - and that's without testing it - that the problem you're having is because you're storing a pointer to a local handle, which might confuse the garbage collector a little due to the fact that you're taking a pointer to an automatic object.
Have you tried to replace the above assignment with
*ptForm1 = gcnew SUTAdapter::Form1();
instead of the detour via the local object reference?